MyTetra Share
Делитесь знаниями!
Clock with 7-segments ver.3
Время создания: 30.11.2017 14:56
Раздел: Electronics - Microcontrollers - AVR8 - AVR GCC - C_PROJ - Clock 7sgm (blue)

#define F_CPU 8000000L

#define DEVICE (__AVR_ATmega8__)


#include <avr/io.h>

#include <avr/interrupt.h>

#include <stdint.h>


#define uint8_t uint8_t


//#include "my_init.h"

//#include "blinking.c"


//typedef uint8_t uint8_t;


#define NOP asm volatile("NOP"::) //NOP

#define SEI asm volatile("sei"::) //enable interrupts

#define CLI asm volatile("cli"::) //disable interrupts


#define SEGM_DDR DDRC

#define SEGM PORTC //PC1..PC4 - 1..4 segment cathodes

#define CATHODE_MASK 0xE1 //1110.0001 - mask for turning off pins [1..4]

#define SEC_DOTS 0x80 //'mask' for switching on central dots on indicator panel

#define SEGM1_ON SEGM |= (1<<1) //PORTC 1

#define SEGM2_ON SEGM |= (1<<2) //PORTC 2

#define SEGM3_ON SEGM |= (1<<3) //PORTC 3

#define SEGM4_ON SEGM |= (1<<4) //PORTC 4

#define SEGM_OFF SEGM &= CATHODE_MASK

#define SEGM_DDR_OFF SEGM_DDR &= CATHODE_MASK


#define HC595 PORTB

#define DS 0 //data

#define ST 2 //locking

#define SH 1 //clock


//PORTD

#define MR 7 //for 74HC595

#define BUTT1 6 //PORTD6 - button #1

#define BUTT2 5 //PORTD5 - button #2

#define BUTT3 4 //PORTD4 - button #3

#define BUTT_MASK 0x70 //0111.0000

#define BUTTONS_STATE ((PIND) & (BUTT_MASK))

//BUTTONS_MASK

// 0111.0000

// |||button_3

// ||button_2

// |button_1

// MR (74HC595)


#define DATA_HI HC595 |= (1<<DS)

#define DATA_LOW HC595 &= ~(1<<DS)

#define CLK_HI HC595 |= (1<<SH)

#define CLK_LOW HC595 &= ~(1<<SH)

#define LOCK_HI HC595 |= (1<<ST)

#define LOCK_LOW HC595 &= ~(1<<ST)

#define CLEAR_OFF PORTD |= (1<<MR)

#define CLEAR_ON PORTD &= ~(1<<MR)


//for indicator with common cathode

//D0..D7 == A,B,C,D,F,G,DP

#define DIG1 0x06;

#define DIG2 0x5B;

#define DIG3 0x4F;

#define DIG4 0x66;

#define DIG5 0x6D;

#define DIG6 0x7D;

#define DIG7 0x07;

#define DIG8 0x7F;

#define DIG9 0x6F;

#define DIG0 0x3F;


#define CHECKBIT(BYTE,BIT) (BYTE & (1<<BIT)) //check bit setting

//#define CHECKBUTTS(BYTE) (BYTE = PIND & BUTT_MASK)


//configuration modes:

#define MOFF 0 //cfg mode turned off (default)

#define MHOUR_H 1 //changing 1st hour digit

#define MHOUR_L 2 //changing 2nd hour digit

#define MMINUTE_H 3 //changing 1st minute digit

#define MMINUTE_L 4 //changing 2nd minute digit

#define MDAY 5 //changing day

#define MMONTH 6 //changing month

#define MYEAR 7 //changing year

#define MEMPTY 8 //empty function

#define MZERO 9 //changing visibility of zero in hours (exmpl: 01:35 vs 1:35)

#define TIME_FOR_CONFIG 6 //cfg mode will have been working for 6 second after last button pressing


#define ONE_SECOND 0x7A12

#define HALF_SECOND 0x3D09

