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

XC164CS-32 port problems

Hello,

I'm using the XC164CS-32, 40 MHz, and I'm experiencing some problems with the ASC0 port where it seems that its not synchronizing with the program I wrote in C#. The application I wrote will send out at least 6 ASCII characters, but no more than 9.

#define TIMEOUT_100MS                                   31250
#define EBCMOD0_SETTING                                 0x1820
#define EBCMOD1_SETTING                                 0x003F
#define FCONCS1_SETTING                                 0x0031u
#define TCONCS1_SETTING                                 0x0181u
#define ADDRSEL1_SETTING                                0xB000u

#define PORT1_HIGH_DIRECTION_SETTINGS   0x0F
#define PORT1_LOW_DIRECTION_SETTINGS    0xFF
#define PORT3_DIRECTION_SETTINGS                0xB620
#define PORT4_DIRECTION_SETTINGS                0x00FC
#define PORT9_DIRECTION_SETTINGS                0x0001

#define SYS_RDY                                                 P1H_P0


void main(void)
{
char temp_string[9] = "\0"; char label[3] = ""; int i = 0;
ASC0_FDV = 0x003B; /* load ASC0 fractional divider register */ ASC0_BG = 0x000E; /* load ASC0 baud rate time reload register */ ASC0_CON = 0x88D1; /* load ASC0 control register */ DP1L = PORT1_LOW_DIRECTION_SETTINGS; DP1H = PORT1_HIGH_DIRECTION_SETTINGS;
ALTSEL0P3 = 0x2720; ASC0_TIC = 0x01B9u; ASC0_RIC = 0x01F9; DP3 = 0xB620; P3_P10 = 1; P1H_P3 = 0; /* Disable the loopback relays */ ASC0_RXFCON = 0x0607; ASC0_RXFCON = 0x0605; GPT12E_T3CON_T3R = 1; /* Start the timer T3 */ printf ("Initialized\n"); setup(); update();


        while (1)
    {
        if (GPT12E_T3 > TIMEOUT_100_MS)
                {
                        GPT12E_T3 = 0; /* Reset the timer */
                        update();
                }

                  // if ( (ASC0_FSTAT & 0x0F) != 0)
                if ( (ASC0_FSTAT & 0x0F) > 6)
            {

                    gets(temp_string, 9);

                        if (strcmp(temp_string, "status") == 0)
                                printstat();

                        else if (strlen(temp_string) < 8)
                        {
                                printf("sync error. purging RX buffer...\n\n");
                                for (i = 0; i < 100; i++)
                                        ASC0_RBUF = 0x0;

                                ASC0_RXFCON = 0x0607;
                                ASC0_RXFCON = 0x0605;
                        }

                        else
                        {


label[0] = temp_string[6]; label[1] = temp_string[7]; label[2] = '\0';
printf("\nInput: %s \n", temp_string); printf("\nhex label: %s \n",label);
if (strcmp(label,"38") == 0) { // some code }
if (strcmp(label,"72") == 0) { // some code }
if (strcmp(label,"8A") == 0) { // some code }
strcpy(label,""); ASC0_RXFCON = 0x0607; ASC0_RXFCON = 0x0605;
}
}
}

My problem lies in the following IF statement:

if (ASC0_FSTAT & 0x000F) != 0)

For some strange reason, it's not getting the first two characters that I send to it via RS232 and it seems to be some kind of synchronization problem.

I thought I would change the situation by replacing the != 0, but when I try making it greater than 6 (> 6), it will hang and will no received data is coming in.

Does any one see a problem and can help me out?

Steve

Parents
  • Don't use _getkey. It is the function gets calls to read one character. You have eliminated the echoing of the characters but _getkey still clears the receive interrupt flag, which should not be done when using the receive FIFO.

    Don't use printf either (or putchar which printf calls). They do things you don't expect, like check and read a received character when they see a '\r' or '\n'.

    If your application really is such that you don't have to do anything else while waiting for a message from the PC or sending a message to the PC, I recommend polling the serial interface directly yourself, both when receiving and sending. Instead of using printf you can use sprintf, which does exactly and only what it is expected to do.

    Sauli

Reply
  • Don't use _getkey. It is the function gets calls to read one character. You have eliminated the echoing of the characters but _getkey still clears the receive interrupt flag, which should not be done when using the receive FIFO.

    Don't use printf either (or putchar which printf calls). They do things you don't expect, like check and read a received character when they see a '\r' or '\n'.

    If your application really is such that you don't have to do anything else while waiting for a message from the PC or sending a message to the PC, I recommend polling the serial interface directly yourself, both when receiving and sending. Instead of using printf you can use sprintf, which does exactly and only what it is expected to do.

    Sauli

Children
  • Sauli,

    Talk about limiting on what can be done on the serial port!

    Are you suggesting something like this?

    
    while (((char)ASC0_RBUF != '\n') && (count < 11) )
    {
            // read the buffer??
            temp_string[count] = (char)ASC0_RBUF;
            // clear the buffer??
            ASC0_RXFCON = 0x0607;
            count++;
    }
    
    temp_string[count] = '\0';
    
    

    but then that causes a problem because it will NEVER get the rest of the data from the RS232 stream and it's like filling up the first character and ignoring the rest.

    How would you then write something up like this using the FIFO buffer to get the received data?

    Curiously, do you know the size for the Receive buffer?

    Steve

  • Check the datasheet about the registers for the serial port.

    You do not read out a character just to check if there is a character. If there is, then your while loop will loose that character.

    There are specific flags to check if there are one or more characters available to read, and if there is room to insert at least one more character to send. Use them, when polling the serial port.

    And skip the space characters. Just refuse to insert them in your buffer, since you would just have to spend time throwing them away later. If you want to know how many space characters you have received before the actul data, you can count the number of spaces thrown away since the previous newline character was received.

    By the way, your chip does not need to be "warmed up". All it needs is enough time for the crystal to get a stable frequency, and that any used PLL gets time to lock into the correct frequency. Depending on hardware, that takes milliseconds up to maybe a second.

  • You really should figure it out yourself, but you can try out these to prove yourself that the serial interface actually does work. It took me a few minutes to write them and I certainly have not tested them, not even compiled. From experience I know that it is all too easy to put in a mistake in the most simple piece of code.

    unsigned int receive_line( char *buf, unsigned int bufsize)
    {
       unsigned int count;
    
       /* Cannot read anything into a nonexistent or
          zero sized buffer. */
       if( ( buf == NULL) || (bufsize == 0))
       {
          return 0;
       }
    
       /* Must have space for the terminating NUL. */
       bufsize--;
    
       /* Read no more characters than fits in the buffer. */
       for( count = 0; count < bufsize; count++)
       {
          /* Wait for a character. */
          while( (ASC0_FSTAT & 0x0F) == 0)
          {
             ;
          }
    
          /* Read it to the buffer. */
          buf[ count] = ASC0_RBUF;
    
          /* If newline, we are done.
             Newline is not saved. */
          if( buf[ count] == '\n')
          {
             break;
          }
       }
    
       /* Terminate the line. */
       buf[ count] = '\0';
    
       /* Return number of characters read. */
       return count;
    }
    
    void send_line( char *buf)
    {
       /* Cannot send anything from a nonexistent buffer. */
       if( buf != NULL)
       {
          /* While not end of string.. */
          while( *buf != '\0')
          {
             /* Wait for room in the transmit FIFO. */
             while( (ASC0_FSTAT & 0xF00) == 0x800)
             {
                ;
             }
    
    
    /* Send the character. */ ASC0_TBUF = *buf++; } } }

    After you have these working, you could start figuring out how to do it with interrupts. Sooner or later you will want to do something useful with the time wasted in these two routines.

    Sauli