The 7 segment display is now working. The display routine uses 3 most significant bits from Timer2 to select which segment to refresh. Taking the 16MHz crystal and using a prescaler of 1024 we have the following timings for each bit of Timer Counter 2:
TCNT2 = 7 6 5 4 3 2 1 0 | | | | | | | | | | | | | | | +--- = 16.000.000/1014 = 15525 Hz | | | | | | +----- = 15625 / 2 = 17812,5 Hz | | | | | +------- = ~3906 Hz | | | | +--------- = ~1953 Hz | | | +----------- = ~976 Hz | | | +---+------------- = ~488 Hz
The 3 most significant bits from TCNT2 flips at a frequency of about 488Hz. Then, by using this 3 bits as an address for each segment of the display, I have a refresh rate of approximately 488/8 = 61Hz, and all segments will stay ON for the same amount of time, without having to worry about measuring time in code. I simply call a refresh_display( ) function with the segments that shall be on as an argument.
void refresh_display( uint8_t segments) {
uint8_t segment_now = (TCNT2 >> 5);
// turn on/off segment according with state of digit
switch (segment_now) {
case _A: if (segments & (1<<_A) ) _A_ON; else _A_OFF;
break;
case _B: if (segments & (1<<_B) ) _B_ON; else _B_OFF;
break;
case _C: if (segments & (1<<_C) ) _C_ON; else _C_OFF;
break;
case _D: if (segments & (1<<_D) ) _D_ON; else _D_OFF;
break;
case _E: if (segments & (1<<_E) ) _E_ON; else _E_OFF;
break;
case _F: if (segments & (1<<_F) ) _F_ON; else _F_OFF;
break;
case _G: if (segments & (1<<_G) ) _G_ON; else _G_OFF;
break;
case _DP: if (segments & (1<<_DP) ) _DP_ON; else _DP_OFF;
break;
}
}
The macros _A_ON / _A_OFF and so on simply set or reset one bit from one port. This makes my life easy, since not all bits from the display share the same port. Indeed, the bits are spread across ports B, C, and D for making the PCB layout easier.
The results can be seen in the video below. I am using NUM LOCK for advancing the slot.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.