特性 | SCI | SPI | I2C |
---|---|---|---|
通信类型 | 异步串行 | 同步串行 | 同步串行 |
引脚数量 | 2(RXD/TXD) | 3~4(MOSI, MISO, SCLK, SS) | 2(SCL, SDA) |
通信距离 | 较远(配合RS232/485) | 短距板内通信 | 短距板内通信 |
主从结构 | 点对点 | 主从结构 | 多主多从 |
速率 | 一般较低(kbps级),RS485能到10M,达到spi的量级 | 高速(Mbps级) | 中低速(kbps~400kbps) |
应用场景 | 串口通信、调试输出、几百米范围内的快速传输 | 快速外设通信(ADC、Flash) | 板间简单通信(EEPROM、传感器) |
- TI的SCI 是一种基础但非常实用的点对点异步串行通信接口,适用于需要可靠串行通信的场合。
TI SCI 的核心寄存器 | 功能说明 |
---|---|
SCICTL1 | 控制寄存器 1:使能 SCI、设置休眠模式、接收使能等 |
SCICTL2 | 控制寄存器 2:设置发送中断、发送使能、接收中断等 |
SCIRXST | 接收状态寄存器:显示 RXRDY、OE、FE、PE 等错误标志 |
SCIRXBUF | 接收缓冲寄存器:读取接收到的数据 |
SCITXBUF | 发送缓冲寄存器:写入要发送的数据 |
SCIBAUD | 波特率设置寄存器:设置波特率除数 |
SCIFFTX / SCIFFRX | FIFO 发送/接收控制寄存器(如果使用 FIFO) |
- DSP28335 使用 SCI 接收数据的基本流程:
- 配置系统时钟和外设时钟
- 初始化 GPIO 引脚为 SCI 功能
- 初始化 SCI 模块(设置波特率、数据格式)
- 使能中断(可选)
- 编写中断服务函数(ISR)处理接收数据
- 主循环中运行或等待中断触发
代码示例(基于 TI C2000Ware 或 DSP2833x_headers)
所需头文件:
#include "DSP2833x_Device.h" // DSP28335 头文件
#include "DSP2833x_Examples.h" // 示例支持库
1. 全局变量定义
// 接收缓冲区相关
char rxData;
Uint16 ScibRxErrorCount = 0;
// 函数声明
interrupt void scibRcvISR(void);
void InitScibGpio(void);
void InitScib(void);
2. 初始化 GPIO(SCI-B)
void InitScibGpio(void)
{
EALLOW;
// 设置 GPIO9 为 SCITXDB(发送)
GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 2;
GpioCtrlRegs.GPADIR.bit.GPIO9 = 1; // 输出
// 设置 GPIO11 为 SCIRXDB(接收)
GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 2;
GpioCtrlRegs.GPAQSEL1.bit.GPIO11 = 1; // 同步采样
GpioCtrlRegs.GPADIR.bit.GPIO11 = 0; // 输入
EDIS;
}
3. 初始化 SCI-B(异步模式,波特率 9600)
void InitScib(void)
{
// 1. 使能 SCI-B 时钟
SysCtrlRegs.PCLKCR0.bit.SCIBENCLK = 1;
// 2. 配置 SCI-B 控制寄存器
ScibRegs.SCICCR.all = 0x0007; // 8 bits, no parity, 1 stop bit
ScibRegs.SCICTL1.all = 0x0003; // enable TX, RX, internal SCICLK
ScibRegs.SCICTL2.bit.RXBKINTENA = 1; // 使能接收中断
ScibRegs.SCIHBAUD = 0x0001; // 波特率高位 (根据公式计算)
ScibRegs.SCILBAUD = 0x00E7; // 波特率低位 => 9600 @ LSPCLK=37.5MHz
ScibRegs.SCIPRI.bit.FREE = 1; // Free run mode for debug
}
4. 中断服务函数(ISR)
interrupt void scibRcvISR(void)
{
// 读取接收数据
rxData = ScibRegs.SCIRXBUF.all;
// 回显发送 数据被写入 SCITXBUF 后,SCI 模块开始将该数据位一位一位地通过串行接口发送出去。
// 如果启用了 FIFO,多个字节可以先缓存在 FIFO 中,直到 FIFO 达到触发级别或者被手动发送。
ScibRegs.SCITXBUF = rxData;
// 错误检查
if ((ScibRegs.SCIRXST.all & 0x0070) != 0)
{
ScibRxErrorCount++;
}
// 清除中断标志 告诉 PIE 控制器 我已经处理完这个中断了,请允许下一次该组中断进入 CPU
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP9;
}
-
GROUP9
- DSP28335 PIE它将多个外设中断分组,然后映射到 CPU 的有限几个中断线(INT1~INT12)上。SCI-B 接收中断属于 Group 9
-
发送数据示例:
void SendData(char *data, Uint16 length)
{
Uint16 i;
for(i = 0; i < length; i++)
{
// 等待 TX FIFO 不满
while(ScibRegs.SCIFFTX.bit.TXFFST >= 16); // 假设 FIFO 大小为 16
ScibRegs.SCITXBUF = data[i]; // 写入数据到 TX Buffer
}
// 等待所有数据发送完成
while(ScibRegs.SCIFFTX.bit.TXFFST != 0);
}
5. 主函数 main() & 接收中断映射到中断服务函数
void main(void)
{
// Step 1: 初始化系统控制(PLL、看门狗、使能外设时钟)
InitSysCtrl();
// Step 2: 初始化 GPIO
InitScibGpio();
// Step 3: 初始化 SCI-B
InitScib();
// Step 4: 初始化 PIE 控制器并映射 ISR
DINT; // 关闭全局中断
InitPieCtrl(); // 初始化 PIE 控制器
IER = 0x0000; // 禁用所有 CPU 中断
IFR = 0x0000; // 清除所有中断标志
InitPieVectTable(); // 初始化 PIE 向量表
// 将 SCI-B 接收中断映射到中断服务函数
PieVectTable.SCIRXINTB = &scibRcvISR;
// Step 5: 使能 CPU 和 PIE 中断
IER |= M_INT9; // 使能 Group 9(SCI-B 属于 Group 9)
EnableInterrupts(); // 开启全局中断(EINT)
// Step 6: 进入主循环
for(;;)
{
// 可在此添加其他逻辑或保持空循环
}
}
加入 FIFO 支持以提高效率
- SCI FIFO 可以缓存多个接收或发送的数据字节,在达到设定的触发阈值时才产生中断,从而避免每次只处理一个字节。
DSP28335 的 SCI 模块支持 FIFO,相关寄存器如下:
- SCIFFTX
:发送 FIFO 控制寄存器
- SCIFFRX
:接收 FIFO 控制寄存器
- SCIFFCT
:FIFO 控制扩展寄存器(一般不常用)
- 初始化函数
InitScib()
void InitScib(void)
{
// 使能 SCI-B 外设时钟
SysCtrlRegs.PCLKCR0.bit.SCIBENCLK = 1;
ScibRegs.SCIFFTX.all = 0x8000; // 禁止 FIFO FIFO RX 和 TX 复位
ScibRegs.SCICCR.all = 0x0007; // 设置数据格式:8 bits, no parity, 1 stop bit
// 3. 使能发送和接收,关闭休眠模式
ScibRegs.SCICTL1.all = 0x0003;
// 4. 设置波特率 (9600 @ LSPCLK = 37.5 MHz)
ScibRegs.SCIHBAUD = 0x0001;
ScibRegs.SCILBAUD = 0x00E7;
// 5. 启用 FIFO 并设置接收中断触发级别为 1/4 满(4 字节)
ScibRegs.SCIFFRX.all = 0x2044; // RXFFIL = 4 (当接收到 4 字节时触发中断)
// RXFFIENA = 1 (使能接收中断)
// 6. 启用 FIFO 发送(可选)
ScibRegs.SCIFFTX.all = 0xC000; // TX FIFO Reset + TX INT Enable
// 7. 选择自由运行模式(调试不停止)
ScibRegs.SCIPRI.bit.FREE = 1;
}
- 中断服务函数(ISR)
- 启用 FIFO 后,可以在中断中一次性读取多个字节。
#define MAX_RX_BUFFER 128
char rxBuffer[MAX_RX_BUFFER];
Uint16 rxIndex = 0;
interrupt void scibRcvISR(void)
{
Uint16 i;
Uint16 rxLevel;
rxLevel = ScibRegs.SCIFFRX.bit.RXFFST; // 当前 FIFO 中有多少个字节
for(i = 0; i < rxLevel; i++)
{
if(rxIndex < MAX_RX_BUFFER - 1)
{
rxBuffer[rxIndex++] = ScibRegs.SCIRXBUF.all; // 读取数据,自动清除标志
// Echo 回去
ScibRegs.SCITXBUF = rxBuffer[i];
}
}
// 清除中断标志
ScibRegs.SCIFFRX.bit.RXFFINTCLR = 1;
// 应答 PIE
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP9;
}
CG
- TI DSP 28335 SCI FIFO中断 串口232通信
- sci的概念比较大,叫串行通讯,可以包括同步串行通讯spi,也包括异步串行通讯uart. 提出这个概念应该是和并行通讯相区别来的, 表示数据是一个字节一个字节依次传送, 单向数据传递只要1跟线,而并行需要8跟线,在 TI DSP(如 C2000 系列)的特定语境中,SCI 通常指该平台上的异步串行通信接口,功能类似于标准 UART,但可能包含一些扩展特性(如 FIFO、多处理器模式等)。
- https://github.com/brunoluiz/28335ModbusSlave
- 普中 DSP28335 开发攻略 https://gitcode.com/Open-source-documentation-tutorial/0bb6c/blob/main/%E6%99%AE%E4%B8%ADDSP28335%E5%BC%80%E5%8F%91%E6%94%BB%E7%95%A5.pdf