基于TMS320F28335与AD2S1210的SPI通信实现方案
一、硬件连接配置
| TMS320F28335引脚 | AD2S1210引脚 | 功能说明 |
|---|---|---|
| GPIO54 (SPISIMO) | SCLK | 串行时钟(主出从入) |
| GPIO55 (SPISOMI) | SDI | 串行数据输入(主入从出) |
| GPIO56 (SPICLK) | CS | 片选信号(低电平有效) |
| GPIO57 (SPISTE) | SAMPLE | 采样控制信号 |
| GPIO58 (SPISIMOA) | A0/A1 | 模式选择引脚 |
关键连接说明:
-
SPISTE引脚需连接AD2S1210的
SAMPLE引脚,用于控制数据采样时序 -
CS引脚需外接上拉电阻(10kΩ)确保空闲状态为高电平
-
电源引脚需添加0.1μF去耦电容
二、SPI时序配置要点
-
时钟参数:
-
空闲状态:CPOL=0(时钟低电平)
-
数据传输:CPHA=1(下降沿采样)
-
波特率:≤25MHz(由LSPCLK=37.5MHz决定)
-
-
关键时序约束:
// 初始化SPI配置(基于DSP28335寄存器) SpiaRegs.SPICCR.all = 0x0007; // 16位数据,无相位延迟 SpiaRegs.SPICTL.all = 0x0006; // 主模式,上升沿发送,下降沿接收 SpiaRegs.SPIBRR = 0x0003; // 波特率=37.5MHz/(3+1)=9.375MHz -
典型读时序:
CS↓ → SCLK↑ → 传输控制字 → SCLK↓ → ... → SCLK↑ → 数据读取
三、核心代码实现
1. SPI初始化
void Init_SPI(void) {
EALLOW;
SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1; // 使能SPI时钟
InitSpiaGpio(); // 配置GPIO54-57为SPI功能
SpiaRegs.SPICCR.bit.SPISWRESET = 0; // SPI复位
SpiaRegs.SPICCR.all = 0x0007; // 16位数据,无相位延迟
SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; // 主模式
SpiaRegs.SPICTL.bit.TALK = 1; // 使能发送
SpiaRegs.SPIBRR = 0x0003; // 设置波特率
SpiaRegs.SPICCR.bit.SPISWRESET = 1; // 释放复位
EDIS;
}
2. AD2S1210读写函数
#define AD2S1210_CS_CLR() GpioDataRegs.GPBCLEAR.bit.GPIO56 = 1
#define AD2S1210_CS_SET() GpioDataRegs.GPBCLEAR.bit.GPIO56 = 0
// 写入控制字
void AD2S1210_WriteReg(Uint16 addr, Uint16 data) {
AD2S1210_CS_CLR();
SpiaRegs.SPITXBUF = (addr << 8) | 0x80; // 控制字高位为1表示写操作
while(SpiaRegs.SPIFFRX.bit.RXFFST < 2); // 等待传输完成
SpiaRegs.SPITXBUF = data;
while(SpiaRegs.SPIFFRX.bit.RXFFST < 1); // 等待ACK
AD2S1210_CS_SET();
}
// 读取位置数据
Uint16 AD2S1210_ReadPos() {
AD2S1210_CS_CLR();
SpiaRegs.SPITXBUF = 0x80; // 读位置寄存器
while(SpiaRegs.SPIFFRX.bit.RXFFST < 2); // 丢弃旧数据
SpiaRegs.SPITXBUF = 0x00; // 发送空数据触发读取
while(SpiaRegs.SPIFFRX.bit.RXFFST < 2); // 等待数据
Uint16 pos = SpiaRegs.SPIRXBUF >> 4; // 右对齐处理
AD2S1210_CS_SET();
return pos;
}
四、典型应用流程
-
硬件初始化:
InitSysCtrl(); // 系统时钟配置 InitPieCtrl(); // 中断控制器初始化 Init_SPI(); // SPI模块初始化 AD2S1210_Reset(); // 执行硬件复位 -
AD2S1210初始化:
AD2S1210_WriteReg(0x92, 0x01); // 设置EXC频率为10kHz AD2S1210_WriteReg(0x8C, 0x80); // 启用增量式编码器仿真 -
数据采集循环:
while(1) { Uint16 angle = AD2S1210_ReadPos(); // 读取位置值 float theta = (angle / 4096.0f) * 360.0f; // 转换为角度 // 执行电机控制算法... }
参考代码 TMS320F28335串行读取AD2S1210数据 www.youwenfan.com/contentcnr/69291.html
五、常见问题解决
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 数据最高位丢失 | SPI时钟相位错误 | 检查CPHA设置(应为1) |
| 通信超时 | 片选信号未正确控制 | 确认CS引脚电平变化时序 |
| 数据波动大 | 激励信号幅值异常 | 检查EXC+/-差分信号峰峰值 |
| 偶发通信失败 | SPI缓冲区溢出 | 启用SPI FIFO模式 |
六、优化建议
-
时钟优化:
// 提高SPI时钟频率(需硬件支持) SpiaRegs.SPIBRR = 0x0000; // 波特率=37.5MHz/(0+1)=37.5MHz -
滤波处理:
// 添加移动平均滤波 #define FILTER_SIZE 5 static Uint16 angle_buf[FILTER_SIZE] = {0}; static Uint8 index = 0; angle_buf[index++] = AD2S1210_ReadPos(); if(index >= FILTER_SIZE) index = 0; Uint16 filtered = 0; for(Uint8 i=0; i<FILTER_SIZE; i++) filtered += angle_buf[i]; filtered /= FILTER_SIZE; -
中断模式:
// 配置SPI接收中断 SpiaRegs.SPIFFRX.bit.RXFFIL = 1; // 设置中断深度 SpiaRegs.SPIFFRX.bit.RXFFIENA = 1; // 使能接收中断 PieVectTable.SPIRXINTA = &SpiRxIsr; // 注册中断服务函数
七、调试工具建议
-
逻辑分析仪配置:
-
触发条件:CS下降沿
-
捕获长度:≥24个时钟周期
-
关键信号:CS、SCLK、SDO
-
-
示波器测量点:
CH1: SCLK (500ns/div) CH2: SDI (500ns/div) CH3: CS (1μs/div)
八、参考资料
-
AD2S1210数据手册(ADI官网)
-
TMS320F28335数据手册(TI官网)
-
《电机控制中的旋变解码技术》(李连志著)
浙公网安备 33010602011771号