hyperterminal and RTC

Go To Last Post
28 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys, I am trying a real time clock on a STK500 kit. (I know there are multiple projects on this but I just want to learn it from scratch). I am using interrupt based counting using timer1 of Mega16. I want to transmit the time updates to my PC with the USART. So far,I have tested each individual part (the USART, the RTC) and it works just fine. However my problem is I want to display the time on my hyperterminal as follows:

HH:MM:SS

However, my the receive window shows a running display of my time. Here is what I have so far:

//Real time clock program using interrupts with timer 1
//transmit time to PC using Bray's terminal program
#include "clock_header.h"

volatile unsigned char seconds,minutes,hours,days,months,years;
volatile unsigned char transmit_time[8];
volatile unsigned int i;

int main (void)
   {
     rtc_init();

     USART_init();

      timer_init(); //setup timer interrupt to fire every 1s
         while(1)
           {
             go_to_sleep();
            }

    }

void timer_init()
    {
        TIMSK |= (1 << OCIE1A); //enable channel 1A interrupt
        sei(); //enable global interrupts

        TCCR1B |= (1 << CS10) | ( 1 << CS11); //start timer at Fcpu/64

        TCCR1B |= (1 << WGM12);//set up for CTC mode

        OCR1A = 65000; //Value that the micro will compare with current count

     }

ISR(TIMER1_COMPA_vect)
   {
     rtc_op();
   }

   void rtc_init()

      {
         seconds = minutes = hours = days = months = years = 0;
      }

   void USART_update(char array[])
      {
        while ((UCSRA & (1 << UDRE)) == 0) {}; //check is the transmit buffer is full

        for(i=0;i<8;i++)

           {
             UDR = array[i];
             i++;
	      _delay_ms(100);
           }

        } 

   void rtc_op()
      {
        seconds++;
        if (seconds == 60) 
          {
            seconds = 0;
//           PORTB ^= (1 << PA1); //toggle LED if needed on PORTA to check counter
            minutes++;
           }
             if (minutes == 60)
                {
                   minutes=0;
//                 PORTB ^= (1 << PA2);
                   hours++;
                 }
                if(hours == 24)
                   {
                      hours = 0;
             //       PORTB ^= (1 << PA3);
                      days++;
                    }
  //array positions:
  // 0,1 --> hours
  //2 --> :
  //3,4 ---> minutes
  //5 ---> :
  //6,7 ---> seconds

                   transmit_time[7] = seconds / 10;
                   transmit_time[6] = seconds % 10;
                   transmit_time[5] = ':';
                   transmit_time[4] = minutes / 10;
                   transmit_time[3] = minutes % 10;
                   transmit_time[2] = ':';
                   transmit_time[1] = hours / 10;
                   transmit_time[0] = hours % 10;

                    USART_update(transmit_time);
          }

void USART_init() //setup USART in transmit mode
   {
     UCSRB |= (1 << TXEN);  // Turn on the transmission circuitry
     UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes
     UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
     UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
    }

void go_to_sleep()
   {
      sleep_cpu();
   }

I am collecting the timer updates in a character array and then passing it to the USART_update function. What am I missing? Thanks for any help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Always look to see if you have a common subroutine. Write this, and the higher level code just follows automatically.

void USART_putchar(char c)
{
   while ((UCSRA & (1 << UDRE)) == 0) {}; //check is the transmit buffer is full
   UDR = c;                      // send the character
}

void USART_update(char array[])
{
    char i;
    for(i=0;i<8;i++)
        USART_putchar(array[i]);
}

You will be using your UART_putchar() function everywhere. It will never try to send characters too fast because it waits until the UART is ready.

In fact both functions will come in handy for all your programs. But the USART_update() will always do eight characters.

If you add a NUL character to your string, you can use the following on any string.

void USART_putstring(char *s)
{
    while (*s)
        USART_putchar(*s++);
}

and use with: (note that I have enlarged your buffer)

