Implementation Method of Software Serial Interface (SCI) Based on C2000
[Copy link]
introduction:
The C2000 Piccolo series MCU chips generally integrate 1-2 hardware SCI (UART). Sometimes, due to cost or layout area considerations, only small packages or models with less resources can be selected, and then there will be a situation where the hardware SCI is not enough. In this case, GPIO software can be used to simulate the SCI interface.
This article gives the method and routines of simulating GPIO into SCI interface by using external interrupt and CPU timer.
1. Test related environment
The test-related software and hardware environment is shown in the following table:
You can select any example project. Here we select timed_led_blink. Its project file directory is:
C:\ti\controlSUITE\device_support\f2806x\v151\F2806x_examples_ccsv5\timed_led_blink
After importing the project in CCS, replace Example_2806xLEDBlink.c with the source code provided in this article.
2. Functional Description
SCI (Serial Communications Interface) is a two-wire asynchronous serial interface, also commonly known as UART. SCI provides a communication interface with some common peripherals. The data frame format of SCI, as shown in Figure 1, usually consists of the following parts:
1 bit Start bit: A logic 0 indicates the start of transmission.
1-8 bit data bit: little-endian transmission, the low bit is transmitted first and then the high bit.
1 bit parity bit (optional): Adding this bit makes the number of data bits 1 an odd or even number.
1 or 2 stop bits: One or two logic 1s indicate the end of transmission.
Figure 1 SCI data frame format
1. Sending program block diagram and sending state machine
After transmission is enabled, the CPU timer is turned on and an interrupt is generated every 8.67us (115200 bps). When the timer interrupt occurs, the output level of the pin is changed to realize data transmission. When the first timer interrupt occurs, the level of the transmit pin is set low, marking the start of data transmission. After that, the data bits and check bits are sent in sequence from low to high in little-endian mode. When odd parity is used, the result of the bitwise XOR of the data and the XOR result of the check bit should be 1; when even parity is used, the result of the bitwise XOR of the data and the XOR result of the check bit should be 0. After the transmission is completed, the transmit pin outputs a high level, marking the end of transmission.
Figure 2 Sending program flowchart and sending state machine
2. Receiver block diagram and receive state machine
After receiving is enabled, turn on the external interrupt. The SCI receiving pin is at a high level in the idle state, and the start bit of the received data is at a low level. Due to the uncertainty of the data arrival time, the external interrupt falling edge trigger method is used to detect the start bit of data transmission. After the external interrupt detects the falling edge, it marks the start of data transmission. At this time, delay 4us first, wait for the signal level to stabilize, then turn off the external interrupt and turn on the timer. The same as sending, the timer generates an interrupt every 8.67us. Each time an interrupt occurs, the level of the receiving pin is sampled, and the data bit, check bit and stop bit are received in turn. When all data are received, turn off the timer and wait for the next reception to be enabled.
Figure 3 Receiver block diagram and receive state machine
3. Functional Description
Baud rate: 115200 bps (adjustable), stop bit: 1 bit, data bit: 1-8 bit, parity bit: no parity, odd parity or even parity. The size of the receiving buffer can be determined by modifying recvBuffLen in the macro definition according to actual needs:
#define recvBuffLen 800
Taking the receiving buffer size of 800 Bytes as an example, every time the program receives 800 Bytes of data from GPIO0, it will send all the received data through GPIO32.
API
1. Macro definition
#define parity 1 // 0: no parity, 1: odd, 2: even
#define dataLength 8 // data bit length 1 - 8
#define recvBuffLen 25 // receive buffer size
parity: Check bit. Can be set to 0: no check, 1: odd check, 2: even check.
dataLength: data bit length, which can be configured as 1-8 bits.
recvBuffLen: Receive buffer size, usually set to the packet length.
2. Global variables
// software sci mode
// 0: rx 1: tx
Uint16 swSciMode = 0;
// rx data & state
Uint16 rxData = 0;
Uint16 rxState = 0;
Uint16 rxError = 0;
// tx data & state
Uint16 txData = 0;
Uint16 txState = 0;
swSciMode: defines the software serial port mode. To save hardware resources, half-duplex mode is used. 0 is the receiving mode, and 1 is the sending mode.
rxData: Single byte data received from GPIO.
rxState: Receiver state machine state, 0-3 are valid states, see Figure 3 for details.
rxError: Receive error indication flag. The value will change accordingly after calling the receive-related API and needs to be cleared manually. The specific definition is as follows:
txData: Single byte of data sent from the GPIO.
txState: Transmitter state machine state, 0-5 are valid states, see Figure 2 for details.
3. Functions
// Software SCI related functions
Uint16 sw_sci_recv_byte(void);
void sw_sci_recv_bytes(Uint16* dataBuff, Uint16 len);
void sw_sci_send_byte(Uint16 data);
void sw_sci_send_bytes(Uint16* dataBuff, Uint16 len);
void sw_sci_send_string(char* txString);
4. Testing
1. Baud rate and CPU load test
In order to test the performance of software SCI, this routine additionally uses GPIO32 as a test pin to indicate the program status. When the program enters the software SCI timer interrupt, GPIO32 outputs a high level; the rest of the time GPIO32 outputs a low level. Figure 4 shows the waveforms of the TX pin (blue line) and the test pin (yellow line) when sending 0x55 at 8 data bits, 1 odd parity, 1 stop bit, and 115200 baud rate. It can be seen from the figure that the actual transmission baud rate is 116280bps, with an error of 0.9%. The high level duration of the test pin and is the time that the software SCI takes up the CPU to send a single byte of data. After measurement, the high level of the test pin lasts for a total of 10.32us, and the theoretical transmission time of a single byte is 95.49us, so the CPU load is 10.8% when sending.
Figure 4 Software serial port routine sending test
Figure 5 shows the waveforms of the RX pin (blue line) and the test pin (yellow line) when receiving 0x55 at 8 data bits, 1 odd parity bit, 1 stop bit, and 115200 baud rate. After measurement, the high level of the test pin lasts for 7.2us, and the theoretical receiving time of a single byte is 95.49us, so the CPU load is 7.5% during reception.
Figure 5 Software serial port routine receiving test
Even without an oscilloscope, the eCAP inside the C2000 MCU can be used to measure the actual transmit baud rate and CPU load.
2. Data transmission and reception test
The software serial port routine is configured with 115200 baud rate, 8 data bits, 1 stop bit, odd parity. When the PC serial port assistant uses the same configuration, data can be sent and received normally:
Figure 6 Normal data transmission and reception
Change the serial port assistant software to even parity, and the routine prompts that the parity bit is wrong:
Figure 7 Check bit error detection
The software serial port routine is configured as no parity bit. When the serial port assistant uses odd parity, the routine actually receives the parity bit when receiving the end bit. At this time, the routine prompts that the end bit is wrong:
Figure 8 Stop bit error detection
When the example and the serial port assistant use the same configuration, 800 Bytes data packets are sent at a frequency of 5Hz, and the sending and receiving are normal:
Figure 9 Continuous transmission and reception test
5. Notes
1. Changing the communication baud rate can be achieved by adjusting the division factor of the CPU timer.
Theoretical frequency division coefficient =
Take LAUNCHXL-F28069M as an example. The main frequency of LAUNCHXL-F28069M is 90 MHz. The theoretical frequency division coefficient should be:
In actual use, since the system clock may have errors, it is recommended to use an oscilloscope to measure the actual output baud rate and adjust the frequency division factor.
2. The TX pin can be changed to any pin as required. The RX pin needs to determine the data start bit through the falling edge of the external interrupt, so it can only be selected from GPIO0-GPIO31.
3. To save hardware resources, the receiving and sending programs use the same CPU timer, so only half-duplex communication is possible. If you want to achieve full-duplex communication, you can use another timer to separate sending and receiving.
6. To-do items
1. Added the function of using eCAP to measure baud rate and CPU load.
2. Added baud rate automatic correction function.
Reference
[1] TMS320x2806x Piccolo Technical Reference Manual (spruh18g).
[2] cpu_timer and external_interrupt routines in ControlSUITE.
|