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

/*

08.06.2017


Program: 2030 bytes (24.8% Full)

(.text + .data + .bootloader)


Data: 13 bytes (1.3% Full)

(.data + .bss + .noinit)


Programm was changed and adapted for new red display

with two central dots for seconds and one central

dot at the bottom for DD.MM

ATMEGA8A

__________

(RESET) PC6 -| |- PC5 (ADC5/SCL)

(RXD) PD0 -| |- PC4 (ADC4/SDA)

(TXD) PD1 -| |- PC3 (ADC3)

(INT0) PD2 -| |- PC2 (ADC2)

(INT1) PD3 -| |- PC1 (ADC1)

(XCK/T0) PD4 -| |- PC0 (ADC0)

VCC -| |- GND

GND -| |- AREF

(OSC1) PB6 -| |- AVCC

(OSC2) PB7 -| |- PB5 (SCK)

(T1) PD5 -| |- PB4 (MISO)

(AIN0) PD6 -| |- PB3 (MOSI/OC2)

(AIN1) PD7 -| |- PB2 (SS/OC1B)

(ICP1) PB0 -|__________|- PB1 (OC1A)


*/


#define F_CPU 8000000L

#define DEVICE (__AVR_ATmega8__)


#include <avr/io.h>

#include <avr/interrupt.h>

//#include <stdint.h>


#include "definitions.h"

#include "functionz.c"


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

// GLOBALVARIABLES

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


//volatile uint16_t TCNT = 0; //timer overflow

volatile uint8_t TCNT = 0; //timer overflow

#ifdef MICROPHONE

volatile uint8_t MicSignal = 0; //microphone trigger

#endif


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

// INTERNAL INTERRUPTS SECTION

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

#ifdef MICROPHONE

ISR(INT0_vect)

{

MicSignal = 1;

INT0_DISABLE; //disable INT0 interrupt

}

#endif


ISR(TIMER0_OVF_vect)

{

++TCNT;

}


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

// FUNCTION SECTION

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


int main(void)

