Search Microcontrollers

Saturday, October 13, 2012

C2000 Piccolo - Serial communications

I was actually tempted to dig into the ADC functionality, however serial communications seemed to be a higher priority thing to learn.
Why?
Let's face it : we (normally) do not have a screen where we can output some debug information, our best bet with microcontrollers is the UART and use a terminal program on a PC to visualize some data.

As I already anticipated in a previous post, the serial interface is handled quite at "high level" with the C2000, in a similar way you would deal with it on a PC.
First of all , in the C2000 the uart is referred a SCI (Serial Communication Interface) and since there is a single module "A", it normally becomes SCI-A or SCIA.

I am starting to look around the SCIA using the demo program tha comes with the c2000 Launchpad, unfortunately that one does not cover the RX part, and therefore all the interrupt handling is not covered either.
We will need to look somewhere else for that.

One interesting thing to notice is that the uart has double buffered RX and TX functions which is kind of neat.
Unfortunately it looks like that a single hardware uart is supported in the piccolo (some devices may support  SCI-B), which is a pity since at least two serial ports are always handy, typically you would use one to communicate with a device and the other one to debug whatever you need with a PC.
At least this is what I normally do.
It should be possible and quite easy to setup a software uart if needed, I hope.

Another thing I noticed is that it looks like there is no hardware flow control functionality provided, no big deal probably as a couple of gpio lines could be eventually used for that, after all that's the beauty of dealing with an mcu.

So, this said, we expect to have only two pins to deal with :   RX and TX.
In fact they are accessible from the Launchpad expansion headers

(from the C2000 Launchpad pdf, by TI)


SCIRXDA (RX) is available on J1.3 (mode 1), J2.2 (mode 2), J2.9 (mode 2)
SCITXDA (TX) on J1.4 (mode 1), J1.7 (mode 2), J2.3 (mode 2)

J1.4 (mode 1) means header J1, pin 4 and MUX mode set to 1

Now, the pdf that came with the Launchpad explains that the board has an FTDI interface to which, by default, the serial communications are redirected.
That makes them available through the USB port.
The Switch S4 connects and disconnects the uart from the ftdi, so, normally, if you want to use the ttl uart signals (3.3V tolerant) you are supposed to switch S4 so that they are isolated from the USB.

But then I am wondering :
According to the Launchpad schematics, S4 connects and disconnects J1.3 and J1.4   (GPIO28 and GPIO29), which would mean that if we use another combination (i.e. the J2.2/3 option) normally we would be isolated from the USB.
That's something I will probably test later.

Let's start simple and imagine we want to connect the SCIA to the usb/ftdi, then we will have the S4 switch set to ON and configure properly the GPIO28 and 29 pin on the mcu.

The demo program has it all in this case :


    GPIO_setPullUp(myGpio, GPIO_Number_28, GPIO_PullUp_Enable);
    GPIO_setPullUp(myGpio, GPIO_Number_29, GPIO_PullUp_Disable);

    GPIO_setQualification(myGpio, GPIO_Number_28, GPIO_Qual_ASync);

    GPIO_setMode(myGpio, GPIO_Number_28, GPIO_28_Mode_SCIRXDA);
    GPIO_setMode(myGpio, GPIO_Number_29, GPIO_29_Mode_SCITXDA);


