Summary of DSP28335 using FIFO serial port interrupt
[Copy link]
1. Serial communication and parallel communication There
are two main types of communication methods that can be used to exchange information and communicate between DSP controllers and between DSP controllers and external devices: 1. Serial communication 2. Parallel communication.
Parallel communication generally includes multiple data lines, multiple control lines and status lines. It has fast transmission speed, many transmission lines, high hardware overhead and is not suitable for long-distance transmission. It is generally used inside the system, such as the XINTF interface or inside the controller, such as the DMA controller.
Serial communication transmits both data information and contact control information on the communication line. It has low hardware overhead and low transmission cost, but the transmission speed is slow, and both the sender and the receiver need a communication protocol. It can be used for long-distance communication. Serial communication can be divided into two categories: 1. Synchronous communication 2. Asynchronous communication
Synchronous communication: The transmitter and receiver are usually synchronized using the same clock source. The method is to include a clock signal when the transmitter sends data, and the receiver uses this clock signal to receive. Typical examples include IC and SPI.
Asynchronous communication: The clocks of the sender and receiver are not the same, and the data is sent and received by their own clocks. However, both parties are required to use the same nominal frequency, and a certain deviation is allowed. A typical example is SCI.
2. Introduction to 28335 SCI
The F28335 processor provides a total of 3 SCI interfaces. Compared with the SCI interface of TI's C240X series DSP, it has a great improvement in function. On the basis of the original functions, new functions such as automatic detection of communication rate and FIFO buffering have been added. In order to reduce the CPU overhead during serial communication, the serial port of F28335 supports 16-level receiving and transmitting FIFOs. FIFO buffering can also be used without using it. The SCI receiver and transmitter have their own independent interrupt and enable bits, which can be operated independently to achieve half-duplex communication, or simultaneously to achieve full-duplex communication. In order to ensure data integrity, the SCI module detects discontinuity, polarity, overrun and frame errors on the received data. In order to reduce the burden on software, SCI uses hardware to check the polarity and data format of communication data. Different SCI communication rates can be configured by programming the 16-bit baud rate control register.
The so-called FIFO means first-in-first-out. SCI works in FIFO mode because the information transmitted is not in units of one frame, but in units of one packet composed of multiple frames. For example, one of my data packets consists of 5 frames, the first one is the control byte, and the last four bytes together form a floating point number. At this time, you can set the FIFO receive interrupt to generate an interrupt when 5 bytes are received. After setting, an interrupt will be generated after every 5 bytes are received, instead of an interrupt for every reception. This can greatly reduce the CPU overhead. The meaning of first-in-first-out is: in the interrupt, the data you read from the FIFO receive register is the first data received, and the second data received is read again. If the depth is 16, it means that the most recent 16 received data can be saved. If the received data exceeds 16, a corresponding overflow will occur, and the overflow can be processed by software programming. The
same is true for the transmit FIFO. You can put multiple data into the transmit FIFO at one time, and then the DSP sends the data in sequence.
3. The features of the SCI module are as follows (these functions can be set through the corresponding registers)
(1) Two external pins: SCITXD is the SCI data transmission pin; SCIRXD is the SCI data reception pin. Both pins are multi-function multiplexed pins and can be used as general digital I/O if not used.
(2) Programmable communication rate, 64K communication rates can be set.
(3) Data format:
◇ 1 start position;
◇ 1~8 bits programmable data word length;
◇You can choose odd parity, even parity or invalid parity bit mode;
◇ 1 or 2 stop bits.
(4) Four error detection flags: parity error, overrun error, frame error, and discontinuity detection.
(5) Two ways to wake up the multiprocessor: idle-line wake-up and address bit wake-up.
(6) Full-duplex or half-duplex communication mode.
(7) Double buffer receiving and sending functions.
(8) Sending and receiving can be done in two ways: interruption and status query.
(9) Independent send and receive interrupt enable control.
(10)NRZ (Non-Return-to-Zero) communication format.
(11) 13 SCI module control registers, starting address is 7050H.
(12) Automatic communication rate detection (an enhanced function compared to F140x).
(13) 16-level transmit/receive FIFO (an enhanced function compared to F240x).
4. SCI main functional units
(1) 1 transmitter (TX) and related registers.
◇ SCITXBUF: transmit data buffer register, storing the data to be sent (loaded by the CPU);
ScicRegs.SCITXBUF=a; //Write data to the data buffer register to send the data
◇ TXSHF register: transmit shift register, receives data from the SCITXBUF register and shifts the data to the SCITXD pin, shifting 1 bit of data each time.
(2) 1 receiver (RX) and related registers.
◇ RXSHF register: receive shift register, shifts data from SCIRXD pin, 1 bit at a time;
◇ SCIRXBUF: Receive data buffer register, stores the data to be read by the CPU. The data from the remote processor is loaded into the register RXSHF, and then loaded into the receive data buffer register SCIRXBUF and the receive emulation buffer register SCIRXEMU.
(3) A programmable baud rate generator.
(4) Data memory mapped control and status registers.
5. SCI Register
The functions of each bit of the SCICCR register are shown in the figure. You can configure the length of the data sent or received by SCI, whether to use parity check, the number of end bits, etc. Similarly, each bit of each register has different functions. When writing a program, just look for the corresponding register. (In fact, TI has already written many things for us, such as the FIFO test function. We can modify it based on what others have written to speed up the progress)
6. Introduction to SCI sending and receiving functions
Programmable interrupt level: Both transmit and receive FIFOs can generate CPU interrupts. As long as the transmit FIFO status bit TXFFST (bits 12~8) matches the interrupt trigger priority TXFFIL (bits 4~0), an interrupt trigger is generated, thus providing a programmable interrupt trigger logic for SCI transmission and reception.
The one-word transmit buffer of the standard SCI acts as a transmit buffer between the transmit FIFO and the shift register. Only after the last bit of the shift register is shifted out, the one-word transmit buffer is loaded from the transmit FIFO. After enabling the FIFO, after an optional delay (SCIFFCT), TXSHF is loaded directly without using TXBUF. (Compared with the standard SCI, the interrupt source has changed. The standard SCI is when TXBUF is empty during transmission.)
During the SCI data transmission process, the line placement and clearing are all automatically completed by hardware.
VII. Analysis of simulation results
The final program is below. The program function is to send an array in the form of FIFO interrupt. The starting data in the array is 5, 5, 5, 5. Send these data first (note that the serial port receives and sends character data, and pay attention to the conversion when sending digital quantities), then modify the fourth data in the interrupt to the number of interrupts, and then send the new data. The first execution result is shown in the figure.
The correct result should be 5555, 5551, .... The analysis result shows that it seems that a serial port transmission interrupt is generated after the interrupt is enabled. But the interrupt flag is cleared. (It is guessed that it is because there is no data in the serial port transmission buffer register at this time, so it is understood as transmission is completed. Is it necessary to assign a value to the transmission buffer register before enabling the interrupt?) (After testing, the data to be sent for the first time is put into the FIFO before the interrupt is enabled, and the output result is correct)
Why does the subsequent configuration not work if I disable the sending function in the serial port experiment? I enabled the sending function at the end, but I cannot receive data. If I do not disable the sending function at the beginning, I can receive data. The reason is as follows:
Although the sending function is finally enabled, the SW RESET bit is written to 0, causing a reset, and all configurations are reset. (This also shows that you should be careful when configuring registers and determine the function of each bit. And when configuring, try to only configure the bit you need, and do not change the others. Use bit, not all)
The final result is shown in the figure, which achieves the expected result. It is also concluded that an interrupt will only occur when all the data in the FIFO has been sent.
8. Summary
When implementing a function, first check the relevant information, such as data sheets, forums, Baidu, books, etc., collect various relevant information, then see how others implement it, analyze the relevant steps, and sort out the ideas. Continue to look for information for the parts you don’t understand, and proceed step by step. (If you want to save trouble, you can modify it based on the correct code of others, see what registers he configured, what functions he implemented, and then check the data sheet to reconfigure it according to your own needs). When implementing, you can implement small functions one by one. If you encounter doubts, in addition to asking for help, you can also try to observe what results will appear in different situations. In short, search more, think more, do more, and summarize more.
#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
#define SCIB 0
#define SCIC 1
// Prototype statements for functions found within this file.
void scic_fifo_init(void);
void scic_xmit(int a);
interrupt void uart_send(void);
// Global counts used in this example
Uint16 isrCount=0;
Uint16 ErrorCount=0;
Uint16 sdata[4]={5,5,5,5};//要发送的数据
void main(void)
{
Uint16 i=0;
// Step 1. Initialize System Control registers, PLL, WatchDog, Clocks to default state:
// This function is found in the DSP2833x_SysCtrl.c file.
InitSysCtrl();
// Step 2. Select GPIO for the device or for the specific application:
// This function is found in the DSP2833x_Gpio.c file.
// InitGpio(); skip this as this is example selects the I/O
// for SCI-A in this file itself
InitSciGpio();
// Step 3. Initialize PIE vector table:
// The PIE vector table is initialized with pointers to shell Interrupt
// Service Routines (ISR). The shell routines are found in DSP2833x_DefaultIsr.c.
// Insert user specific ISR code in the appropriate shell ISR routine in
// the DSP28_DefaultIsr.c file.
// Disable and clear all CPU interrupts:
DINT;
IER = 0x0000;
IFR = 0x0000;
// Initialize Pie Control Registers To Default State:
// This function is found in the DSP2833x_PieCtrl.c file.
// InitPieCtrl(); PIE is not used for this example
// Initialize the PIE Vector Table To a Known State:
// This function is found in DSP2833x_PieVect.c.
// This function populates the PIE vector table with pointers
// to the shell ISR functions found in DSP2833x_DefaultIsr.c.
InitPieVectTable();
// Enable CPU and PIE interrupts
// This example function is found in the DSP2833x_PieCtrl.c file.
EnableInterrupts();
// Step 4. Initialize all the Device Peripherals to a known state:
// This function is found in DSP2833x_InitPeripherals.c
// InitPeripherals(); skip this for SCI tests
// Step 5. User specific functions, Reassign vectors (optional), Enable Interrupts:
isrCount = 0;
ErrorCount = 0;
#if SCIB
scib_fifo_init(); // Initialize the SCI FIFO
scib_loopback_init(); // Initalize SCI
#elif SCIC
scic_fifo_init(); // Initialize the SCI FIFO
#endif
// Send a character ,先给发送缓冲寄存器赋值。
for(i=0;i<4;i++)
{
scic_xmit(sdata[i]+0x30);
}
scic_xmit(' ');
// Step 6. Send Characters forever starting with 0x00 and going through
// 0xFF. After sending each, check the recieve buffer for the correct value
EALLOW;
// PieVectTable.SCIRXINTC = &uartIsr;
PieVectTable.SCITXINTC = &uart_send;
EDIS;
PieCtrlRegs.PIECTRL.bit.ENPIE=1;
// PieCtrlRegs.PIEIER8.bit.INTx5=1;
PieCtrlRegs.PIEIER8.bit.INTx6=1;
IER|=M_INT8;
EINT;
ERTM;
for(;;){ }
}
interrupt void uart_send(void)
{
Uint16 i;
isrCount++;
sdata[3]=isrCount;
for(i=0;i<4;i++)
{
scic_xmit(sdata[i]+0x30);
}
scic_xmit(' ');
if(isrCount==10)
{
ScicRegs.SCICTL1.bit.TXENA =0;//禁止发送缓冲器工作。
}
PieCtrlRegs.PIEACK.all=0xffff;//0x0080;
ScicRegs.SCIFFTX.bit.TXFFINTCLR=1; // Clear SCI Interrupt flag
}
// Transmit a character from the SCI'
void scic_xmit(int a)//发送一个数据a,类型为int
{
ScicRegs.SCITXBUF=a;//向数据缓冲寄存器中写入数据即可发送该数据
}
// Initalize the SCI FIFO
void scic_fifo_init()
{
// Test 1,SCIC DLB, 8-bit word, baud rate 9.6k, default, 1 STOP bit, no parity
//功能是配置发送模式
// Note: Clocks were turned on to the SCIC peripheral
// in the InitSysCtrl() function
// ScicRegs.SCICTL1.all =0x0000; //开始的时候先禁止接收与发送功能
ScicRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback
// No parity,8 char bits,
// async mode, idle-line protocol
//数据长度8位,一个结束位,无奇偶校验,空闲线模式,禁止回送
// ScicRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
ScicRegs.SCICTL1.all =0x0002; //允许发送,禁止接收
// ScicRegs.SCICTL2.all =0x0001;//发送缓冲器中断使能。似乎与下面的重复了
ScicRegs.SCICTL2.bit.TXINTENA =1;//发送缓冲器中断使能。
// ScicRegs.SCICTL2.bit.RXBKINTENA =1;
ScicRegs.SCIHBAUD =0x0001;
ScicRegs.SCILBAUD =0x00e7;
//上面是波特率设置,书上写的0x00e7
// ScicRegs.SCICCR.bit.LOOPBKENA =0;// enable(Disable) loop back
ScicRegs.SCICTL1.all =0x0022; // Relinquish SCI from Reset
//FIFO setScicRegs.SCIFFTX.bit.TXFIFOXRESET
=0;
// ScicRegs.SCIFFRX.bit.RXFIFORESET=0;
ScicRegs.SCIFFTX.all=0xE060;
// ScicRegs.SCIFFRX.all=0x204f;
ScicRegs.SCIFFCT.all=0x0;
}
//============================================== ============================
// No more.
//=============================================== ===========================
|