DSP实战TMS320F28035:SPI 初始化与配置要点
一、SPI 核心基础
1.1 什么是 SPI
-
SPI(Serial Peripheral Interface):同步串行外设接口,一种高速、全双工的串行通信协议。
-
架构:采用「1 个主机 + 多个从机」的主从架构,主机主导通信,从机被动响应。
-
通信本质:同步时钟驱动,核心特点是「发即收」,收发同时进行,无单独的读/写指令。
1.2 SPI 硬件引脚(4根核心线)
SPI 标准通信需4根核心引脚,不同厂商命名可能略有差异,但功能一致:
-
SCLK(Serial Clock):串行时钟线,由「主机单独产生」,用于同步收发双方的数据传输节奏,决定通信速率。
-
MOSI(Master Out Slave In):主机输出、从机输入线,主机通过该线向从机发送数据。
-
MISO(Master In Slave Out):主机输入、从机输出线,从机通过该线向主机回传数据。
-
CS/SS/NSS(Chip Select/Slave Select):片选信号线,低电平有效(默认),主机通过拉低对应从机的CS引脚,选中该从机进行通信;通信结束后拉高,释放总线,避免多从机干扰。
1.3 SPI 核心特点
-
全双工:收发数据同时进行,无需等待一方完成再执行另一方,通信效率高。
-
同步通信:数据传输严格由SCLK时钟边沿控制,时序稳定,适合高速传输。
-
主从模式:在绝大多数工程场景中,均工作在「主机模式」(产生时钟、发起通信)。
-
多从机支持:通过多个CS引脚扩展,同一时刻只能有一个从机被选中。
-
高速性:通信速率通常为几MHz~几十MHz,远高于I2C协议。
-
无应答机制:数据传输无确认环节,可靠性略低于I2C,但胜在速度快、配置简单。
1.4 时钟极性与相位(CPOL/CPHA)—— SPI配置核心
SPI 一共有4种工作模式,完全由「CPOL(时钟极性)」和「CPHA(时钟相位)」两个参数决定,这两个参数必须与从机设备的配置完全一致,否则会出现通信失败、数据乱码等问题,是SPI配置的重中之重。
1.4.1 CPOL(时钟极性)
定义SCLK时钟线在「空闲状态」(无数据传输时)的电平:
-
CPOL = 0:SCLK空闲时为低电平(最常用)。
-
CPOL = 1:SCLK空闲时为高电平(少数特殊外设使用)。
1.4.2 CPHA(时钟相位)
定义数据的「采样边沿」(即从机/主机在SCLK的哪个边沿读取数据):
-
CPHA = 0:在SCLK的「第一个边沿」(上升沿或下降沿,由CPOL决定)采样数据。
-
CPHA = 1:在SCLK的「第二个边沿」采样数据。
1.4.3 4种SPI通信模式对照表
|
SPI 模式 |
CPOL |
CPHA |
SCLK空闲电平 |
数据采样边沿 |
常用设备 |
|---|---|---|---|---|---|
|
Mode 0(常用) |
0 |
0 |
低电平 |
上升沿 |
SPI Flash(W25Q系列)、LCD、大多数传感器 |
|
Mode 1 |
0 |
1 |
低电平 |
下降沿 |
部分TFT屏、专用通信芯片 |
|
Mode 2 |
1 |
0 |
高电平 |
下降沿 |
少数音频芯片、ADC |
|
Mode 3 |
1 |
1 |
高电平 |
上升沿 |
部分高速外设、工业芯片 |
1.5 SPI 数据传输顺序
-
MSB first(高位先行):数据传输时,先发送/接收最高位(如0x12,先传0x1,再传0x2),是绝大多数SPI设备的默认配置。
-
LSB first(低位先行):数据传输时,先发送/接收最低位,仅少数特殊芯片支持(如部分传感器),需手动配置。
1.6 SPI 数据位宽
-
常用位宽:8bit(最普遍,适配绝大多数SPI外设,如Flash、LCD、传感器)。
-
扩展位宽:部分外设支持16bit(如部分ADC、DAC),TI C2000系列DSP支持3~16位可配置,按需调整。
1.7 NSS/CS 管理方式
1.7.1 软件 NSS(推荐)
-
原理:将CS引脚配置为普通GPIO,通过代码手动拉低(选中从机)、拉高(释放从机)。
-
优势:灵活度高,支持多从机扩展,适配绝大多数工程场景,是实际开发中最常用的方式。
1.7.2 硬件 NSS
-
原理:利用SPI外设自带的NSS引脚,由SPI模块自动控制拉低/拉高,无需手动操作。
-
劣势:仅适合单从机场景,灵活性差,工程中极少使用。
1.8 SPI 通信本质:发即收
SPI 协议没有“只发不收”或“只收不发”的操作,核心本质是「发即收」:
-
主机发送1字节数据的同时,必然会从MISO线接收1字节数据(即使不需要接收,也会自动接收)。
-
若想从从机读取数据,必须向从机发送一个「虚拟字节」(通常为0x00或0xFF),用于产生SCLK时钟,触发从机输出数据。
-
结论:SPI的读函数和写函数是同一个,本质都是“发送+接收”的组合操作。
二、F28035 SPI 初始化标准流程
TI C2000系列DSP(如F28035、F28335)的SPI初始化,遵循以下6个步骤,顺序错误会导致SPI无法正常工作,记牢即可:
-
GPIO 复用配置:将普通IO引脚复用为SPI功能引脚(SIMO、SOMI、SCLK),部分引脚需配置上拉、异步输入。
-
时钟使能:SPI的时钟由LSPCLK(低速外设时钟)提供,C2000默认已使能,无需额外配置,只需关注后续波特率分频即可。
-
SPI 软件复位:先将SPI模块复位(清空所有配置),再进行参数配置,避免残留配置影响功能。
-
配置核心参数:包括主从模式、CPOL/CPHA(工作模式)、波特率分频、数据位宽、MSB/LSB、NSS管理方式。
-
退出软件复位,使能SPI:所有参数配置完成后,退出复位状态,SPI模块开始工作。
-
调试与优先级配置:配置调试模式(断点不影响通信)、片选引脚极性等,提升工程实用性。
三、SPI IO 初始化(GPIO复用,硬件基础)
SPI IO初始化的核心是“将普通GPIO复用为SPI功能”,以下代码可直接复制使用,适配SPIA/SPIB双模块,注释详细,无需修改核心逻辑,仅需根据硬件修改引脚编号即可。
3.1 代码
void SPI_IOinit()
{
EALLOW;
// FLASH、LCD 相关控制脚配置为普通 GPIO
EECSMUX = 0; EECSDIR = 1;
LCD_BKMUX = 0; LCD_BKDIR = 1;
LCD_RSTMUX = 0; LCD_RSTDIR = 1;
LCD_CDMUX = 0; LCD_CDDIR = 1;
LCD_CSMUX = 0; LCD_CSDIR = 1;
#ifdef TFT_SPIA
// 上拉使能
GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0;
GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;
GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0;
// 异步输入模式
GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3;
GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3;
GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3;
// 复用为 SPIA
GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1;
GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1;
GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1;
#else
// SPIB 对应 GPIO 配置
#endif
CE_High(); // FLASH 片选拉高,避免总线冲突
EDIS;
}
3.2SPI FIFO 初始化(提升速度)
void spi_fifo_init()
{
PtrSPI->SPIFFTX.bit.SPIRST = 1;
PtrSPI->SPIFFTX.bit.SPIFFENA = 1; // 使能 FIFO
PtrSPI->SPIFFTX.bit.TXFFIENA = 0; // 关闭发送中断
PtrSPI->SPIFFRX.bit.RXFFIENA = 0; // 关闭接收中断
PtrSPI->SPIFFRX.bit.RXFFIL = 4; // FIFO 触发深度
PtrSPI->SPIFFCT.all = 0x0;
}
- 开启 FIFO 可以大幅提高刷屏速度。
- 不使用中断,查询方式更简单、稳定、易调试。
3.3 配置要点
-
EALLOW/EDIS必须成对使用:TI C2000的GPIO、SPI等控制寄存器是受保护的,必须先解锁(EALLOW)才能修改,配置完成后重新锁定(EDIS)。
-
上拉电阻必须开启:SPI通信属于高速串行传输,开启内部上拉可以增强信号抗干扰能力,避免因信号抖动导致通信错误。
-
异步输入配置:将SPI引脚配置为异步输入(GPAQSELx=3),可以消除同步延迟,保证高速传输时的数据采样准确。
-
复用编号必须查数据手册:不同DSP型号、不同SPI模块(SPIA/SPIB)的GPIO复用编号不同(如SPIA复用1,SPIB复用3),绝对不能写错,否则引脚无法正常工作。
-
CS引脚初始化:初始化时必须将CS引脚拉高,避免总线冲突,后续通信时再手动拉低选中对应从机。
四、SPI 寄存器初始化
SPI核心参数均通过寄存器配置,以下代码对应TI C2000的SPI寄存器操作,配置为「主机模式、8bit数据、Mode 1、波特率LSPCLK/4」,注释详细,逐行解析核心作用,可直接复制使用。
4.1 代码
// SPI模块指针(根据使用的模块修改:SpiaRegs=SPIA,SPIBRegs=SPIB)
#define PtrSPI SpiaRegs
/**
* @brief SPI核心参数初始化(主机模式)
* @note 配置:8bit数据、CPOL=0、CPHA=1(Mode1)、波特率LSPCLK/4、软件NSS
*/
void spi_init()
{
CE_High(); // 初始化前拉高CS,避免总线冲突
// 1. SPI软件复位(必须最先执行,清空原有配置)
PtrSPI->SPICCR.bit.SPISWRESET = 0; // 拉低复位,开启复位状态
// 2. 配置数据位宽:8bit(SPICHAR=7 → 7+1=8bit)
PtrSPI->SPICCR.bit.SPICHAR = 7; // TI C2000:SPICHAR=n → 数据位宽=n+1
// 3. 配置CPOL=0(SCLK空闲时为低电平,对应Mode1/Mode0)
PtrSPI->SPICCR.bit.CLKPOLARITY = 0 ;
// 4. 配置CPHA=1(下降沿采样数据,对应Mode1)
PtrSPI->SPICTL.bit.CLK_PHASE = 1; // 数据在SCLK上升沿输出,下降沿采样
// 5. 配置主从模式:1=主机模式(DSP产生SCLK,发起通信)
PtrSPI->SPICTL.bit.MASTER_SLAVE = 1;
// 6. 配置波特率:SPIBRR=3 → 波特率=LSPCLK/(SPIBRR+1)=LSPCLK/4
PtrSPI->SPIBRR = 3; // SPIBRR≥3时,波特率公式:LSPCLK/(SPIBRR+1)
// 7. 退出软件复位,使能SPI模块(所有参数配置完成后执行)
PtrSPI->SPICCR.bit.SPISWRESET = 1;
// 8. 调试与优先级配置(实用配置,避免调试时中断通信)
PtrSPI->SPIPRI.bit.FREE = 1; // 断点调试时,SPI继续传输,不中断
PtrSPI->SPIPRI.bit.STEINV = 0; // SPISTE引脚低电平有效(硬件NSS用,软件NSS不影响)
}
4.2 关键配置总结
-
软件复位顺序:必须先执行「SPISWRESET=0」(复位),配置完所有参数后,再执行「SPISWRESET=1」(退出复位),顺序绝对不能错。
-
数据位宽配置:TI C2000的SPICHAR寄存器,值为n时,数据位宽为n+1,常用「SPICHAR=7」(8bit)。
-
工作模式配置:代码中「CPOL=0,CPHA=1」,对应SPI Mode 1,需根据从机设备的数据手册修改,确保与从机一致。
-
主从模式:「MASTER_SLAVE=1」为主体模式,是工程中最常用的模式;若需配置为从机,改为0即可。
-
波特率计算(TI C2000专属):
-
当SPIBRR ≥ 3时,波特率 = LSPCLK / (SPIBRR + 1)
-
当SPIBRR < 3时,波特率 = LSPCLK / 4
-
注意:LSPCLK通常为系统时钟SYSCLK的二分频,波特率不能超过从机的最大支持时钟。
-
-
调试配置:「FREE=1」是实用配置,断点调试时SPI不会中断传输,避免调试时通信异常。
五、SPI 单字节收发函数(体现“发即收”本质)
结合SPI“发即收”的核心特点,读写函数是同一个,以下代码实现SPI单字节收发,适配8bit数据传输,可直接调用。
5.1 代码
/**
* @brief SPI单字节收发函数(发即收)
* @param a: 要发送的字节数据
* @retval 接收从机返回的字节数据
*/
uint8_t Send_Byte(uint16_t a)
{
Uint16 rdata; // 接收数据(C2000 SPI接收寄存器为16bit)
PtrSPI->SPICTL.bit.TALK = 1; // 使能SPI发送通道,允许主机输出数据
PtrSPI->SPITXBUF = (a << 8) & 0xff00; // 发送数据:8bit数据左移8位,占用SPITXBUF高8位
while(PtrSPI->SPIFFRX.bit.RXFFST >= 4 ) { } // 等待接收完成(FIFO模式,等待FIFO清空)
// while(SpiaRegs.SPISTS.bit.INT_FLAG == 0) {} // 备选:等待中断标志位(非FIFO模式,更常用)
rdata = PtrSPI->SPIRXBUF; // 读取接收缓冲区的数据(16bit)
return (uint8_t)(rdata >> 8); // 右移8位,提取有效8bit数据,返回
}
uint16_t Get_Byte(void)
{
uint8_t rdata;
PtrSPI->SPICTL.bit.TALK = 0; // 关闭发送通路
PtrSPI->SPITXBUF = DUMMYDATA; // 发空包产生时钟
while(PtrSPI->SPIFFRX.bit.RXFFST == 0);
rdata = PtrSPI->SPIRXBUF;
return rdata;
}
5.2 核心原理(理解“发即收”)
-
TALK位使能:「TALK=1」开启SPI发送通道,主机才能向从机发送数据;若为0,发送通道关闭,无法发送数据。
-
发送数据:TI C2000的SPITXBUF(发送寄存器)是16bit,而我们配置的是8bit数据传输,因此需将8bit数据左移8位,占用寄存器的高8位,避免数据错位。
-
等待接收:两种等待方式二选一,FIFO模式(代码中方式)适合高速传输,中断标志位方式适合普通场景,均能实现“等待收发完成”。
-
接收数据:SPIRXBUF(接收寄存器)也是16bit,接收的8bit数据存放在高8位,因此需右移8位,提取有效数据并返回。
本文完,感谢阅读!如果对你有帮助,欢迎点赞、收藏、关注~
作者:自动化小小
日期:2026年4月
更多推荐
所有评论(0)