Author Topic: Serial ports creating characters  (Read 7870 times)

Offline ewan

  • Newbie
  • *
  • Posts: 43
    • View Profile
Serial ports creating characters
« on: November 05, 2008, 10:11:29 PM »
I have both ports interconnected so that I can easily check the hardware. The output of port 0 is connected to the input of port 1 and vice versa. I send a char 'A' which is then properly received according to the debugger. I then take whatever was received and add 1 to it (to get a 'B' hopefully). I then send the 'B' out on the other port and again (according to the debugger) the correct character is received. When I say character I mean that ucRx[0] = the character, and ucRx[1] = 0. My problem is that when I attach an oscilloscope to the second output there is not just a 'B' but a 'B' followed by an 'A'.
Code: [Select]
void fnRC531 (TTASKTABLE *)
{
  INTERRUPT_SETUP                 interrupt_setup;
  TTYTABLE                        tInterfaceParameters;
  static QUEUE_HANDLE             SerialPortID0, SerialPortID1;
 
  volatile unsigned char          receive, receive2;
  static unsigned char            FirstTime = TRUE;
 
  unsigned char                   ucRx[RX_BUFFER_SIZE];
  unsigned char                   ucLength;

 
  if (FirstTime == TRUE)
  {
    FirstTime = FALSE;
   
    tInterfaceParameters.Channel                 = 0;
    tInterfaceParameters.ucSpeed                 = SERIAL_BAUD_19200;
    tInterfaceParameters.Rx_tx_sizes.RxQueueSize = RX_BUFFER_SIZE;
    tInterfaceParameters.Rx_tx_sizes.TxQueueSize = TX_BUFFER_SIZE;
    tInterfaceParameters.Task_to_wake            = TASK_RC531;
    tInterfaceParameters.usConfig                = (CHAR_8 | NO_PARITY | ONE_STOP | NO_HANDSHAKE | CHAR_MODE);
   
    SerialPortID0 = fnOpen(TYPE_TTY, FOR_I_O, &tInterfaceParameters);

    tInterfaceParameters.Channel                 = 1;
    tInterfaceParameters.ucSpeed                 = SERIAL_BAUD_19200;
    tInterfaceParameters.Rx_tx_sizes.RxQueueSize = RX_BUFFER_SIZE;
    tInterfaceParameters.Rx_tx_sizes.TxQueueSize = TX_BUFFER_SIZE;
    tInterfaceParameters.Task_to_wake            = TASK_RC531;
    tInterfaceParameters.usConfig                = (CHAR_8 | NO_PARITY | ONE_STOP | NO_HANDSHAKE | CHAR_MODE);
   
    SerialPortID1 = fnOpen(TYPE_TTY, FOR_I_O, &tInterfaceParameters);

    PANPAR = 0;                                                         // return all ADC inputs to GPIO
    DDRAN &= ~PORT_AN_BIT0;                                             // set up direction for opto input
    DDRLD |= PORT_LD_BIT4;                                         // set up direction for opto output
    OPTO_ON();                                                          // needs 1ms to be detected
       
    interrupt_setup.int_type       = PORT_INTERRUPT;                    // identifier when configuring {25} - always initialise
    interrupt_setup.int_handler    = RC531_IRQ_OnInterrupt;             // handling function
    interrupt_setup.int_priority   = (INTERRUPT_LEVEL_1);               // interrupt priority level (this can not be modified for IRQ1..IRQ7 so the value is not really relevant)
    interrupt_setup.int_port_bit   = 1;                                 // The IRQ input connected
    interrupt_setup.int_port_sense = IRQ_RISING_EDGE;                   // Interrupt on this edge
    fnConfigureInterrupt((void *)&interrupt_setup);                     // configure test interrupt
   
    (void) OpenRC();                                                    // pins, speed & reset
    (void) Mf500PcdConfig(); 
    (void) Mf500PcdSetDefaultAttrib();
  }
   
  if (!Q_OPTO())
  {
    lamps (GREEN, OFF);
    lamps (RED, ON);
   
    return;
  }
 
  OpenCard();
 
  receive = ReadCard();
 
  if (receive == MI_OK)
  {
    lamps (GREEN, ON);
    lamps (RED, OFF);
  }
  else
  {
    lamps (GREEN, OFF);
    lamps (RED, ON);
  }
 
  // the output of port 0 is wired to the input of port 1 and vice versa
 
  ucRx[0] = 'A';                                      // send out an 'A'
  ucLength = fnWrite(SerialPortID1, ucRx, 1);         // on port 1
  ucLength = fnRead (SerialPortID0, ucRx, 1);         // read it back from port 0
  ucRx[0] += 1;                                       // make it a 'B'
  ucLength = fnWrite(SerialPortID0, ucRx, 1);         // send it on port 0
  ucLength = fnRead (SerialPortID1, ucRx, 1);         // read it back on port 1
 
 

//  uTaskerStateChange(TASK_RC531, UTASKER_SUSPENDED);  // run task only once for now
 
  return;
}

Another weird one.
Thanks,
Ewan.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Serial ports creating characters
« Reply #1 on: November 05, 2008, 10:39:34 PM »
Hi Ewan

Although probably not a cause of problems - check whether the project has DMA enabled on the UARTs (SERIAL_SUPPORT_DMA in
Code: [Select]
app_hw_m5223x.h). If it does you should also fill out the ucDMAConfig parameters when configuring (otherwise the value will randomly initialise modes).

A possible problem that you have is that the reads return zero length (because the character is still being transmitted). I would thus expect 'A' to be sent on channel 1, the read to not return anything (too soon) and then 'B' is sent by channel 0 (has nothing to do with reception - I would overwrite ucRx[0] after the first transmission so that you can distinguish a read reception). When the first 'A' is received it will wake the task and it will then repeat. This however doesn't explain to me why you see 'B' and then 'A'.

Check that the serial port is not also being used by the demo project (in application.c). If it is, there is an echo on input characters and maybe the other task is actually being woken and echoing.

Beware that the fnRead() will not wait until something is received. You can put a while around it to wait but this is not recommended. It is best to quit the task when you have sent the 'A'. Wait until it is woken to read the input and then send the echo+1, etc. This usually requires a state flag so that you know what you are expecting when entering the task - but this state-event method is usually very suited to communication tasks and protocol.

Note that UART work is usually very easy in the uTasker simulator. You can also install a virtual COM loop back and test everything virtually. I find it saves lots of time (and cables) - see: http://www.utasker.com/forum/index.php?topic=343.0

Regards

Mark

Offline ewan

  • Newbie
  • *
  • Posts: 43
    • View Profile
Re: Serial ports creating characters
« Reply #2 on: November 05, 2008, 11:52:01 PM »
Mark,

Thanks for the pointers. It is true that I was not receiving any characters. Overwriting made that obvious. I then put in a delay for 100ms before each read (just for the hardware testing) but still no joy. Then I thought it would be a good idea to add the following code.
Code: [Select]
    fnDriver(SerialPortID0, (TX_ON | RX_ON), 0);
    fnDriver(SerialPortID1, (TX_ON | RX_ON), 0);
All is working, and now on to other stuff.

Regards and thanks again,

Ewan.