char transmit_time[9];
USART_putstring(transmit_time);

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks, David..
I tried the first part (I changed the loop counter to an int as the compiler gave me a warning for char) and it worked just fine.

For using the string here is what I tried:

//i made my transmit_time char array a string

  transmit_time[8] = '\0';
  transmit_time[7] = seconds / 10;
  transmit_time[6] = seconds % 10;
  transmit_time[5] = ':';
  transmit_time[4] = minutes / 10;
  transmit_time[3] = minutes % 10;
  transmit_time[2] = ':';
  transmit_time[1] = hours / 10;
  transmit_time[0] = hours % 10;
 
//then called my update function
USART_putstring(transmit_time); 

I have also defined the function as you suggested. But there is no output on the hyperterminal window. Do I have to change/add delays to the putchar function?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But seconds, minutes and hours are in binary? You need to add some "+ '0'" offsets to convert binary to displayable ASCII. Though (at a cost of code space) you could be better off using sprintf:

sprintf(transmit_time,"%02d:%02d:%02d", hours, minutes, seconds);

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You do not need any delays at all. The code looks ok to me, but perhaps you could run it through the simulator.

I always use puts("hello"); at the beginning of any program. just after the init() functions e.g.

     USART_init();
     USART_putstring("Clock program");

You do realise that your main() loop does nothing. You appear to call rtc_op() from within your ISR(). This is very unwise. If your ISR() updates the buffer, let the main() do the actual printing. So your main:

    char oldminute;
    while (1) {
        if (minute != oldminute) {
             oldminute = minute;
             USART_putstring(transmit_time);
        }
    } 

You can sort the sleeping out later.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are correct,Cliff I have not converted to ASCII. I will use sprintf.
I was trying to give a task scheduler feel to my program (like a miniOS) where the micro is powered down in main and wakes up only after an interrupt which in this case would be the one second tick.But yes, that's a good suggestion,David and I will try updating in main.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
However my problem is I want to display the time on my hyperterminal as follows:

Code:

HH:MM:SS

However, my the receive window shows a running display of my time. Here is what I have so far:

Neglecting the fact that your display may be showing jibberish due to binary values rather than ASCII characters...

I assume that what you are seeing is something along the lines of (for 12:15:00 time, incrementing by 1 second every time)

12:15:0012:15:0112:15:0212:15:0312:15:0412:15:05

You need some ASCII control characters in your string. These are the carriage return (and often, but not from your description,) the line feed. These are demominated in C style languages as "/r" and "/n" which corrispond to 0x0D and 0x0A.

Append the "/r" on to your output and you will return the cursor to the beginning of the line, and then over write the characters that are already there with new ones. The result will be a stationary indicator that updates just like the LCD on a clock.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok w0067814, thanks for that..I tried the following:

  transmit_time[8] = '\0';
  transmit_time[7] = seconds % 10;
  transmit_time[6] = seconds / 10;
  transmit_time[5] = ':';
  transmit_time[4] = minutes % 10;
  transmit_time[3] = minutes / 10;
  transmit_time[2] = ':';
  transmit_time[1] = hours % 10;
  transmit_time[0] = hours / 10;
 

 sprintf(transmit_time,"%02d:%02d:%02d\r", hours, minutes, seconds);
 USART_putstring(transmit_time);

now I am getting this as the o/p

12:57:49.187> 00:00:20
12:57:49.750> 00:00:21
12:57:50.312> 00:00:22
12:57:50.875> 00:00:23
12:57:51.437> 00:00:24
12:57:52.000> 00:00:25
12:57:52.562> 00:00:26
12:57:53.187> 00:00:27
12:57:53.750> 00:00:28
12:57:54.312> 00:00:29
12:57:54.875> 00:00:30
12:57:55.437> 00:00:31
12:57:56.000> 00:00:32
12:57:56.562> 00:00:33
12:57:57.125> 00:00:34
12:57:57.687> 00:00:35
12:57:58.312> 00:00:36
12:57:58.875> 00:00:37
12:57:59.437> 00:00:38

