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

Serial i/o programming using keil c

Hi. I'm working on a project involving a java program and the micro controller NXP P89v664.

The java program which utilises the RXTX package, outputs to the serial port a string of characters to be deciphered by the micro controller.

My java program is completed and outputs correctly as checked by virtual com ports and a c program.

I have written a keil c program to receive the input but I somehow receive random inputs instead.

I used the _getkey() fuction to receive the input and putchar() function to check the output.

I'm new to keil c can anyone shed some light on this pls?

Thanks.

  • "My java program ... outputs correctly as checked by virtual com ports and a c program"

    How have you verified that the 'C' program is correct?

    "I have written a keil c program to receive the input but I somehow receive random inputs instead."

    Is the serial port configured correctly - baud rate, parity, etc...?

  • I'm rather positive that the output from the java program is correct as i'm able to println the outputs from netbeans and check using external programs as well.

    The baudrate is set to 9600, no parity bit and 8 data bits.

    I'm using timer 1 mode 2 to generate the baudrate. But what i'm not sure is, if the baud rate mismatches am i able to receive input at all? I tried to change my baudrate to something else and i could not receive any input from the serial.

  • Always good to have your microcontroller try to send a couple of characters. Then you can measure the baudrate with an oscilloscope just to make sure that you don't have any computation errors. Large errors would result in constantly broken characters being received but switching two digits could result in baudrate errors that just make every 100 character fail.

    So the baudrate should always be verified my actually measuring the data rate.

  • Always good to have your microcontroller try to send a couple of characters. Then you can measure the baudrate with an oscilloscope just to make sure that you don't have any computation errors
    Constantly transmitting uppercase U is excellent for this purpose, a properly coded UART will generate a a square vawe with the frequency of baudrate/2

    Erik

  • But have you verified that its actual output from a physical COM port is correct?

    If you've messed up your physical COM port configuration or handling, then "internal" tests in the PC (such as virtual COM ports) may not show that...

  • Hi All. Thanks for the replies. I will test the output from an oscilloscope soon. However i do suspect that my formula for calculating the baudrate is at fault.

    I lifted this code for initializing the serial port and setting baudrate to 9600

    void com_initialize (void)
    { /*------------------------------------------------
    Setup TIMER1 to generate the proper baud rate.
    ------------------------------------------------*/
    com_baudrate (9600);

    /*------------------------------------------------
    Clear com buffer indexes.
    ------------------------------------------------*/
    EA = 0; /* Disable Interrupts */

    t_in = 0;
    t_out = 0;
    t_disabled = 1;

    r_in = 0;
    r_out = 0;

    /*------------------------------------------------
    Setup serial port registers.
    ------------------------------------------------*/
    SM0 = 0; SM1 = 1; /* serial port MODE 1 */
    SM2 = 0;
    REN = 1; /* enable serial receiver */

    TI = 0; /* clear transmit interrupt */
    RI = 0; /* clear receiver interrupt */

    ES0 = 1; /* enable serial interrupts */
    PS0 = 0; /* set serial interrupts to low priority */

    EA = 1; /* Enable Interrupts */
    }

    void com_baudrate (unsigned baudrate)
    { EA = 0; /* Disable Interrupts */

    /*------------------------------------------------
    Clear transmit interrupt and buffer.
    ------------------------------------------------*/ TI = 0; /* clear transmit interrupt */ t_in = 0; /* empty transmit buffer */ t_out = 0; t_disabled = 1; /* disable transmitter */

    /*------------------------------------------------
    Set timer 1 up as a baud rate generator.
    ------------------------------------------------*/ TR1 = 0; /* stop timer 1 */ ET1 = 0; /* disable timer 1 interrupt */

    PCON |= 0x80; /* 0x80=SMOD: set serial baudrate doubler */

    TMOD &= ~0xF0; /* clear timer 1 mode bits */ TMOD |= 0x20; /* put timer 1 into MODE 2 */

    TH1 = (unsigned char) (256 - (18432000 / (16L * 12L * baudrate))); //18432000=Crystal freq set in the project options

    TR1 = 1; /* start timer 1 */

    EA = 1; /* Enable Interrupts */
    }

    Thanks for the help everyone!

  • Check it here: http://www.keil.com/c51/baudrate.asp

    Then start with a simple "Hello, World" embedded application sending to the serial port, and check that Hyperterminal (or whatever) received the output correctly...

    And pay attention to the clearly-stated instructions for posting source code:

    www.danlhenry.com/.../keil_code.png

  • TH1 = (unsigned char) (256 - (18432000 / (16L * 12L * baudrate))); //18432000=Crystal freq set in the project options.
    


    Interesting line. So you want 16 and 12 to be long constants. But does 18432000 seem like it fits in a 16-bit int?

  • Hi. I have checked the value and used the value TH1=0xF6 but the results are the same. I'm receiving funny stuff from the micro controller like before.

    I used a simple program to test but the results are the same as my other program.

    SEND: 0x01 0x02 0x03 0x04
    RECEIVE: 0xFD 0xFB 0xFB 0xF7

  • Hi. Can you send me more examples of your output that is generated?
    Send ...
    Receive...

  • Hi everyone. Sorry for the late reply. Have been testing with different crystals and baudrate.

    Microcontroller: NXP P89v664
    Flash Program: Flash Magic

    Crystal: 14.74756
    Baud: 38400
    TH1: 0xFE

    Results in hyper terminal:

    Input: 0 1 2 3 4 5 6 7 8 9
    Output: ðþ ñþ òþ óþ ôþ õþ öþ ÷þ øþ ùþ

    Results in another program:

    Input(HEX): 01 02 03 04 05 06 07 08 09 10 20 30 40
    Output(HEX): E1 E2 E3 E4 E5 E6 E7 E8 E9 F0 E0FE(Sometimes FE) F0FE(Sometimes FE) E0FF(Sometimes FF)

    Input(HEX): 81 82 83 84 85 86 87 88 89 90 A0
    Output(HEX): E1 E2 E3 E4 E5 E6 E7 E8 E9 F0 E0FE(Sometimes FE)

    Input(HEX): D1 D2 D3 E1 E2 E3 E4 E5 E6 E7 E8 E9 F0 F1 F2 F3
    Output(HEX): F1 F2 F3 E1 E2 E3 E4 E5 E6 E7 E8 E9 F0 F1 F2 F3

  • Using this code:

    /*------------------------------------------------------------------------------
    MAIN.C:  Interrupt Driver SIO Using printf.
    
    Copyright 1995-2002 KEIL Software, Inc.
    ------------------------------------------------------------------------------*/
    
    #include <reg51.h>
    #include <stdio.h>
    #include "sio.h"
    
    /*------------------------------------------------------------------------------
    _getkey waits until a character is received from the serial port.  This may not
    be the exact desired operation (for example if the buffer is empty, this
    function hangs waiting for a character to be received).
    ------------------------------------------------------------------------------*/
    char _getkey (void)
    {
    int k;
    
    do
      {
      k = com_getchar ();
      }
    while (k == -1);
    
    return ((unsigned char) k);
    }
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    char putchar (char c)
    {
    volatile unsigned int i;
    
    while (com_putchar (c) != 0)
      {
      for (i=0; i<1000; i++)
        {
        /*** DO NOTHING ***/
        }
      }
    
    return (c);
    }
    
    /*------------------------------------------------------------------------------
    Note that the two function above, _getkey and putchar, replace the library
    functions of the same name.  These functions use the interrupt-driven serial
    I/O routines in SIO.C.
    ------------------------------------------------------------------------------*/
    code char message [] =
      "This is a test to see if the interrupt driven serial I/O routines really work.";
    
    void main (void)
    {
    com_initialize ();              /* initialize interrupt driven serial I/O */
    com_baudrate (38400);            /* setup for 1200 baud */
    
    EA = 1;                         /* Enable Interrupts */
    
    //printf ("Interrupt-driver Serial I/O Example\r\n\r\n");
    
    while (1)
      {
      unsigned char c;
    
     //printf ("Press a key.\r\n");
      c = _getkey();
            putchar(c);
    
     // printf ("\r\n");
    // printf ("You pressed '%c'.\r\n\r\n", c);
      }
    }
    
    

  • /*------------------------------------------------------------------------------
    SIO.C:  Serial Communication Routines.
    
    Copyright 1995-2002 KEIL Software, Inc.
    ------------------------------------------------------------------------------*/
    
    #include <reg51.h>
    #include <string.h>
    #include "sio.h"
    
    /*------------------------------------------------------------------------------
    Notes:
    
    The length of the receive and transmit buffers must be a power of 2.
    
    Each buffer has a next_in and a next_out index.
    
    If next_in = next_out, the buffer is empty.
    
    (next_in - next_out) % buffer_size = the number of characters in the buffer.
    ------------------------------------------------------------------------------*/
    #define TBUF_SIZE   2           /*** Must be one of these powers of 2 (2,4,8,16,32,64,128) ***/
    #define RBUF_SIZE   8           /*** Must be one of these powers of 2 (2,4,8,16,32,64,128) ***/
    
    #define TBUF_SPACE  idata       /*** Memory space where the transmit buffer resides ***/
    #define RBUF_SPACE  idata       /*** Memory space where the receive buffer resides ***/
    
    #define CTRL_SPACE  data        /*** Memory space for the buffer indexes ***/
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    #if TBUF_SIZE < 2
    #error TBUF_SIZE is too small.  It must be larger than 1.
    #elif TBUF_SIZE > 128
    #error TBUF_SIZE is too large.  It must be smaller than 129.
    #elif ((TBUF_SIZE & (TBUF_SIZE-1)) != 0)
    #error TBUF_SIZE must be a power of 2.
    #endif
    
    #if RBUF_SIZE < 2
    #error RBUF_SIZE is too small.  It must be larger than 1.
    #elif RBUF_SIZE > 128
    #error RBUF_SIZE is too large.  It must be smaller than 129.
    #elif ((RBUF_SIZE & (RBUF_SIZE-1)) != 0)
    #error RBUF_SIZE must be a power of 2.
    #endif
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    static TBUF_SPACE unsigned char tbuf [TBUF_SIZE];
    static RBUF_SPACE unsigned char rbuf [RBUF_SIZE];
    
    static CTRL_SPACE unsigned char t_in = 0;
    static CTRL_SPACE unsigned char t_out = 0;
    
    static CTRL_SPACE unsigned char r_in = 0;
    static CTRL_SPACE unsigned char r_out = 0;
    
    static bit ti_restart = 0;  /* NZ if TI=1 is required */
    
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    static void com_isr (void) interrupt 4
    {
    /*------------------------------------------------
    Received data interrupt.
    ------------------------------------------------*/
    if (RI != 0)
      {
      RI = 0;
    
      if (((r_in - r_out) & ~(RBUF_SIZE-1)) == 0)
        {
        rbuf [r_in & (RBUF_SIZE-1)] = SBUF;
        r_in++;
        }
      }
    
    /*------------------------------------------------
    Transmitted data interrupt.
    ------------------------------------------------*/
    if (TI != 0)
      {
      TI = 0;
    
      if (t_in != t_out)
        {
        SBUF = tbuf [t_out & (TBUF_SIZE-1)];
        t_out++;
        ti_restart = 0;
        }
      else
        {
        ti_restart = 1;
        }
      }
    
    }
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    #pragma disable
    
    void com_initialize (void)
    {
    /*------------------------------------------------
    Setup TIMER1 to generate the proper baud rate.
    ------------------------------------------------*/
    com_baudrate (1200);
    
    /*------------------------------------------------
    Clear com buffer indexes.
    ------------------------------------------------*/
    t_in = 0;
    t_out = 0;
    
    r_in = 0;
    r_out = 0;
    
    /*------------------------------------------------
    Setup serial port registers.
    ------------------------------------------------*/
    SM0 = 0; SM1 = 1;   /* serial port MODE 1 */
    SM2 = 0;
    REN = 1;            /* enable serial receiver */
    
    RI = 0;             /* clear receiver interrupt */
    TI = 0;             /* clear transmit interrupt */
    ti_restart = 1;
    
    ES = 1;             /* enable serial interrupts */
    PS = 0;             /* set serial interrupts to low priority */
    }
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    #pragma disable
    
    void com_baudrate (
      unsigned baudrate)
    {
    /*------------------------------------------------
    Clear transmit interrupt and buffer.
    ------------------------------------------------*/
    TI = 0;             /* clear transmit interrupt */
    t_in = 0;           /* empty transmit buffer */
    t_out = 0;
    
    /*------------------------------------------------
    Set timer 1 up as a baud rate generator.
    ------------------------------------------------*/
    TR1 = 0;            /* stop timer 1 */
    ET1 = 0;            /* disable timer 1 interrupt */
    
    PCON |= 0x80;       /* 0x80=SMOD: set serial baudrate doubler */
    
    TMOD &= ~0xF0;      /* clear timer 1 mode bits */
    TMOD |= 0x20;       /* put timer 1 into MODE 2 */
    
    TH1 = 0xFE;//(unsigned char) (256 - (XTAL / (16L * 12L * baudrate)));
    
    TR1 = 1;            /* start timer 1 */
    }
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    #pragma disable
    
    char com_putchar (
      unsigned char c)
    {
    /*------------------------------------------------
    If the buffer is full, return an error value.
    ------------------------------------------------*/
    if (com_tbuflen () >= TBUF_SIZE)
      return (-1);
    
    /*------------------------------------------------
    Add the data to the transmit buffer.  If the
    transmit interrupt is disabled, then enable it.
    ------------------------------------------------*/
    tbuf [t_in & (TBUF_SIZE - 1)] = c;
    t_in++;
    
    if (ti_restart)
      {
      ti_restart = 0;
      TI = 1;               /* generate transmit interrupt */
      }
    
    return (0);
    }
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    #pragma disable
    
    int com_getchar (void)
    {
    if (com_rbuflen () == 0)
      return (-1);
    
    return (rbuf [(r_out++) & (RBUF_SIZE - 1)]);
    }
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    #pragma disable
    
    unsigned char com_rbuflen (void)
    {
    return (r_in - r_out);
    }
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    #pragma disable
    
    unsigned char com_tbuflen (void)
    {
    return (t_in - t_out);
    }
    
    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/