#include #include #include #define F_CPU 20000000UL //20 MHz #include /* 7-Segment display: */ #define NUM_DIGITS 3U //3 Digits #define DIGIT_TENS 2U //left #define DIGIT_ONES 1U //middle #define DIGIT_UNIT 0U //right #define SELECT_DIGIT(digit) (1U << digit) #define TEMP_MIN 0U #define TEMP_MAX 50U #define BUTTON_THRESHOLD 50U //software debounce /* Symbol indexes: */ #define SYM_n 10U #define SYM_o 11U #define SYM_E 12U #define SYM_R 13U #define SYM_DEG_CELCIUS 14U #define SYM_P_P 15U #define SYM_OFF 16U #define SYM_DASH 17U /* 7-Segment Layout: A F B G E C D P Pin 7 6 5 4 3 2 1 0 Segment A F B E D C G P */ static uint8_t g_au8Symbols[18U] = { /* 00 */ 0b11111100U, //0 (ABCDEF) /* 01 */ 0b00100100U, //1 (BC) /* 02 */ 0b10111010U, //2 (ABDEG) /* 03 */ 0b10101110U, //3 (ABCDG) /* 04 */ 0b01100110U, //4 (BCFG) /* 05 */ 0b11001110U, //5 (ACDFG) /* 06 */ 0b11011110U, //6 (ACDEFG) /* 07 */ 0b10100100U, //7 (ABC) /* 08 */ 0b11111110U, //8 (ABCDEFG) /* 09 */ 0b11101110U, //9 (ABCDFG) /* 10 */ 0b00010110U, //n (CEG) SYM_n /* 11 */ 0b00011110U, //o (CDEG) SYM_o /* 12 */ 0b11011010U, //E (ADEFG) SYM_E /* 13 */ 0b00010010U, //r (EG) SYM_r /* 14 */ 0b10101101U, //degC (ABCDP) SYM_DEG_CELCIUS /* 15 */ 0b11110011U, //P. (ABEFGP) SYM_P_P /* 16 */ 0b00000000U, //OFF SYM_OFF /* 17 */ 0b00000010U //- (G) SYM_DASH }; static uint8_t g_u8WaterTemperature = 24U; //Water temperature, default 24 degree celcius static uint8_t g_u8CountIncs = 0U; //'+' button counter static uint8_t g_u8CountDecs = 0U; //'-' button counter uint8_t g_u8ISRDigitSelect = 0U; uint8_t g_au8Digits[3U] = { SYM_OFF, //unit SYM_OFF, //ones SYM_OFF //tens }; void vInit( void ); void vSetValue( uint8_t u8Value, uint8_t u8Unit ); void vSetDisplayDigits( uint8_t u8Tens, uint8_t u8Ones, uint8_t u8Unit ); void vReadButtons( void ); void vCalculate( void ); /************************************************************************/ /* Timer1 ISR - show values on display */ /************************************************************************/ ISR ( TIMER1_COMPA_vect ) { PORTB = 0; PORTD = 0; _delay_us(2); PORTB = SELECT_DIGIT(g_u8ISRDigitSelect); PORTD = g_au8Symbols[g_au8Digits[g_u8ISRDigitSelect]]; g_u8ISRDigitSelect++; if (g_u8ISRDigitSelect > 2U) { g_u8ISRDigitSelect = 0U; } } /************************************************************************/ /* main() */ /************************************************************************/ int main(void) { /* Init I/O: */ vInit(); /* Set default value: */ vSetDisplayDigits( SYM_DASH, SYM_DASH, SYM_DASH ); /* wait 3 seconds */ _delay_ms(3000); /* Set default value: */ vSetValue( g_u8WaterTemperature, SYM_DEG_CELCIUS ); while ( 1 ) { vReadButtons(); vCalculate(); _delay_ms(3); } return 0; } /************************************************************************/ /* Initialize inputs and outputs */ /************************************************************************/ void vInit( void ) { /* Port D - Pins 0-7: Outputs */ DDRD = 0b11111111U; /* Port B - Pins 0-2: Outputs */ DDRB = 0b00000111U; /* Port C - Pins 4-5: Inputs with internal Pull-up */ PORTC = 0b00110000U; /* 16-bit TIMER1 in CTC mode * prescaler = 8 * 20 MHz / 8 = 2.5 MHz * Compare value = 2500 => 1 ms IRQ */ TCCR1A = 0U; TCCR1B = (1< BUTTON_THRESHOLD ) { g_u8WaterTemperature++; if ( g_u8WaterTemperature > TEMP_MAX ) { g_u8WaterTemperature = TEMP_MIN; } blChanged = true; g_u8CountIncs = 0U; //reset increment counter } if ( g_u8CountDecs > BUTTON_THRESHOLD ) { if ( g_u8WaterTemperature == TEMP_MIN ) { g_u8WaterTemperature = TEMP_MAX; } else { g_u8WaterTemperature--; } blChanged = true; g_u8CountDecs = 0U; //reset decrement counter } if ( blChanged ) { vSetValue( g_u8WaterTemperature, SYM_DEG_CELCIUS ); } return; //void }