#define SEC_FOR_TIME 15

#define SEC_FOR_DATE 6


#define BAD_CONTROL 99 //control number for reseting date from 1 not 0


//#define RAZR16

#ifndef RAZR16

#define RAZR 8

#else

#define RAZR 16

#endif


// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

// comment the next #define if you want to disable blinking in cfg mode:

// ------------------------------------------------------------------

#define CONFIGURATION_BLINKING

#ifdef CONFIGURATION_BLINKING

#endif


volatile unsigned int TCNT = 0; //timer overflow


//================================================================================

// INTERNAL INT SECTION

//================================================================================


ISR(TIMER0_OVF_vect)

{

++TCNT;

}


void clearRegState(void);

void sendRegData(const uint8_t data);

uint8_t assignDigit(const uint8_t val);

uint8_t assignSegment(const uint8_t segNu, const uint8_t v1, const uint8_t v2, const uint8_t v3, const uint8_t v4);

uint8_t upClock(uint8_t val, const uint8_t limit, const uint8_t control);

uint8_t calcRemainder(uint8_t val, uint8_t * const rem);


//================================================================================

// FUNCTION SECTION

//================================================================================


int main(void)

{

//====================------------------------------------------------

// INIT SECTION

//====================------------------------------------------------

ACSR |= 1<<ACD; //Disable analog comparator

//Timer0_START

TCCR0 = (TCCR0 | 1<<CS00) | (TCCR0 | 0<<CS01) | (TCCR0 | 0<<CS02); //NO Prescaler

TIMSK |= 1<<TOIE0; //Enable TIMER0 interrupts

//Timer0_END

DDRB = 0x07; //0000.0111 DDRB

DDRC = 0x1E; //0001.1110


DDRD &= ~(BUTT_MASK); //set 0 in DDRD for buttons

PORTD |= BUTT_MASK; //PullUp for buttons

DDRD |= 1 << MR; //pin D7 output for MR bit


SEGM = 0x00; //PORTC off


CLK_LOW;

LOCK_LOW;


clearRegState();


//====================------------------------------------------------

// END of INIT SECTION

//====================------------------------------------------------


uint8_t dotsBlink = 1; //dots state and blinking (1 = dots're active)

uint8_t seconds = 0; //seconds counter

uint8_t minute_h = 5; //minutes counter

uint8_t minute_l = 4;

uint8_t hour_h = 1; //hours counter

uint8_t hour_l = 8;

uint8_t day = 13;

uint8_t month = 3;

unsigned int year = 2017;

uint8_t displayTimer = 0; //timer for switching between clock and date displaying

uint8_t currentDisplay = 0; //0 = HH:MM, 1 = DD.MM, 2 = YYYY

uint8_t buttonPressed = 0; //set if any button pressed

uint8_t buttonState = 0; //0 = no one button is pressed, 1 - pressed

uint8_t cfgMode = 0; //for configuration (1..9)

uint8_t cfgModeTime = 0; //Auto exit from cfg mode after .. seconds

#ifdef CONFIGURATION_BLINKING

uint8_t cfgBlinkState = 1; //1 - digit is turned on

#endif


SEI;


// TCNT = 0; // +8 bytes to programm size!!!!!!!

//############================================---------------------------------------

// ---------------------------------= LOOPED CYCLE =---------------------------------

//############================================---------------------------------------

for(;;)

{

//_____________________IF BUTTON IS PRESSED________________________

//check all buttons

buttonState = BUTTONS_STATE; // check buttons


if( buttonState < BUTT_MASK && buttonPressed == 0 ) // if any button is pressed

{

cfgModeTime = 0; //clear time after any button pressing

displayTimer = 0; //reset timer for changing display

buttonPressed = 1;

if( CHECKBIT(buttonState,BUTT1) == 0)

{

++cfgMode; //if BUTTON 1 - change mode

if(cfgMode == MDAY || cfgMode == MYEAR)

{

// cfgMode = 1;

++currentDisplay;

}

if(cfgMode == 8)

{

currentDisplay = 0;

cfgMode = 0;

cfgModeTime = 0;

}

}

else if( CHECKBIT(buttonState,BUTT2) == 0 && cfgMode > 0) //if BUTTON 2 - depends on mode

{

switch(cfgMode)

{

case 1: hour_h = upClock(hour_h, 2, hour_l); break; //incr hour_h

case 2: hour_l = upClock(hour_l, 9, hour_h); break; //incr hour_l (depends on hour_h)

case 3: minute_h = upClock(minute_h, 5, 0); break; //incr minute_h

case 4: minute_l = upClock(minute_l, 9, 0); break; //incr minute_l

case 5: day = upClock(day, 31, BAD_CONTROL); break; //incr day

case 6: month = upClock(month, 12, BAD_CONTROL); break; //incr month

default: break;

}

}

// else if( CHECKBIT(buttonState,BUTT3) == 0 && cfgMode == 1)

// {

//

// }

}

else if( buttonPressed == 1 && buttonState == BUTT_MASK ) // if all buttons are NOT pressed

{

buttonPressed = 0;

}

//^^^

//_____________________IF BUTTON IS PRESSED________________________


#ifdef CONFIGURATION_BLINKING

if(cfgBlinkState == 0 && TCNT > HALF_SECOND)

{

cfgBlinkState = 1;

}

#endif


//_____________________TIME CALCULATING________________________

//time calculating

if(TCNT > ONE_SECOND)

{

TCNT = 0; //main counter

++seconds; //main clock time

++displayTimer; //

++cfgModeTime; //time of active configuration mode

if(cfgModeTime > TIME_FOR_CONFIG)

{

cfgMode = 0; //turn off cfg mode after X seconds

cfgModeTime = 0;

}

#ifdef CONFIGURATION_BLINKING

if(cfgMode != 0)

cfgBlinkState = 0; //turn off segment for 0.5 sec if in cfg mode

#endif

if(dotsBlink == 0) dotsBlink = 1; //state of two central dots

else {dotsBlink = 0;} //turn off

//_______________________________________

//--== MAIN TIME COUNTING

if(seconds == 60)

{

seconds = 0;

++minute_l;

if(minute_l == 10)

{

minute_l = 0;

++minute_h;

if(minute_h == 6)

{

minute_h = 0;

++hour_l;

if(hour_h < 2 && hour_l == 10)

{

hour_l = 0;

++hour_h;

}

else if(hour_h == 2 && hour_l == 4)

{

hour_l = 0;

hour_h = 0;

++day;

if(day == 31)

{

day = 1;

++month;

if(month == 13)

{

month = 1;

++year;

if(year > 0x270F) year = 0; //0x270f == 9999

}

}

}

}

}

}

}

//___END_OF____________TIME CALCULATING________________________


clearRegState();

//_____________________SHOW TIME OR DATE________________________

//cycle for selecting data and same digital segment:

for(uint8_t segmentNumber = 4; segmentNumber > 0; --segmentNumber)

{

uint8_t temp = 0;

uint8_t data = 0; //74HC595 pins state

// CHANGE DISPLAY between TIME, DATE and YEAR

// if display time has gone

if(currentDisplay == 0 && displayTimer > SEC_FOR_TIME)

{

displayTimer = 0;

currentDisplay = 1;

}

else if(currentDisplay > 0 && displayTimer > SEC_FOR_DATE)

{

if(currentDisplay == 2) currentDisplay = 0;

else currentDisplay = 2;

displayTimer = 0;

}


clearRegState();


//SHOW TIME

if(currentDisplay == 0)

{

temp = assignSegment(segmentNumber, hour_h, hour_l, minute_h, minute_l);

}

//SHOW DAY AND MONTH

else if(currentDisplay == 1)

{

uint8_t day_l;

uint8_t * const pDay_l = &day_l;

uint8_t month_l;

uint8_t * const pMonth_l = &month_l;

uint8_t day_h = calcRemainder(day, pDay_l);

uint8_t month_h = calcRemainder(month, pMonth_l);

temp = assignSegment(segmentNumber, day_h, day_l, month_h, month_l);

}

//SHOW YEAR

else if(currentDisplay == 2)

{

temp = assignSegment(segmentNumber, 2, 0, 1, 7);

}


data = assignDigit(temp);

#ifdef CONFIGURATION_BLINKING

//_____________________________________________

// dont show configurable digit for 0.5 seconds

// while cfgBlinkState == 0:

if(

cfgBlinkState == 0

&&

(

(cfgMode == segmentNumber) ||

(cfgMode == 5 && (segmentNumber == 1 || segmentNumber == 2)) ||

(cfgMode == 6 && (segmentNumber == 3 || segmentNumber == 4))

)

)

data = 0;

#endif

//_____________________________________________

//if needed to turn on two central dots, 7th bit will be added:

if

(

(dotsBlink == 1 && currentDisplay == 0) ||

(segmentNumber == 4 && currentDisplay == 1)

)

{ //two dots : for time, one dot . for date, no dots for year

data |= 1 << 7;

}


SEGM_OFF; //turn off all cathodes

SEGM |= 1 << segmentNumber; //turn on actual cathode


clearRegState();

//_____________________________________________

sendRegData(data); //sending of all 8 bites of data for 74HC595N:

}

}

return 0;

}


