UART(SCI)串口配置与使用
目录
- SCI基础
- 与STM32对比
- SCI寄存器
- 手动配置SCI
- SysConfig配置SCI
- 实战示例
SCI基础
F280049C的串口模块称为SCI (Serial Communications Interface):
- SCI数量: 2个独立的SCI模块(SCIA, SCIB)
- 通信模式: 全双工异步通信
- 数据位: 1-8位可配置
- 停止位: 1或2位
- 校验位: 无校验、奇校验、偶校验
- 波特率: 可编程,最高可达LSPCLK/8
SCI特性
- 独立的发送和接收FIFO(16级深度)
- 支持中断和DMA传输
- 硬件流控(RTS/CTS)可选
- 自动波特率检测
- 多处理器通信模式
SCI引脚
每个SCI模块有2个引脚:
- SCITXD: 发送数据
- SCIRXD: 接收数据
与STM32对比
术语对比
| STM32 |
F280049C |
说明 |
| USART |
SCI |
串口模块名称 |
| USART1 |
SCIA |
串口1 |
| USART2 |
SCIB |
串口2 |
| TX |
SCITXD |
发送引脚 |
| RX |
SCIRXD |
接收引脚 |
配置流程对比
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| UART_HandleTypeDef huart1; huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; HAL_UART_Init(&huart1);
SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE)); SCI_enableModule(SCIA_BASE); SCI_resetChannels(SCIA_BASE);
|
SCI寄存器
主要寄存器
1. SCIxCCR - 通信控制寄存器
1 2 3 4
| SciaRegs.SCICCR.bit.SCICHAR = 7; SciaRegs.SCICCR.bit.STOPBITS = 0; SciaRegs.SCICCR.bit.PARITYENA = 0; SciaRegs.SCICCR.bit.LOOPBKENA = 0;
|
2. SCIxCTL1 - 控制寄存器1
1 2 3
| SciaRegs.SCICTL1.bit.RXENA = 1; SciaRegs.SCICTL1.bit.TXENA = 1; SciaRegs.SCICTL1.bit.SWRESET = 1;
|
3. SCIxCTL2 - 控制寄存器2
1 2
| SciaRegs.SCICTL2.bit.RXBKINTENA = 1; SciaRegs.SCICTL2.bit.TXINTENA = 1;
|
4. SCIxHBAUD/SCIxLBAUD - 波特率寄存器
1 2 3 4 5
|
uint16_t brr = (DEVICE_LSPCLK_FREQ / (115200 * 8)) - 1; SciaRegs.SCIHBAUD.all = (brr >> 8) & 0xFF; SciaRegs.SCILBAUD.all = brr & 0xFF;
|
5. SCIxRXBUF/SCIxTXBUF - 数据缓冲区
1 2 3 4 5
| SciaRegs.SCITXBUF.all = 'A';
uint16_t data = SciaRegs.SCIRXBUF.all;
|
6. SCIxFIFOTX/SCIxFIFORX - FIFO控制
1 2 3
| SciaRegs.SCIFFTX.bit.SCIFFENA = 1; SciaRegs.SCIFFTX.bit.TXFIFOXRESET = 1; SciaRegs.SCIFFRX.bit.RXFIFORESET = 1;
|
手动配置SCI
方法1: 直接寄存器操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include "F28x_Project.h"
void SCIA_Init_Register(void) { EALLOW;
GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1; GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0; GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0; GpioCtrlRegs.GPAQSEL2.bit.GPIO29 = 3;
SciaRegs.SCICTL1.bit.SWRESET = 0;
SciaRegs.SCICCR.bit.SCICHAR = 7; SciaRegs.SCICCR.bit.STOPBITS = 0; SciaRegs.SCICCR.bit.PARITYENA = 0; SciaRegs.SCICCR.bit.LOOPBKENA = 0;
SciaRegs.SCIHBAUD.all = 0x00; SciaRegs.SCILBAUD.all = 53;
SciaRegs.SCIFFTX.bit.SCIFFENA = 1; SciaRegs.SCIFFTX.bit.TXFIFOXRESET = 1; SciaRegs.SCIFFRX.bit.RXFIFORESET = 1;
SciaRegs.SCICTL1.bit.RXENA = 1; SciaRegs.SCICTL1.bit.TXENA = 1;
SciaRegs.SCICTL1.bit.SWRESET = 1;
EDIS; }
void SCIA_SendChar(char data) { while(SciaRegs.SCIFFTX.bit.TXFFST != 0); SciaRegs.SCITXBUF.all = data; }
char SCIA_ReceiveChar(void) { while(SciaRegs.SCIFFRX.bit.RXFFST == 0); return SciaRegs.SCIRXBUF.all; }
|
方法2: DriverLib库函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include "driverlib.h" #include "device.h"
void SCIA_Init_DriverLib(void) { GPIO_setPinConfig(GPIO_28_SCIA_TX); GPIO_setPadConfig(28, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(28, GPIO_QUAL_ASYNC);
GPIO_setPinConfig(GPIO_29_SCIA_RX); GPIO_setPadConfig(29, GPIO_PIN_TYPE_PULLUP); GPIO_setQualificationMode(29, GPIO_QUAL_ASYNC);
SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE));
SCI_enableFIFO(SCIA_BASE); SCI_resetTxFIFO(SCIA_BASE); SCI_resetRxFIFO(SCIA_BASE);
SCI_enableModule(SCIA_BASE); SCI_resetChannels(SCIA_BASE); }
void SCIA_SendChar_DriverLib(char data) { SCI_writeCharBlockingFIFO(SCIA_BASE, data); }
char SCIA_ReceiveChar_DriverLib(void) { return SCI_readCharBlockingFIFO(SCIA_BASE); }
void SCIA_SendString(const char *str) { while(*str) { SCI_writeCharBlockingFIFO(SCIA_BASE, *str++); } }
|
波特率计算
公式
1
| BRR = (LSPCLK / (波特率 × 8)) - 1
|
常用波特率配置(LSPCLK = 50MHz)
1 2 3 4 5 6 7 8
| BRR = (50000000 / (9600 × 8)) - 1 = 650
BRR = (50000000 / (115200 × 8)) - 1 = 53
BRR = (50000000 / (921600 × 8)) - 1 = 6
|
SysConfig配置SCI
步骤1: 添加SCI模块
- 在SysConfig中找到 SCI
- 点击 “+” 添加SCI实例
- 选择 SCIA 或 SCIB
步骤2: 配置参数
1 2 3 4 5 6 7 8 9
| SCI Instance: SCIA ├── Baud Rate: 115200 ├── Data Bits: 8 ├── Stop Bits: 1 ├── Parity: None ├── Enable FIFO: ✓ ├── Enable TX: ✓ ├── Enable RX: ✓ └── Enable Interrupts: ✓ (可选)
|
步骤3: 配置引脚
在Pin Mux视图中:
1 2
| SCIA_TX → GPIO28 SCIA_RX → GPIO29
|
步骤4: 使用生成的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include "board.h"
void main(void) { Device_init(); Device_initGPIO();
Board_init();
const char *msg = "Hello from F280049C!\r\n"; while(*msg) { SCI_writeCharBlockingFIFO(SCIA_BASE, *msg++); }
while(1) { char c = SCI_readCharBlockingFIFO(SCIA_BASE); SCI_writeCharBlockingFIFO(SCIA_BASE, c); } }
|
实战示例
示例1: 串口发送字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include "driverlib.h" #include "device.h"
void SCIA_Init(void) { GPIO_setPinConfig(GPIO_28_SCIA_TX); GPIO_setPinConfig(GPIO_29_SCIA_RX); GPIO_setPadConfig(28, GPIO_PIN_TYPE_STD); GPIO_setPadConfig(29, GPIO_PIN_TYPE_PULLUP);
SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE));
SCI_enableFIFO(SCIA_BASE); SCI_resetTxFIFO(SCIA_BASE); SCI_resetRxFIFO(SCIA_BASE); SCI_enableModule(SCIA_BASE); SCI_resetChannels(SCIA_BASE); }
void SCIA_SendString(const char *str) { while(*str) { SCI_writeCharBlockingFIFO(SCIA_BASE, *str++); } }
void main(void) { Device_init(); Device_initGPIO();
SCIA_Init();
SCIA_SendString("F280049C UART Test\r\n"); SCIA_SendString("Hello World!\r\n");
while(1); }
|
示例2: 串口回显
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include "driverlib.h" #include "device.h"
void SCIA_Init(void) { GPIO_setPinConfig(GPIO_28_SCIA_TX); GPIO_setPinConfig(GPIO_29_SCIA_RX); GPIO_setPadConfig(28, GPIO_PIN_TYPE_STD); GPIO_setPadConfig(29, GPIO_PIN_TYPE_PULLUP);
SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE));
SCI_enableFIFO(SCIA_BASE); SCI_resetTxFIFO(SCIA_BASE); SCI_resetRxFIFO(SCIA_BASE); SCI_enableModule(SCIA_BASE); SCI_resetChannels(SCIA_BASE); }
void main(void) { Device_init(); Device_initGPIO();
SCIA_Init();
while(1) { char c = SCI_readCharBlockingFIFO(SCIA_BASE);
SCI_writeCharBlockingFIFO(SCIA_BASE, c); } }
|
示例3: 串口中断接收
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| #include "driverlib.h" #include "device.h"
#define RX_BUFFER_SIZE 128 char rxBuffer[RX_BUFFER_SIZE]; volatile uint16_t rxIndex = 0;
__interrupt void sciaRxISR(void) { while(SCI_getRxFIFOStatus(SCIA_BASE) != SCI_FIFO_RX0) { char c = SCI_readCharNonBlocking(SCIA_BASE);
if(rxIndex < RX_BUFFER_SIZE - 1) { rxBuffer[rxIndex++] = c;
if(c == '\n') { rxBuffer[rxIndex] = '\0'; rxIndex = 0; } } }
SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_RXFF); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); }
void SCIA_Init_Interrupt(void) { GPIO_setPinConfig(GPIO_28_SCIA_TX); GPIO_setPinConfig(GPIO_29_SCIA_RX); GPIO_setPadConfig(28, GPIO_PIN_TYPE_STD); GPIO_setPadConfig(29, GPIO_PIN_TYPE_PULLUP);
SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE));
SCI_enableFIFO(SCIA_BASE); SCI_setFIFOInterruptLevel(SCIA_BASE, SCI_FIFO_TX0, SCI_FIFO_RX1); SCI_resetTxFIFO(SCIA_BASE); SCI_resetRxFIFO(SCIA_BASE);
SCI_enableInterrupt(SCIA_BASE, SCI_INT_RXFF);
SCI_enableModule(SCIA_BASE); SCI_resetChannels(SCIA_BASE);
Interrupt_register(INT_SCIA_RX, &sciaRxISR); Interrupt_enable(INT_SCIA_RX); }
void main(void) { Device_init(); Device_initGPIO();
Interrupt_initModule(); Interrupt_initVectorTable();
SCIA_Init_Interrupt();
EINT; ERTM;
while(1) { } }
|
示例4: printf重定向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include "driverlib.h" #include "device.h" #include <stdio.h>
void SCIA_Init(void) { GPIO_setPinConfig(GPIO_28_SCIA_TX); GPIO_setPinConfig(GPIO_29_SCIA_RX); GPIO_setPadConfig(28, GPIO_PIN_TYPE_STD); GPIO_setPadConfig(29, GPIO_PIN_TYPE_PULLUP);
SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE));
SCI_enableFIFO(SCIA_BASE); SCI_resetTxFIFO(SCIA_BASE); SCI_resetRxFIFO(SCIA_BASE); SCI_enableModule(SCIA_BASE); SCI_resetChannels(SCIA_BASE); }
int fputc(int ch, FILE *f) { SCI_writeCharBlockingFIFO(SCIA_BASE, ch); return ch; }
int fgetc(FILE *f) { return SCI_readCharBlockingFIFO(SCIA_BASE); }
void main(void) { Device_init(); Device_initGPIO();
SCIA_Init();
printf("F280049C printf test\r\n"); printf("Counter: %d\r\n", 123); printf("Float: %.2f\r\n", 3.14159);
uint32_t counter = 0; while(1) { printf("Count: %lu\r\n", counter++); DEVICE_DELAY_US(1000000); } }
|
示例5: 命令行解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| #include "driverlib.h" #include "device.h" #include <string.h>
#define CMD_BUFFER_SIZE 64 char cmdBuffer[CMD_BUFFER_SIZE]; uint16_t cmdIndex = 0;
void SCIA_Init(void) { GPIO_setPinConfig(GPIO_28_SCIA_TX); GPIO_setPinConfig(GPIO_29_SCIA_RX); GPIO_setPadConfig(28, GPIO_PIN_TYPE_STD); GPIO_setPadConfig(29, GPIO_PIN_TYPE_PULLUP);
SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE));
SCI_enableFIFO(SCIA_BASE); SCI_resetTxFIFO(SCIA_BASE); SCI_resetRxFIFO(SCIA_BASE); SCI_enableModule(SCIA_BASE); SCI_resetChannels(SCIA_BASE); }
void SCIA_SendString(const char *str) { while(*str) { SCI_writeCharBlockingFIFO(SCIA_BASE, *str++); } }
void ProcessCommand(char *cmd) { if(strcmp(cmd, "help") == 0) { SCIA_SendString("Available commands:\r\n"); SCIA_SendString(" help - Show this help\r\n"); SCIA_SendString(" led on - Turn on LED\r\n"); SCIA_SendString(" led off - Turn off LED\r\n"); SCIA_SendString(" status - Show system status\r\n"); } else if(strcmp(cmd, "led on") == 0) { GPIO_writePin(31, 1); SCIA_SendString("LED ON\r\n"); } else if(strcmp(cmd, "led off") == 0) { GPIO_writePin(31, 0); SCIA_SendString("LED OFF\r\n"); } else if(strcmp(cmd, "status") == 0) { SCIA_SendString("System OK\r\n"); } else { SCIA_SendString("Unknown command. Type 'help' for help.\r\n"); } }
void main(void) { Device_init(); Device_initGPIO();
GPIO_setPadConfig(31, GPIO_PIN_TYPE_STD); GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); GPIO_setPinConfig(GPIO_31_GPIO31);
SCIA_Init();
SCIA_SendString("\r\nF280049C Command Line\r\n"); SCIA_SendString("Type 'help' for commands\r\n"); SCIA_SendString("> ");
while(1) { char c = SCI_readCharBlockingFIFO(SCIA_BASE);
SCI_writeCharBlockingFIFO(SCIA_BASE, c);
if(c == '\r' || c == '\n') { SCIA_SendString("\r\n");
if(cmdIndex > 0) { cmdBuffer[cmdIndex] = '\0'; ProcessCommand(cmdBuffer); cmdIndex = 0; }
SCIA_SendString("> "); } else if(c == '\b' || c == 127) { if(cmdIndex > 0) { cmdIndex--; SCIA_SendString(" \b"); } } else if(cmdIndex < CMD_BUFFER_SIZE - 1) { cmdBuffer[cmdIndex++] = c; } } }
|
常见问题
1. 串口无输出?
- 检查GPIO引脚配置是否正确
- 检查波特率计算是否正确
- 检查是否调用了
SCI_enableModule() 和 SCI_resetChannels()
- 使用示波器或逻辑分析仪检查TX引脚
2. 接收数据乱码?
- 检查波特率是否匹配
- 检查数据位、停止位、校验位配置
- 检查LSPCLK频率是否正确
3. 如何选择SCI模块?
- SCIA: GPIO28(TX), GPIO29(RX)
- SCIB: GPIO18(TX), GPIO19(RX) 或其他复用引脚
4. FIFO的作用?
5. 如何实现高速通信?
- 使用DMA传输
- 提高LSPCLK频率
- 优化中断处理时间
下一步
学习完UART后,继续学习:
参考资料
- TMS320F28004x Technical Reference Manual - SCI Module
- C2000Ware DriverLib API Guide - SCI Module
- SCI Example Code in C2000Ware