I have written code to make a digital clock using timer1 and tested with Proteus (an Arduino simulator). That program has been downloaded into an Atmega8 and interfaced to an LCD display. Seconds are being counted perfectly in 1 second duration. But when second, minutes and hours are incremented to greater than 60 I see problems. To limit those value, I have written these instruction:
if (second==60)
{
second=0;
}
But when the seconds reach 59, the LCD shows the next second's value randomly. For example: 59,09,19,29,39,49,59…..99,10,11,12,13,14.
My code:
unsigned int second=0;
unsigned int minute=0;
void init_timer1(void);
int main(void)
{
init_timer1();
sei();
Init_LCD();
while(1)
{
goto_position_X_Y(1,0); //first line first position
sprintf(lcd,"second=%d",second);
Send_A_String(lcd);
goto_position_X_Y(2,0); // second line first position
sprintf(lcd,"minute=%d",minute);
Send_A_String(lcd);
}
}
void init_timer1(void)
{
TCCR1B |=(1<< CS12); // prescaler set 256;new freq=31250;
TCCR1B |=(1<< WGM12);
TCNT1 =0;
OCR1A= 3107; // 16 bit max count value 65535,
TIMSK |=(1<< OCIE1A) ;
}
ISR(TIMER1_COMPA_vect)
{
second++;
if(second==60)
{
second=0;
}
minute=minute+(second/60);
if(minute==60)
{
minute=0;
}
}
can you suggest me that can problem be occurred in lcd's program? Code:
Send_A_String(lcd); function of this instruction.
void Send_A_String(unsigned char*String_data)
{
while (*String _data>0) {
send_A_data(*String_data++) ;
}
}
Best Answer
Actually, it isn't shown "randomly", as you explained yourself later. Noticing that there is a pattern is important to solving this problem. Always look for patterns in your data - they are telling you something.
Based on your description, this is nothing to do with the values held in the actual variable
second
but it is, as you suggested later, purely a display problem. Although you've mentioned the displayed characters in a few places, I'll quote this recent comment of yours:Well done! You found a pattern in the "faulty" displayed data, and that pattern contains the clue to solve this problem.
This is a classic display bug, when:
The result is that, depending on the exact behaviour of the code being used to format the data to send to the display, there can still be some previous output characters left visible on the display. In short - one character can't replace two characters on the display.
At the start of each minute, your output data for the variable
second
is:59, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
etc.Therefore for the first 10 seconds of each minute, you are sending only a single character to that fixed location on your LCD display (you describe it in the code as "first line first position"). That single character is being written to the location where the previous "tens" unit was displayed i.e. where the
5
of59
used to be.That leaves the digit
9
of59
still visible, until it is overwritten by the first output data (10
) which has 2 digits!See this table showing the characters which you send to the LCD display, what you want (intend) it to display, and what it actually displays (which matches your list):
I see two places where you could fix this - either:
Send_A_String()
function, test whether the input string is only a single character and add a leading0
when that occurs. However, I would not do that, as it changes that routine from a general "display what I receive" function, into a function with specific behaviour for this program, which reduces its reusability for the future.Or
If your library
sprintf()
function includes the necessary functionality for "format strings" (some "minimal"sprintf()
versions do not include this) then use:sprintf(lcd,"second=%02d",second);
instead of your original:
sprintf(lcd,"second=%d",second);
That will cause the padding to be with the character
0
instead of spaces (sprintf
"flags") and will cause the output to be a minimum of2
characters (sprintf
"width") - hence the02
in thesprintf()
format string.