the string on the left looks like is the time..But I am getting seconds that are repeated.. Why am I getting the string on the right after the > symbol?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Because you need

char transmit_time[10];

You have to count the '\r' and the '\0' .... 2 whole characters.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok i made transmit_time as a char array with 10 elements. Do I have to use strcat to concatenate a '\r' and '\0' to my transmit_time string? I tried the following and that didn't work.

 sprintf(transmit_time,"%02d:%02d:%02d\r\0", hours, minutes, seconds);
 USART_putstring(transmit_time);

I also tried:

transmit_time[9] = '\r';
transmit_time[8] = '\0';
 sprintf(transmit_time,"%02d:%02d:%02d", hours, minutes, seconds);
 USART_putstring(transmit_time);

and that didn't work either. Is there some easier way to append these two characters at the end of my transmit_time string?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When using sprintf() you don't need to insert the terminating \0 - you get one of those thrown in for free (as you do with most of C's string handling functions). However it's your choice as to whether you want a \r

(by the way, in your second example you'd need the two lines setting [8] and [9] AFTER the sprintf and in that case you WOULD need to add the \0 manually)

But is it really \r you want to use? \r means "Return cursor to column one" (also known as "Carriage Return" from the days of teletypes and typewriters). Meanwhile \n means "New line" and will have one of two effects depending on the terminal software you use and how it is configured. If it acts like a "Windows" terminal then it does nothing but move down a line so it may leave the point where the next character appears some characters in from the left margin. If it acts like a "Unix" terminal then \n means both move down one line AND move back to column one. So:

\r moves the output point back to the start of current line so next text written will over-write the text you have written previously.

\n will move down a line (and in Unix to the start of the next line) so the next text appears below the previous

\r\n will ensure (when talking to "Windows") that the text most definitely appears at column one on the line below the current text. If used in Unix then the \r is superfluous as you get one thrown in for free with the \n

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

that's very useful info. Cliff. Thanks.
So I tried the following:

 sprintf(transmit_time,"%02d:%02d:%02d", hours, minutes,seconds);
 transmit_time[10] = '\0';
 transmit_time[9] = '\n';
 transmit_time[8]= '\r';
 USART_putstring(transmit_time);

with this I am getting:

8:21:37.437> 00:01:16
8:21:38.000> 00:01:17
8:21:38.562> 00:01:18
8:21:39.125> 00:01:19
8:21:39.687> 00:01:20
8:21:40.250> 00:01:21
8:21:40.812> 00:01:22
8:21:41.375> 00:01:23

so with a \n and a \r it is giving me the updated values on the new line at the same column.(i am using Bray's terminal with Windows setting).

How do I get it to overwrite the same line every time it updates? So if seconds change then I want the minutes and hours to stay unchanged at the same column and line and only have the seconds refresh.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

How do I get it to overwrite the same line every time it updates?

Just \r *should* achieve that though some terminal programs have a setting for "how to treat CR/0x0D/'\n'" and convert each received 0x0D into \r\n - so that would need to be switched off.

Another way to do this if you really want to jazz this up (and the terminal software supports ASCII escapes) is to output ASCII escapes both for cursor positioning and perhaps even setting colours - you could have hh, mm and ss in red, green and blue if you wanted.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok I tried to play with Bray's terminal and could not see the magic switch anywhere. Any idea where (if at all it exists) it could be? I have even asked Mr.Bray himself but no response yet. I am going to try the inevitable hyperterminal now. Are there any other hyperterminal programs I could try?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Are there any other hyperterminal programs I could try?

My personal fave is Teraterm and in the latest version it has a wide range of settings for CR/LF handling.

I'm using 4.61 which appears to be the latest download at:

http://ttssh2.sourceforge.jp/

(the great thing about this is that it's open source so if there's anything you don't like about the way it works or that you think is missing you can change it):

http://cvs.sourceforge.jp/view/t...

While I've not modified it I have found that useful to look at the source to see how it's doing some things (more than most user manuals offer!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Man, this works like magic on TeraTerm! Finally got my real time clock working. Thanks, guys.. Thanks for the teraterm, Cliff. I may post this in the projects forum..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hyperterminal bashing again. :( If it does not work with Hyperterminal then you are doing something wrong.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

If it does not work with Hyperterminal then you are doing something wrong.

Not on this occasion - Hyperterminal does not offer the same level of control for CR/LF interpretation that TeraTerm does.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Surely the safest way is to program for a bog-standard.

As far as I can see, he has had a problem with inadequate buffer size and whether to use or sequences. He could use a single or a vt100 escape sequence to keep a stationary display.

To rely on configuring a particular terminal program is just adding a complication.

Mind you, I do not like HyperTerminal either.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I agree, David. Just got carried away when the damn thing started working. :)

I have already tried sending a single '\r' but that didn't work. What is a vt100 escape sequence? I noticed that Teraterm had its "Window" settings default to VT100.

Also if I wanted to send these clock ticks to an LCD, will I still need the CR?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

What is a vt100 escape sequence?

Quote:

Another way to do this if you really want to jazz this up (and the terminal software supports ANSI escapes) is to output ANSI escapes both for cursor positioning and perhaps even setting colours - you could have hh, mm and ss in red, green and blue if you wanted.

http://www.termsys.demon.co.uk/v...

For example on the AVR try:

USART_putstring("\x1b[31;47mHello World");

and with any luck something wonderful might happen on the terminal (assuming I typed that right!)

(and yes I corrected by previous use of "ASCII" to "ANSI" - I must be going acronym-blind!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An lcd library has a lcd_gotoxy(char x, char y); function which effectively just sets the printing position.

A VT100 has a similar function. You just send a special sequence of characters e.g.

0x1B, 0x5B, 0x31, 0x32, 0x3B, 0x33, 0x34, 0x48 // "\033[12;34H"

The character hex 0x1B or octal 033 starts the escape sequence. The [ is next and then you have the row 12 and column 34 followed by the letter 'H' which ends the sequence.

Google "VT100 escape sequence" or "Ansi escape sequence"

In the old days each manufacturer used a different format. Now that even a VT100 is out of date, it is still commonly recognised.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My bad, the hyperterminal is working just fine with one CR (no need of VT100).I just had to uncheck the line feed option in the settings dialog.I completely bypassed it and went to Bray assuming that it won't work.

Thanks for the info David I am going to need it for the LCD. John, I need to have more faith in hyperterminal.

I guess the hyperterminal remains unchallenged (although I agree it is more primitive than Teraterm / Bray, but it works). :)

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
John, I need to have more faith in hyperterminal.
After all it is/was good enough for Bill Gates, the richest man in the world. :wink:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi people....
i am transmitting a value 7 from comport of my pc and receiving 37 hex acii equivalent of 7 .is there any way by which i can receive only 7 as values which i transmit may vary...can any one help???

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Look at a table of ASCII codes. 7 is the Bell and you can type a ctl-G to transmit it.

I am sure that Hyperterminal will totally destroy any scheme to send characters like this.

It is always safer to just send regular printing characters like '0', '1', etc. Let your AVR interpret the '7'.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks David. i tried out clrt_G and it is working fine ....actually in my project my micro will be receiving data from comport all hex values e.g (3400) base 16 and i have store it as it as in sram i.e 00 34 (2 bytes) but my micro is receiving it as 33 34 30 30 (3400) (4 bytes) if i am transmitting from hyperterminal or terminal v1.8 by Bray++..and similarly my micro will transmitvalues in hex which i want my terminal to receive as it is. is there any out from this ?? i m using GCC compiler...

Last Edited: Wed. Mar 25, 2009 - 06:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
...what do i do when i want to send 1432...

IIRC holding the Alt button down while pressing the number sequence for each byte you want works too.