The RX is going to be configured as input (implicitly, that's done automatically when setting the pin to uart mode).
To avoid floating signals the pullup  resistor is enabled.
TX is obviously output, therefore pull resistors are not used.
The setQualification part is related to synchronizing and qualifying the signal with the internal clock.
I will not enter too much in the details here, but let's just say that if a signal uses a clock that is not defined internally (this is the case for the RX signal whose clock depends on the other device on the communication line), then it needs to be synchronized with the internal clock to detect the gap with it.
A number of samples (configurable) is taken and a high frequency clock (SYSCLK or a divided value) is used to assess the gap.
The process is described in the 2802X_system manual.

The final two lines set the MUX  mode for GPIO28 and 29 pins, the GPIO_28_Mode_SCIRXDA and GPIO_29_Mode_SCITXDA are two enum constants (value = 1).

If instead we would have preferred to use the J2 option (GPIO19 = RX, GPIO12 =TX) the needed code would have been :


    GPIO_setPullUp(myGpio, GPIO_Number_19, GPIO_PullUp_Enable);
    GPIO_setPullUp(myGpio, GPIO_Number_12, GPIO_PullUp_Disable);

    GPIO_setQualification(myGpio, GPIO_Number_19, GPIO_Qual_ASync);

    GPIO_setMode(myGpio, GPIO_Number_19, GPIO_19_Mode_SCIRXDA);
    GPIO_setMode(myGpio, GPIO_Number_12, GPIO_12_Mode_SCITXDA);


And presumably the S4 switch would not affect at all, however, before connecting a ttl serial device to them, I would make sure that GPIO28 and 29 are NOT configured as SCIA at the same time (!!).

Now that we have the pin configured properly, let's take a look to the function that configures the SCIA peripheral (still from the demo software)


 mySci = SCI_init((void *)SCIA_BASE_ADDR, sizeof(SCI_Obj));

This line initializes a SCI handler, which will be used later.

void scia_init()
{
    CLK_enableSciaClock(myClk);

We also initialized and configured properly the clock (check this other post for details) , now we are using the myClk handler to enable the clock for the SCI peripheral

    SCI_disableParity(mySci);
    SCI_setNumStopBits(mySci, SCI_NumStopBits_One);
    SCI_setCharLength(mySci, SCI_CharLength_8_Bits);
    
    SCI_enableTx(mySci);
    SCI_enableRx(mySci);

Ok, this part is quite obvious,  we are using the classic 8-N-1 setup and we want both RX and TX channels enabled.

    SCI_enableTxInt(mySci);
    SCI_enableRxInt(mySci);

Also we think it is cool to have interrupts on both RX and TX buffers, then we want to set the Baud Rate.
At this point, you realize that the way these libraries have been created allow you to perform all the needed configuration without knowing much about the internals of the device.
... but some details cannot hurt.

The base clock of the SCI is the low speed clock (LSPCLK), then a 16 bit register (BRR) is provided to configure a divider.
That allows up to 65535 different BR configurations, the formula is the following :


By default the LSPCLK is set to SYSCLK / 4 ( 60MHz/4 in our case = 15MHz)
According to the formula, assuming BRR = 15
-> BR = 15.000.000 / (15 +1)*8 = 15.000.000 /128 = 117.2K  which is not exactly 115.2K  but close enough.
Using BRR = 16 we would have 15.000.000 / 136 = 110.3K and using BRR = 14 : 125K
So, finally, BRR = 15 is the best option

    // Configured for 115.2kbps
#if (CPU_FRQ_60MHZ)
    SCI_setBaudRate(mySci, SCI_BaudRate_115_2_kBaud);    // value is 15
#elif (CPU_FRQ_50MHZ)
    SCI_setBaudRate(mySci, (SCI_BaudRate_e)13);
#elif (CPU_FRQ_40MHZ)
    SCI_setBaudRate(mySci, (SCI_BaudRate_e)10);
#endif

Obviously we need a different divider if the CPU is not set to 60MHz, but hey, you have the formula, you can do the math :)
The following code enables the fifo buffers for both the RX and TX channels, then it enables the TX fifo interrupt, but not the RX one.
That's because, I suppose, the sample program is not meant to receive any data, in a real world application we would probably need that one too.
Despite the fact that the TX interrupt is enabled, there is no interrupt handler function in the demo program.
I assume the interrupt is used internally by the library in order to manage properly the output buffer.

    SCI_enableFifoEnh(mySci);
    SCI_resetTxFifo(mySci);
    SCI_clearTxFifoInt(mySci);
    SCI_resetChannels(mySci);
    SCI_setTxFifoIntLevel(mySci, SCI_FifoLevel_Empty);

    SCI_resetRxFifo(mySci);
    SCI_clearRxFifoInt(mySci);
    SCI_setRxFifoIntLevel(mySci, SCI_FifoLevel_4_Words);

Finally, after clearing the interrupts, the buffers etc, a priority is set and the module enabled

    SCI_setPriority(mySci, SCI_Priority_FreeRun);
    SCI_enable(mySci);
    return;
}



checking in the header file it looks that the following priorities are available :

 
     SCI_Priority_Immediate=(0 << 3),    //!< Denotes an immediate stop
    SCI_Priority_FreeRun=(1 << 3),      //!< Denotes free running
    SCI_Priority_AfterRxRxSeq=(2 << 3)  //!< Denotes that a stop after the current receive/transmit sequence

That completes the hardware configuration, on the software side, the port is dealt with similarly to a stream (or file) :


    status = add_device("scia", _SSA, SCI_open, SCI_close, SCI_read, SCI_write, SCI_lseek, SCI_unlink, SCI_rename);
    fid = fopen("scia","w");
    freopen("scia:", "w", stdout);
    setvbuf(stdout, NULL, _IONBF, 0);

First a "device" named scia is added, then it is opened for output and finally redirected to the standard output device (stdout).
From now on, each write to stdout will actually be directed to the uart :

   putchar(0x1B);

This was a very high level first look into the serial communications of the C2000, will come back in the future with some more details and some experiments.



11 comments:

Unknown said...

Thanks for your great guides.

I am trying to get the serial port working on my C2000 and can't seem to get any data out. I have tried the example program and also checked it with your steps and all seems ok. I have also made sure that S4 is on and all of S1 is also on.

When the program runs, no data is seen on Putty or a port monitor that I am using. The TX and RX LED's on the board also don't light up indicating that data was sent from the C2000.

