#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) /* DS18B20 peripherals: */ #define DS18B20_PORT PORTC #define DS18B20_DDR DDRC #define DS18B20_PIN PINC #define DS18B20_DQ PINC3 /* DS18B20 commands: */ #define DS18B20_CMD_CONVERTTEMP 0x44U #define DS18B20_CMD_RSCRATCHPAD 0xBEU #define DS18B20_CMD_WSCRATCHPAD 0x4EU #define DS18B20_CMD_CPYSCRATCHPAD 0x48U #define DS18B20_CMD_RECEEPROM 0xB8U #define DS18B20_CMD_RPWRSUPPLY 0xB4U #define DS18B20_CMD_SEARCHROM 0xF0U #define DS18B20_CMD_READROM 0x33U #define DS18B20_CMD_MATCHROM 0x55U #define DS18B20_CMD_SKIPROM 0xCCU #define DS18B20_CMD_ALARMSEARCH 0xECU //#define TEMP_MIN 0U //#define TEMP_MAX 50U #define MODE_MEASURE 0U #define MODE_ANIMATION_1 1U #define MODE_ANIMATION_2 2U #define ANIMATION_DELAY_MS 70U #define ANIMATION_START_DELAY_MS 70U #define BUTTON_THRESHOLD 50 //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 #define SYM_I 18U #define SYM_SEG_A 19U #define SYM_SEG_B 20U #define SYM_SEG_C 21U #define SYM_SEG_D 22U #define SYM_SEG_E 23U #define SYM_SEG_F 24U #define SYM_SEG_AB 25U #define SYM_SEG_BCD 26U #define SYM_SEG_CD 27U #define SYM_SEG_DE 28U #define SYM_SEG_DEF 29U #define SYM_SEG_AEF 30U #define SYM_SEG_AF 31U /* 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[32U] = { /* 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 /* 18 */ 0b01010000U, //I (EF) SYM_I /* 19 */ 0b10000000U, //SegA SYM_SEG_A /* 20 */ 0b00100000U, //SegB SYM_SEG_B /* 21 */ 0b00000100U, //SegC SYM_SEG_C /* 22 */ 0b00001000U, //SegD SYM_SEG_D /* 23 */ 0b00010000U, //SegE SYM_SEG_E /* 24 */ 0b01000000U, //SegF SYM_SEG_F /* 25 */ 0b10100000U, //SegAB SYM_SEG_AB /* 26 */ 0b00101100U, //SegBCD SYM_SEG_BCD /* 27 */ 0b00001100U, //SegCD SYM_SEG_CD /* 28 */ 0b00011000U, //SegDE SYM_SEG_DE /* 29 */ 0b01011000U, //SegDEF SYM_SEG_DEF /* 30 */ 0b11010000U, //SegAEF SYM_SEG_AEF /* 31 */ 0b11000000U, //SegAF SYM_SEG_AF }; //static uint8_t g_u8WaterTemperature = 24U; //Water temperature, default 24 degree celcius static uint8_t g_u8ButtonCountTop = 0U; //upper button counter static uint8_t g_u8ButtonCountBot = 0U; //lower button counter static uint8_t g_u8Mode = MODE_MEASURE; //Current display mode uint8_t g_u8ISRDigitSelect = 0U; uint8_t g_au8Digits[3U] = { SYM_OFF, //unit SYM_OFF, //ones SYM_OFF //tens }; void s_vInit( void ); void s_vSetValue( uint8_t u8Value, uint8_t u8Unit ); void s_vSetDisplayDigits( uint8_t u8Tens, uint8_t u8Ones, uint8_t u8Unit ); void s_vReadButtons( void ); void s_vShowAnim( uint8_t u8Select ); uint8_t s_u8DS18B20_Reset( void ); void s_vDS18B20_WriteByte( uint8_t u8Byte ); void s_vDS18B20_WriteBit( uint8_t u8Bit ); uint8_t s_u8DS18B20_ReadByte( void ); uint8_t s_u8DS18B20_ReadBit( 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; } /* Read and evaluate button status */ s_vReadButtons(); } /************************************************************************/ /* main() */ /************************************************************************/ int main(void) { uint8_t u8TempLo, u8TempHi; float f32Temperature; uint8_t u8Loop = 0U; /* Init I/O: */ s_vInit(); s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF ); _delay_ms(10); s_vSetDisplayDigits( SYM_SEG_A, SYM_OFF, SYM_OFF ); _delay_ms(300); s_vSetDisplayDigits( SYM_SEG_A, SYM_SEG_A, SYM_OFF ); _delay_ms(300); s_vSetDisplayDigits( SYM_SEG_A, SYM_SEG_A, SYM_SEG_D ); _delay_ms(300); while ( u8Loop < 5U ) { s_vSetDisplayDigits( SYM_OFF, SYM_SEG_A, SYM_SEG_DE ); _delay_ms(ANIMATION_START_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_SEG_DEF ); _delay_ms(ANIMATION_START_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_SEG_AEF ); _delay_ms(ANIMATION_START_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, SYM_SEG_D, SYM_SEG_AF ); _delay_ms(ANIMATION_START_DELAY_MS); s_vSetDisplayDigits( SYM_SEG_D, SYM_SEG_D, SYM_SEG_A ); _delay_ms(ANIMATION_START_DELAY_MS); s_vSetDisplayDigits( SYM_SEG_DE, SYM_SEG_D, SYM_OFF ); _delay_ms(ANIMATION_START_DELAY_MS); s_vSetDisplayDigits( SYM_SEG_DEF, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_START_DELAY_MS); s_vSetDisplayDigits( SYM_SEG_AEF, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_START_DELAY_MS); s_vSetDisplayDigits( SYM_SEG_AF, SYM_SEG_A, SYM_OFF ); _delay_ms(ANIMATION_START_DELAY_MS); s_vSetDisplayDigits( SYM_SEG_A, SYM_SEG_A, SYM_SEG_D ); _delay_ms(ANIMATION_START_DELAY_MS); u8Loop++; } /* Set default value: */ s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF ); while ( 1 ) { /* perform mode action */ switch ( g_u8Mode ) { case MODE_MEASURE: (void) s_u8DS18B20_Reset(); s_vDS18B20_WriteByte( DS18B20_CMD_SKIPROM ); s_vDS18B20_WriteByte( DS18B20_CMD_CONVERTTEMP ); while ( !s_u8DS18B20_ReadBit() ); (void) s_u8DS18B20_Reset(); s_vDS18B20_WriteByte( DS18B20_CMD_SKIPROM ); s_vDS18B20_WriteByte( DS18B20_CMD_RSCRATCHPAD ); u8TempLo = s_u8DS18B20_ReadByte(); u8TempHi = s_u8DS18B20_ReadByte(); f32Temperature = ((u8TempHi << 8) + u8TempLo) * 0.0625; s_vSetValue( (uint8_t) f32Temperature, SYM_DEG_CELCIUS ); if ( g_u8Mode == MODE_MEASURE ) { _delay_ms(500); } break; case MODE_ANIMATION_1: s_vShowAnim(g_u8Mode); g_u8Mode = MODE_MEASURE; break; case MODE_ANIMATION_2: s_vShowAnim(g_u8Mode); g_u8Mode = MODE_MEASURE; break; default: break; } //end switch } return 0; } /************************************************************************/ /* Initialize inputs and outputs */ /************************************************************************/ void s_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_u8ButtonCountTop = 0U; //reset top counter g_u8Mode = MODE_ANIMATION_1; } else if ( g_u8ButtonCountBot > BUTTON_THRESHOLD ) { g_u8ButtonCountBot = 0U; //reset bottom counter g_u8Mode = MODE_ANIMATION_2; } //else //{ //return MODE_MEASURE; //} return; //void } /************************************************************************/ /* */ /************************************************************************/ void s_vShowAnim( uint8_t u8Select ) { s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); switch ( u8Select ) { case MODE_ANIMATION_1: //fade from left to right and from right to left s_vSetDisplayDigits( SYM_I, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_E, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, SYM_I, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, SYM_E, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, 1U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, 3U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, 8U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, 8U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, 3U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, 1U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, SYM_E, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, SYM_I, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_E, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_I, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); break; case MODE_ANIMATION_2: //fade from left to right and clear s_vSetDisplayDigits( SYM_I, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_E, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, SYM_I, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, SYM_E, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, 1U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, 3U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 8U, 8U, 8U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 3U, 8U, 8U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( 1U, 8U, 8U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, 8U, 8U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, 3U, 8U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, 1U, 8U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, SYM_OFF, 8U ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_E ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_I ); _delay_ms(ANIMATION_DELAY_MS); s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); break; default: break; } //end switch s_vSetDisplayDigits( SYM_OFF, SYM_OFF, SYM_OFF ); _delay_ms(ANIMATION_DELAY_MS); return; //void } /************************************************************************/ /* Reset DS18B20 (960 us) */ /************************************************************************/ uint8_t s_u8DS18B20_Reset( void ) { uint8_t u8Status; //low for 480 us DS18B20_PORT &= ~ (1<>= 1U; } return; //void } /************************************************************************/ /* Write single bit to DS18B20 (61 us) */ /************************************************************************/ void s_vDS18B20_WriteBit( uint8_t u8Bit ) { //low for 1 us DS18B20_PORT &= ~ (1U<>= 1U; n |= (s_u8DS18B20_ReadBit()<<7U); } return n; } /************************************************************************/ /* Read single bit from DS18B20 (60 us) */ /************************************************************************/ uint8_t s_u8DS18B20_ReadBit( void ) { uint8_t u8Bit = 0U; //low for 1 us DS18B20_PORT &= ~ (1U<