This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

help: how to setup serial port baud rate using T2

hi, all. I am a new comer to 8051.
It seems that I have problem in generating the baud rate of 19200 for serial port using timer 2. The uC is AT89C52. here is my code:

#include <at89x52.h>
#include <stdio.h>

void SPortISR (void) interrupt 4
{
unsigned char i = 0;
putchar (i);              /* output character i*/
TI = 0;                   /* clear flag */
}

void main (void){
T2CON = 0x34;             /* Set T2 Mode 1  */
RCAP2H = 0xFF;
RCAP2L = 0xEC;            /* RCAP2 = 65516  */
TH2 = RCAP2H;
TL2 = RCAP2L;

SCON = 0x50;              /*set serial port mode 1 */
ES = 1;                   /*Enable Serial Port interrupt*/
EA = 1;                   /*Enable Global Interrupt */
}
Can anyone figure out the problem? How to check the serial port output?
I would also like to know if there is any similar example.
thanks a lot.

Parents
  • u don't have to load TH2 & TL2 with RCAP values. just setting RCAP@H & RCAP2L will do the job. i'd used timer 2 for one of the serial comm applications. i'm just pasting a section of those codes. pls take the needful & ignore the rest.

    codes:

    IE = 0x94;
    TMOD = 0xD1;

    RCAP2H = 0xFF; //->for baud rate setting; 9600bps
    RCAP2L = 0xFA; //->for baud rate setting; 9600bps

    PCON = 0x00; //->for power control - unused.
    SCON = 0x50;

    T2CON = 0x34;

Reply
  • u don't have to load TH2 & TL2 with RCAP values. just setting RCAP@H & RCAP2L will do the job. i'd used timer 2 for one of the serial comm applications. i'm just pasting a section of those codes. pls take the needful & ignore the rest.

    codes:

    IE = 0x94;
    TMOD = 0xD1;

    RCAP2H = 0xFF; //->for baud rate setting; 9600bps
    RCAP2L = 0xFA; //->for baud rate setting; 9600bps

    PCON = 0x00; //->for power control - unused.
    SCON = 0x50;

    T2CON = 0x34;

Children
  • Thanks for your help.
    Now I can send characters to serial port at 18500 baud rate.
    however, I am still not clear about the mechanism.

    1. When I want to send a character, do i need to set TI=1 manually in program code?

    2. When using SBUF = i , no output is observed from Serial Port #1 view window. where i is unsigned char type. Is this statement correct?

    3. If I use C51 function getchar(i), it gives a character 0D, but i is equal to 10(0x0A) in decimal. why?

    If there is any sample code, can I have a look?
    thanks a lot.

  • 1) No. TI is set by the mcu to indicate that the character has been sent and sbuf is ready to accept another character for transmission. If the serial interrupt is enabled TI will call the ISR to be called.

    2) There was a recent thread on what you can see in the serial windows. I don't use the debugger/simulator much so I can't answer your question.

    3) getchar() doesn't take a parameter, it returns whatever is in the receiving sbuf. I imagine it calls _getkey(), I think the default implementation of _getkey() waits for RI to be set.

    The is sample code on this site - you'll have to search.

    In case you hadn't realised there are actually two sbuf registers. One that holds the most recent character received, and one that holds the character to be transmitted. As they exist at the same address you get the received character when you read sbuf, when you write to sbuf the mcu will transmit that character. You cannot read back the character you have placed in sbuf.

    Stefan

  • Hi, Stefan. Thanks for your answer.

    In 2, my words was misleading. I want to know whether i can use SBUF=i in C code. It is supposed to be working, but I observe nothing from the Serial Window #1 when I use it.

    In 3, the function should be putchar(i), sorry about the typing mistake. I think I find out the problem. The printed character in serial port is ASCII character set.

    Below is my code, but it doesnt work.

    #include <at89x52.h>
    #include <stdio.h>
    
    static signed char i = 0;
    
    void SPISR (void) interrupt 4      /* serial port ISR */
    {
    	TI = 0;                 /* clear flag */
    }
    
    void main (void)
    {
    RCAP2H = 0xFF;
    RCAP2L = 0xEC;       /* set 18500 baud rate  */
    T2CON = 0x34;         /* Set T2 Mode 1.
    SCON = 0x50;         /* set serial port mode 1.  */
    IE = 0x90;           /* Enable global & serial port interrupt */
    
    while (1)
      {
    	if(i==20)
    	putchar(i);            /* output character i, */
    	i++;
    	if(i==126)
    	i=0;
    	}
    }
    

    The program works if I place TI=1 at the current location of putchar, and move putchar(i) inside SPISR.
    why?

  • The default implementation of putchar() isn't intended to be used with interrupt driven serial comms. It waits for TI to be set before transmitting a character, but your ISR clears TI, so putchar() hangs.

    If you want to use interrupt driven serial comms with the standard library I/O functions you need to write your own versions of _getkey() and putchar(). The source for Keil's implementations is in the C51\LIB directory. By the way, putchar() translates linefeed characters (0x0a) into CRLF sequences (0x0d, 0x0a).

    Yes, you can use SBUF=i in C code, this is exactly what putchar() does.

    There is an 'interrupt driven serial comms' example somewhere on this site, I suggest you track it down and have a look.

    The basic difference between interrupt driven and non-interrupt driven comms is that with interrupt driven comms the RI and TI flags cause the serial ISR to be called, this will 'preempt' any code outwith the ISR that is looking at these flags. In either case you must reset the flags in software.

    Stefan

  • Hi, Stefan. Thanks for your clear and detail explanation. I am clear on transmit from Serial port, and my program is working now.
    I've learnt a lot from you and Kaushik B. Thanks again.
    ^_^