void clearRegState(void)

{

CLEAR_ON;

LOCK_HI;

CLEAR_OFF;

LOCK_LOW;

}


void sendRegData(const uint8_t data)

{

uint8_t bit_counter = RAZR;

do

{

DATA_LOW;

CLK_LOW;

if( CHECKBIT(data, --bit_counter) ) //if bit in data == 1

DATA_HI;

CLK_HI;

} while(bit_counter > 0);


CLK_LOW;

LOCK_HI;

LOCK_LOW;

}


uint8_t assignDigit(const uint8_t val)

{

//_____________________________________________

//START of CODE SELECTING block for number:

switch(val)

{

default:

case 0: return DIG0;

case 1: return DIG1;

case 2: return DIG2;

case 3: return DIG3;

case 4: return DIG4;

case 5: return DIG5;

case 6: return DIG6;

case 7: return DIG7;

case 8: return DIG8;

case 9: return DIG9;

}

//END of CODE SELECTING block for number

}


uint8_t assignSegment(const uint8_t segNu, const uint8_t v1, const uint8_t v2, const uint8_t v3, const uint8_t v4)

{

switch(segNu)

{

case 1: return v1;

case 2: return v2;

case 3: return v3;

case 4: return v4;

default: return 0;

}


}


/*

uint8_t upClock(uint8_t val, const uint8_t limit)

{

if(val == limit) return 0;

return ++val;

}

*/


/*

.!!!BAD FUNCTION!!!.

.NEED TO BE CHANGED.


//_____________________________________________

Control byte - it's for checking hour's second digit.

If you need to change low hour number, use high hour number as control number

If you need to change other values, use 0 as control byte.

*/

uint8_t upClock(uint8_t val, const uint8_t limit, const uint8_t control)

{

if(control == 99 && val == limit) return 1; //99 control for date (day and month starts at 1)

else if

(

(val == limit) ||

(control == 2 && val == 3) ||

(control > 3 && control != 99 && val == 1)

)

return 0;

else return ++val;

#if 0

if(control == 2 && val == 3) return 0; //checking for 24 hours format

if(control > 3 && val == 1) return 0;

if(val == limit) return 0;

else return ++val;

#endif

}


uint8_t calcRemainder(uint8_t val, uint8_t * const rem)

{

uint8_t temp = 0;

while(val > 9)

{

val -= 10;

++temp;

}

*rem = val;

return temp;

}

 
MyTetra Share v.0.53
Яндекс индекс цитирования