{

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

// INIT SECTION

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

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

//Timer0_START

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

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

//Timer0_END

#ifdef MICROPHONE

MCUCR = (MCUCR | 1<<ISC01) | (MCUCR | 0<<ISC00); //falling endge of INT0 generates an interrupt

INT0_DISABLE;

#endif


DDRB = 0x07; //0000.0111 DDRB

DDRC = 0x1E; //0001.1110


DDRC |= 1 << SENSOR_POWER;

SENSOR_POWER_DISABLE;


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

PORTD |= BUTT_MASK; //PullUp for buttons

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


ZUMMER_DDR |= 1 << ZUMMER;

ZUMMER_DIS;


EN_DDR_LIGHT_SENSOR;

EN_PORT_LIGHT_SENSOR;


#ifdef MICROPHONE

MICRO_DDR_CLR;

MICRO_PORT_CLR;

#endif

// MICRO_PORT_SET; //used in programm


CLK_LOW;

LOCK_LOW;


clearRegState();


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

// END of INIT SECTION

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


uint8_t segmentNumber = 4;

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

uint8_t seconds = 55; //seconds counter

uint8_t minutes = 55;

uint8_t hours = 18;

uint8_t day = EEPROM_read(DAY_ADR);

uint8_t month = EEPROM_read(MON_ADR);

uint8_t year_h = EEPROM_read(YEARH_ADR); //first two digits of year

uint8_t year_l = EEPROM_read(YEARL_ADR); //last two digits of year

uint8_t maxDay = 31; //maximum of days in month (limited by 31 or 32 !)

uint8_t leapYear; //1 - leap, 0 - NOT leap

uint8_t alarm = EEPROM_read(ALRM_ST_ADR); //alarm state

uint8_t alarm_minutes = EEPROM_read(ALRM_M_ADR); //minutes for alarm

uint8_t alarm_hours = EEPROM_read(ALRM_H_ADR); //hours for alarm

uint8_t alarmSignalRepeat = 0; //counter of repeats

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 cfgChanges = 0; //bits for checking date and time changes

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

uint8_t checkChangesTCNT0 = 0; //trigger is changed after every T0 interruption

uint8_t checkChangesTCNT = 0;

uint8_t nightMode = 0x00; //last bit for mode activation


if(month > 12 || month < 1) month = 1;

if(year_h > 99) year_h = 0;

if(year_l > 99) year_l = 0;

leapYear = leapYearFoo(year_h, year_l);

maxDay = findMaxDay(month, leapYear);

if(day > maxDay || day < 1) day = 1;

if(alarm_hours > 24) alarm_hours = 0;

if(alarm_minutes > 59) alarm_minutes = 0;


TCNT0 = 0;

SEI;


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

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

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

for(;;)

{

//%%%%%%%%%%%%%%%%%%%%%::::::::::::::::::::::::::::::::::::::

//BIG BLOCK "EVERY SECOND" STARTS

//%%%%%%%%%%%%%%%%%%%%%::::::::::::::::::::::::::::::::::::::


//###########==========------------TO DO EVERY SECOND

if(TCNT == 0x7A && TCNT0 >= 0x12)

{

TCNT = TCNT0 = 0;

++seconds; //main clock time

++displayTimer; //

INVERTBIT(dotsBlink, 0);

SENSOR_POWER_ENABLE;

// ZUMMER_DIS;

//###########==========------------IF CONFIGURATION IS TURNED ON

if(cfgMode)

{

if(displayTimer > TIME_FOR_CONFIG)

{

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

displayTimer = 0;

currentDisplay = 0;

}

else segmentBlinking = 0;

}

//###########==========------------IF SOMETHING WAS CHANGED AFTER CONFIGURATION

else if(cfgChanges) //if time or date was changed and there is no cfgMode

{

//if alarm hours or minutes are changed:

if( CHECKBIT(cfgChanges, CH_ALRM_H) ) EEPROM_write(ALRM_H_ADR, alarm_hours);

if( CHECKBIT(cfgChanges, CH_ALRM_M) ) EEPROM_write(ALRM_M_ADR, alarm_minutes);

//if alarm state is changed:

if( CHECKBIT(cfgChanges, CH_ALRM_ST) ) EEPROM_write(ALRM_ST_ADR, CHECKBIT(alarm, ALARM_STATE) );

//if year is changed:

if( CHECKBIT(cfgChanges, CH_YEARL) ) EEPROM_write(YEARL_ADR, year_l);

if( CHECKBIT(cfgChanges, CH_YEARH) ) EEPROM_write(YEARH_ADR, year_h);

if( CHECKBIT(cfgChanges, CH_YEARL) || CHECKBIT(cfgChanges, CH_YEARH) )

leapYear = leapYearFoo(year_h, year_l); //check for leap year

//if month is changed:

if( CHECKBIT(cfgChanges, CH_MONTH) )

{

maxDay = findMaxDay(month, leapYear); //calculate maximum days in month

EEPROM_write(MON_ADR, month);

}

//if day is changed:

if( CHECKBIT(cfgChanges, CH_DAY) )

{

if(day > maxDay) day = 1; //need to check after month changing by user

EEPROM_write(DAY_ADR, day);

}


cfgChanges = 0;

}


//###########==========------------MAIN TIME COUNTING

if(seconds == 60)

{

// +++++++++++++++-------------

// repeat alarm 3 times every 5 seconds or while it's not switched off

ZUMMER_DIS;

alarm &= ~(1 << ALARM_SIGNAL);

if(alarmSignalRepeat)

{

++alarm;

// if alarm == xxxx.0101 == 5

if( CHECKBIT(alarm, ALARM_REPEAT) && CHECKBIT(alarm, ALARM_REPEAT0) )

{

--alarmSignalRepeat;

alarm |= 1 << ALARM_SIGNAL;

alarm &= 0xF0;

}

if( CHECKBIT(alarm, ALARM_NO_REPEAT) )

{

alarm &= ~(1 << ALARM_NO_REPEAT);

}

}


seconds = 0;

++minutes;

if(minutes == 60)

{

minutes = 0;

++hours;

if(hours == 24)

{

hours = 0;

++day;

if(day > maxDay)

{

day = 1;

++month;

if(month == 13)

{

month = 1;

++year_l;

if(year_l > 0x63) // 0x63 = 99

{

year_l = 0;

++year_h;

if(year_h > 0x63)

{

year_h = 0;

}

cfgChanges |= 1 << CH_YEARH; //save year_h in EEPROM

}

cfgChanges |= 1 << CH_YEARL; //save year_l in EEPROM

}

cfgChanges |= 1 << CH_MONTH; //save month in EEPROM

}

cfgChanges |= 1 << CH_DAY; //save day in EEPROM

}

}

}

//###########==========------------CHANGE DISPLAY

//between TIME, DATE and YEAR if display time has gone

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

{

++currentDisplay;

displayTimer = 0;

}

else if(currentDisplay && displayTimer > SEC_FOR_DATE)

{

if(currentDisplay < 2) ++currentDisplay;

else currentDisplay = 0;

displayTimer = 0;

}


//###########==========------------CHECK LIGHT SENSOR AGAIN

if( CHECKBIT(LIGHT_PIN, LIGHT_SENSOR) )//&& !CHECKBIT(alarm, ALARM_SIGNAL) )

nightMode = NIGHTMODE_WAIT;

else nightMode = NIGHTMODE_OFF;

SENSOR_POWER_DISABLE;

}

//%%%%%%%%%%%%%%%%%%%%%

//BIG BLOCK "EVERY SECOND" ENDS


//%%%%%%%%%%%%%%%%%%%%%::::::::::::::::::::::::::::::::::::::

//BIG BLOCK "TCNT0 CHNGD" STARTS

//%%%%%%%%%%%%%%%%%%%%%::::::::::::::::::::::::::::::::::::::

if(checkChangesTCNT0 != TCNT0)

{

checkChangesTCNT0 = TCNT0;


//###########==========------------IF BUTTON IS PRESSED

uint8_t buttonState = BUTTONS_STATE; // check buttons


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

{

displayTimer = 0; //reset timer for changing display

buttonPressed = 1; //set flag of pressed button


if(cfgMode == MOFF)

currentDisplay = 0; //back to screen with time


//###########==========------------1st BUTTON

// first button works only if there is no alarm signal

if( CHECKBIT(buttonState,BUTT1) == 0 && !CHECKBIT(alarm, ALARM_SIGNAL))

{

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

if(cfgMode == MDAY_H || cfgMode == MYEAR_4)

{

++currentDisplay; //go to the next display

}

else if(cfgMode == MBACK_OFF || cfgMode == MEND ) //set default display

{

currentDisplay = 0;

cfgMode = MOFF;

}

}

//###########==========------------2nd BUTTON

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

{

uint8_t factor = 1;

switch(cfgMode)

{

case 1: factor = 10; //incr hour_h

case 2: hours = incrValue(hours, 24, factor); break; //incr hour_l (depends on hour_h)

case 3: factor = 10; //incr minute_h

case 4: minutes = incrValue(minutes, 60, factor); break; //incr minute_l

case 5: factor = 10;

case 6: day = incrValue(day, maxDay, factor); cfgChanges |= 1 << CH_DAY; break; //incr day

case 7: factor = 10;

case 8: month = incrValue(month, 13, factor); cfgChanges |= 1 << CH_MONTH; break; //incr month

case 9: factor = 10;

case 10: year_h = incrValue(year_h, 100, factor); cfgChanges |= 1 << CH_YEARH; break; //

case 11: factor = 10;

case 12: year_l = incrValue(year_l, 100, factor); cfgChanges |= 1 << CH_YEARL; break; //

case 14: factor = 10; //incr alarm hour_h

case 15: alarm_hours = incrValue(alarm_hours, 24, factor); cfgChanges |= 1 << CH_ALRM_H; break;

case 16: factor = 10; //incr alarm minute_h

case 17: alarm_minutes = incrValue(alarm_minutes, 60, factor); cfgChanges |= 1 << CH_ALRM_M; break;

default: break;

}

if(day == 0) day = 1;

if(month == 0) month = 1;

}

//###########==========------------3rd BUTTON

else if( CHECKBIT(buttonState,BUTT3) == 0)

{

if(cfgMode)

{

currentDisplay = 3; //show time for alarm

cfgMode = MALARM_H_H; //turn on mode for changing alarm time

}

else if(alarmSignalRepeat)

{

if( !CHECKBIT(alarm, ALARM_SIGNAL) )

alarmSignalRepeat = 0; //switch off alarm signals

alarm &= ~(1 << ALARM_SIGNAL);

}

else

{

INVERTBIT(alarm,ALARM_STATE); //turn on or off alarm

alarm &= ~(1 << ALARM_NO_REPEAT);

cfgChanges |= 1 << CH_ALRM_ST; //save the state in EEPROM

}

}

}

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

{

buttonPressed = 0;

}


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

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

if( CHECKBIT(alarm, ALARM_STATE) &&

!CHECKBIT(alarm, ALARM_NO_REPEAT) &&

minutes == alarm_minutes &&

hours == alarm_hours )

{

alarm |= 1 << ALARM_NO_REPEAT;

alarm |= 1 << ALARM_SIGNAL; //switch on alarm signals

alarmSignalRepeat = ALARM_REPEATS;

}


//switch on blinking if

if( CHECKBIT(alarm, ALARM_SIGNAL) ) //if it's alarm

{

currentDisplay = 0; //show time display

displayTimer = 0; //don't switch to other displays

segmentBlinking = 0; //switch on blinking

cfgMode = 0; //disable configuration mode

if( TCNT < 0x3D )

{

ZUMMER_EN;

}

}


//###########==========------------SHOW BLINKING

//in CONFIGURATION MODE or WHILE ALARM IS WORKING

//if( TCNT > HALF_SECOND )

if( TCNT > 0x3D )

{

segmentBlinking = 1;

ZUMMER_DIS;

}


//###########==========------------FOR NIGHT MODE

if(checkChangesTCNT != TCNT)

{

checkChangesTCNT = TCNT;

if(nightMode == NIGHTMODE_WAIT)

nightMode = NIGHTMODE_ON;

}


//%%%%%%%%%%%%%%%%%%%%%//%%%%%%%%%%%%%%%%%%%%%::::::::::::::::::::::::::::::::::::::

//BIG BLOCK "DISPLAY" STARTS

//%%%%%%%%%%%%%%%%%%%%%//%%%%%%%%%%%%%%%%%%%%%::::::::::::::::::::::::::::::::::::::


//###########==========------------SHOW TIME OR DATE

if( nightMode != NIGHTMODE_WAIT )

{

//cycle for selecting data and same digital segment:

if(segmentNumber == 4)

{

segmentNumber = 1;

if( nightMode > NIGHTMODE_WAIT ) --nightMode;

}

else ++segmentNumber;


uint8_t data = 0; //74HC595 pins state

uint8_t indic = 0;

uint8_t segment_1 = 0;

uint8_t segment_2;

uint8_t * const pSegm2 = &segment_2;

uint8_t segment_3 = 0;

uint8_t segment_4;

uint8_t * const pSegm4 = &segment_4;


uint8_t funcArg1 = hours;

uint8_t funcArg3 = minutes;


switch(currentDisplay)

{

case 0: break;

case 1: funcArg1 = day; funcArg3 = month; break;

case 2: funcArg1 = year_h; funcArg3 = year_l; break;

case 3: funcArg1 = alarm_hours; funcArg3 = alarm_minutes; break;

default: break;

}

segment_1 = calcRemainder(funcArg1, pSegm2);

segment_3 = calcRemainder(funcArg3, pSegm4);


data = assignSegment(segmentNumber, segment_1, segment_2, segment_3, segment_4);

data = assignDigit(data);


//switch off segment in cfg mode or while alarming

if(

segmentBlinking == 0

&&

(

cfgMode == segmentNumber ||

cfgMode == segmentNumber + 4 ||

cfgMode == segmentNumber + 8 ||

cfgMode == segmentNumber + 13 ||

CHECKBIT(alarm, ALARM_SIGNAL) //if alarm is working

)

)

{

data = 0;

}


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

if

(

// 2 central dots

(segmentNumber == 2 &&

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

currentDisplay == 3 ||

CHECKBIT(alarm, ALARM_SIGNAL) ))

||

// 1 bottom dot

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

)

{

data += SEC_DOTS;

}


//switch on alarm indication

if

(

currentDisplay == 3 || (

CHECKBIT(alarm, ALARM_SIGNAL) ||

(alarmSignalRepeat && dotsBlink) ||

(!alarmSignalRepeat && CHECKBIT(alarm, ALARM_STATE) ))

)

{

ALARM_INDICAT_ON;

}


switch(currentDisplay)

{

case 0: TIME_INDICAT_ON; break;

case 1: DATE_INDICAT_ON; break;

case 2: YEAR_INDICAT_ON; break;

default: break;

}


SEGM_OFF; //turn off all cathodes

clearRegState();

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

sendRegData(indic); //data for switching LED indicators

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

LOCK_HI;

LOCK_LOW;

}

else

clearRegState(); //skip indication in night mode

//%%%%%%%%%%%%%%%%%%%%%//%%%%%%%%%%%%%%%%%%%%%

//BIG BLOCK "DISPLAY" ENDS

}

//%%%%%%%%%%%%%%%%%%%%%

//BIG BLOCK "TCNT0 CHNGD" ENDS

}

return 0;

}

Так же в этом разделе:
 
MyTetra Share v.0.53
Яндекс индекс цитирования