Do you know of any other set up that I might need to do.

I have a flashing LED program working so think I have my project set up correctly.

Thanks,
Greg

Franz said...

Hello, are you actually trying to achieve serial communications via the USB (FTDI) interface or via the expansion pins (TTL UART)?

If you use the FTDI virtual serial port, the issue might be on your PC side (maybe you are not checking the correct comport?)

Unknown said...

Thanks for replying.

I am using the FTDI VCP. Only one VCP get enumerated so I can only connect to that one. Will have a closer look at the schematic to see if there is some hardware change that needs to be done.

Franz said...

Uhm, in that case it should really work, normally the only HW setting needed is the S4 switch.
You may have problems with the windows driver for the virtual comport (if you have any other ftdi device that sends data, you may try to verify with that one).
Also the problem may be in the terminal program you are using under windows, in which you may have not set the correct connection properties.
I use Teraterm and had that issue at the beginning

Unknown said...

Thanks again for your help. I managed to find the demo software source code and with the help of that I got it working.
Changed a few things and now have an echo program working.
Thanks

Anonymous said...

Dear Francesco,

Have you ever tried using I2C and SCI modules on F2803x ??

I am supposed to make a measurement module based on TMS320F28035 MCU and I have a problem with making it work.
I implemented a code to communicate with 5 sensors and I am collecting data from them without a problem.
If I want to send e.g. 2 bytes from one of the sensors, a terminal program sees them correctly. Everything is fine when I do that.
BUT, when I want to add even one byte from another sensor to the previous 2, the data from all of the sensors become weird. They are completely not as before adding the additional byte to UART communitacion.
May it be that SCI affects I2C? Because SCI sends right data, but I2C collects some rubbish which seems like overload of I2C buffers.
If you want I can send you my code by e-mail.
My address is rafal-chojnowski@o2.pl

Thank you in advance for your help,
Regards
Rafal

Anonymous said...

Dear Francesco,

Have you ever tried using I2C and SCI modules on F2803x ??

I am supposed to make a measurement module based on TMS320F28035 MCU and I have a problem with making it work.
I implemented a code to communicate with 5 sensors and I am collecting data from them without a problem.
If I want to send e.g. 2 bytes from one of the sensors, a terminal program sees them correctly. Everything is fine when I do that.
BUT, when I want to add even one byte from another sensor to the previous 2, the data from all of the sensors become weird. They are completely not as before adding the additional byte to UART communitacion.
May it be that SCI affects I2C? Because SCI sends right data, but I2C collects some rubbish which seems like overload of I2C buffers.
If you want I can send you my code by e-mail.
My address is rafal-chojnowski@o2.pl

Thank you in advance for your help,
Regards
Rafal

Franz said...

Well, honestly I never tried SPI / I2C on the piccolo, I will probably have to use them on the stellaris in a month or so...

the SCI-A is a single module that handles all the serial communication, so it is totally possible that some things might interfere if you try to use the simultaneously.
I am sorry I am not able to help you with this one, I am not even sure I understood the complete scenario.
What is not clear is when you say : when i add a byte FROM ANOTHER SENSOR.
UART is not a bus communication, I think you get weird results having different devices transmitting on the same line if this is what you are doing.
I2C might be more appropriate as you can have several slaves, but 1) the communication is normally initiated by the master and 2) it might be tricky for longer distances.

In a similar scenario I implemented a simple rs485. it is a bit slow, but it is cheap and easy to set up if your devices have an uart.

Anonymous said...

Hi,

I'm sorry for the late response. The notifications about new posts here came to my spam box.

I acctually resolved this problem and all the data from all the sensors (4: 2 teperature, 1 humidity and 1 lightning) were sent by spi, using UART perfectely.
The problem was an implementation of transmition and receiving of data to and from master device (F28035)
That is a short version of the solution.
If you have more questions, write to me at rafal-chojnowski@o2.pl

Oscar said...

Hi!
I'm trying to use the Sci module of the piccolo launchpad, but I'm using assambly instructions.
My problem is that I can't see the information byte on the Tx pin.
I've alrady enabled the SciClk, and I've checked that all the Sci registers.
On the Sci Reference guide says that once the TxBuf is written to, the TxEmpty flag must be cleared and I get 0x00c0 on the SciCtl2 register right after writting to the TxBuf, which meand that TxEmpty and TxRdy flags are set.
I appreciate any help!
Thank you!

Unknown said...

Hi....I am using C2000 piccolo launchpad F28027....I want to transmit data from C2000 to xigbee....I ahve connected the xigbee from SCITXD but my launchpad is also connected to pc via usb ....Will the SCITXD will work?...How to store the program on the c2000 launchpad....But i also want to observe the data in c2000 memeory so I cant disconnect it from pc....Any suggestion?...Or there any other way to connect xigbee to C2000?...I am coding using simulink