一、系统概述
AD2S1210是一款高精度的旋变数字转换器(RDC),用于将旋转变压器输出的模拟信号转换为数字角度和速度值。本程序基于TI DSP F28335实现与AD2S1210的串行通信(SPI接口),完成角度和速度的读取与解析。
二、硬件连接
F28335 AD2S1210
------------------------
GPIO19 (CS) -> CS
GPIO18 (SCLK)-> SCLK
GPIO17 (SDIN)-> SDIN
GPIO16 (SDOUT)-> SDOUT
3.3V -> VDD
GND -> GND
三、程序架构

四、核心代码实现
1. 头文件与宏定义
#include "F28335_device.h"
#include "F28335_system.h"
// AD2S1210寄存器地址
#define REG_POSITION_MSB 0x80
#define REG_POSITION_LSB 0x81
#define REG_SPEED_MSB 0x82
#define REG_SPEED_LSB 0x83
#define REG_LOS_THR 0x88
#define REG_DOS_OVR_THR 0x89
#define REG_DOS_MIS_THR 0x8A
#define REG_DOS_RST_MAX 0x8B
#define REG_DOS_CFG 0x8C
#define REG_CONFIG 0x91
#define REG_FAULT 0x92
// 控制命令
#define WRITE_CMD 0x00
#define READ_CMD 0x80
// GPIO定义
#define AD2S1210_CS GpioDataRegs.GPBDAT.bit.GPIO48
#define SPI_CLK_FREQ 10000000 // 10MHz
2. SPI初始化
void InitSPI(void) {
// 1. 使能SPI时钟
EALLOW;
SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1;
EDIS;
// 2. 配置GPIO为SPI功能
EALLOW;
GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // SPISIMOA
GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // SPISOMIA
GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // SPICLKA
GpioCtrlRegs.GPBMUX2.bit.GPIO48 = 0; // GPIO48作为CS
GpioCtrlRegs.GPBDIR.bit.GPIO48 = 1; // 输出模式
EDIS;
// 3. 复位SPI模块
SpiaRegs.SPICCR.all = 0x0007; // 复位,8位字符,禁用自测
SpiaRegs.SPICTL.all = 0x0006; // 主模式,禁止超时,启用发送
SpiaRegs.SPIBRR = 0x001F; // 波特率设置 (SYSCLKOUT/(SPIBRR+1))
SpiaRegs.SPICCR.all = 0x0087; // 退出复位,启用SPI
// 4. 配置SPI FIFO
SpiaRegs.SPIFFTX.all = 0xE040; // 使能FIFO,清除发送寄存器
SpiaRegs.SPIFFRX.all = 0x204F; // 接收FIFO中断级别=15
SpiaRegs.SPIFFCT.all = 0x0000; // 无延迟
}
3. AD2S1210初始化
void AD2S1210_Init(void) {
// 1. 设置工作模式
AD2S1210_WriteReg(REG_CONFIG, 0x0C); // 16位分辨率,外部时钟
// 2. 配置故障阈值
AD2S1210_WriteReg(REG_LOS_THR, 0x0F); // 失锁阈值
AD2S1210_WriteReg(REG_DOS_OVR_THR, 0x07); // 过速阈值
AD2S1210_WriteReg(REG_DOS_MIS_THR, 0x07); // 欠速阈值
// 3. 使能故障检测
AD2S1210_WriteReg(REG_DOS_CFG, 0x0F); // 使能所有故障检测
// 4. 清除故障标志
AD2S1210_WriteReg(REG_DOS_RST_MAX, 0x00);
AD2S1210_WriteReg(REG_FAULT, 0x00);
}
4. SPI数据传输函数
Uint16 SPI_Transfer(Uint16 data) {
// 等待发送缓冲区为空
while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG);
// 发送数据
SpiaRegs.SPITXBUF = data;
// 等待接收完成
while(!SpiaRegs.SPISTS.bit.INT_FLAG);
// 读取接收到的数据
Uint16 rx_data = SpiaRegs.SPIRXBUF;
return rx_data;
}
5. AD2S1210寄存器读写
void AD2S1210_WriteReg(Uint8 reg_addr, Uint8 data) {
// 拉低CS
AD2S1210_CS = 0;
// 发送写命令和寄存器地址
SPI_Transfer(WRITE_CMD | reg_addr);
// 发送数据
SPI_Transfer(data);
// 拉高CS
AD2S1210_CS = 1;
}
Uint8 AD2S1210_ReadReg(Uint8 reg_addr) {
Uint8 result;
// 拉低CS
AD2S1210_CS = 0;
// 发送读命令和寄存器地址
SPI_Transfer(READ_CMD | reg_addr);
// 读取数据
result = SPI_Transfer(0xFF);
// 拉高CS
AD2S1210_CS = 1;
return result;
}
6. 角度和速度读取
typedef struct {
float angle; // 角度值 (0-360度)
float speed; // 速度值 (RPM)
Uint16 raw_angle; // 原始角度值
Int16 raw_speed; // 原始速度值
} AD2S1210_Data;
AD2S1210_Data AD2S1210_ReadData(void) {
AD2S1210_Data data;
// 读取角度高8位
Uint8 angle_msb = AD2S1210_ReadReg(REG_POSITION_MSB);
// 读取角度低8位
Uint8 angle_lsb = AD2S1210_ReadReg(REG_POSITION_LSB);
// 组合为16位角度值
data.raw_angle = (angle_msb << 8) | angle_lsb;
// 转换为角度 (0-360度)
data.angle = (data.raw_angle / 65536.0) * 360.0;
// 读取速度高8位
Uint8 speed_msb = AD2S1210_ReadReg(REG_SPEED_MSB);
// 读取速度低8位
Uint8 speed_lsb = AD2S1210_ReadReg(REG_SPEED_LSB);
// 组合为16位有符号速度值
data.raw_speed = (Int16)((speed_msb << 8) | speed_lsb);
// 转换为RPM (根据数据手册公式)
// 假设激励频率为10kHz,分辨率16位
data.speed = (data.raw_speed * 60.0) / 65536.0;
return data;
}
7. 故障检测
void AD2S1210_CheckFaults(void) {
Uint8 fault_reg = AD2S1210_ReadReg(REG_FAULT);
if(fault_reg & 0x01) {
// 失锁故障 (LOS)
Fault_Handler(FAULT_LOS);
}
if(fault_reg & 0x02) {
// 过速故障 (DOS OVR)
Fault_Handler(FAULT_DOS_OVR);
}
if(fault_reg & 0x04) {
// 欠速故障 (DOS MIS)
Fault_Handler(FAULT_DOS_MIS);
}
if(fault_reg & 0x08) {
// 信号幅度不足 (DOS SIN)
Fault_Handler(FAULT_DOS_SIN);
}
if(fault_reg & 0x10) {
// 信号幅度不足 (DOS COS)
Fault_Handler(FAULT_DOS_COS);
}
if(fault_reg & 0x20) {
// 配置错误 (CONFIG ERROR)
Fault_Handler(FAULT_CONFIG_ERROR);
}
}
8. 主程序
void main(void) {
// 系统初始化
InitSysCtrl();
DINT;
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
// 外设初始化
InitSPI();
InitGpio();
// AD2S1210初始化
AD2S1210_Init();
// 主循环
while(1) {
// 读取角度和速度
AD2S1210_Data sensor_data = AD2S1210_ReadData();
// 处理数据 (例如更新显示或控制算法)
ProcessSensorData(&sensor_data);
// 检测故障
AD2S1210_CheckFaults();
// 延时
DELAY_US(1000); // 1ms
}
}
五、关键参数配置
1. SPI时序配置
| 参数 | 值 | 说明 |
|---|---|---|
| 时钟极性(CPOL) | 0 | 空闲时低电平 |
| 时钟相位(CPHA) | 0 | 数据在第一个边沿采样 |
| 波特率 | 10 MHz | 根据系统时钟计算 |
| 数据位 | 8位 | 每次传输8位数据 |
| 传输模式 | 主模式 | F28335作为主设备 |
2. AD2S1210工作模式
| 参数 | 值 | 说明 |
|---|---|---|
| 分辨率 | 16位 | 角度和速度均为16位 |
| 激励频率 | 10 kHz | 旋变激励信号频率 |
| 故障检测 | 使能 | 所有故障检测使能 |
| 输出模式 | 串行 | 使用SPI接口输出数据 |
六、故障处理机制
typedef enum {
FAULT_NONE = 0,
FAULT_LOS, // 失锁故障
FAULT_DOS_OVR, // 过速故障
FAULT_DOS_MIS, // 欠速故障
FAULT_DOS_SIN, // 正弦信号幅度不足
FAULT_DOS_COS, // 余弦信号幅度不足
FAULT_CONFIG_ERROR // 配置错误
} FaultType;
void Fault_Handler(FaultType fault) {
switch(fault) {
case FAULT_LOS:
// 处理失锁故障
// 1. 检查旋变连接
// 2. 增加激励信号幅度
// 3. 记录故障日志
break;
case FAULT_DOS_OVR:
// 处理过速故障
// 1. 检查机械负载
// 2. 降低系统速度
break;
// 其他故障处理...
default:
// 未知故障
break;
}
// 更新故障状态寄存器
UpdateFaultStatus(fault);
}
参考代码 基于DSP F28335的AD2S1210的串行通信程序 www.youwenfan.com/contentalg/51768.html
七、优化措施
1. 数据读取优化
// 批量读取角度和速度
void AD2S1210_ReadAllData(AD2S1210_Data* data) {
// 拉低CS
AD2S1210_CS = 0;
// 发送读角度MSB命令
SPI_Transfer(READ_CMD | REG_POSITION_MSB);
data->raw_angle = SPI_Transfer(0xFF) << 8;
// 发送读角度LSB命令
SPI_Transfer(READ_CMD | REG_POSITION_LSB);
data->raw_angle |= SPI_Transfer(0xFF);
// 发送读速度MSB命令
SPI_Transfer(READ_CMD | REG_SPEED_MSB);
data->raw_speed = SPI_Transfer(0xFF) << 8;
// 发送读速度LSB命令
SPI_Transfer(READ_CMD | REG_SPEED_LSB);
data->raw_speed |= SPI_Transfer(0xFF);
// 拉高CS
AD2S1210_CS = 1;
// 转换为实际值
data->angle = (data->raw_angle / 65536.0) * 360.0;
data->speed = (data->raw_speed * 60.0) / 65536.0;
}
2. DMA传输实现
// 使用DMA进行SPI数据传输
void AD2S1210_DMA_Read(Uint8* tx_buf, Uint8* rx_buf, Uint16 len) {
// 配置DMA通道
DmaRegs.CH1.MODE.bit.CH1CONTINUOUS = 0; // 单次传输
DmaRegs.CH1.MODE.bit.CH1TRANSFERMODE = 1; // 16位传输
DmaRegs.CH1.BURST_SIZE.all = 0; // 单字突发
DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (Uint32)tx_buf;
DmaRegs.CH1.SRC_ADDR_SHADOW = (Uint32)tx_buf;
DmaRegs.CH1.DST_BEG_ADDR_SHADOW = (Uint32)&SpiaRegs.SPITXBUF;
DmaRegs.CH1.DST_ADDR_SHADOW = (Uint32)&SpiaRegs.SPITXBUF;
DmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFF; // 无环绕
DmaRegs.CH1.DST_WRAP_SIZE = 0xFFFF;
DmaRegs.CH1.TRANSFER_SIZE = len; // 传输长度
// 启动DMA传输
DmaRegs.CH1.CONTROL.bit.RUN = 1;
// 等待传输完成
while(DmaRegs.CH1.CONTROL.bit.OVRFLG == 0);
}
八、调试与测试方法
1. 测试点设置
| 测试点 | 信号 | 预期结果 |
|---|---|---|
| TP1 | SCLK | 10MHz方波,占空比50% |
| TP2 | SDIN | 数据波形符合SPI协议 |
| TP3 | SDOUT | 数据波形符合SPI协议 |
| TP4 | CS | 低电平有效,脉冲宽度>100ns |
| TP5 | ANGLE_OUT | 0-5V模拟信号,随角度变化 |
| TP6 | SPEED_OUT | 0-5V模拟信号,随速度变化 |
2. 测试用例
void Test_AD2S1210(void) {
// 1. 寄存器读写测试
AD2S1210_WriteReg(REG_CONFIG, 0x0C);
Uint8 config = AD2S1210_ReadReg(REG_CONFIG);
if(config != 0x0C) {
// 错误处理
}
// 2. 角度读取测试
AD2S1210_Data data = AD2S1210_ReadData();
if(data.raw_angle < 0 || data.raw_angle > 65535) {
// 错误处理
}
// 3. 速度读取测试
if(data.raw_speed < -32768 || data.raw_speed > 32767) {
// 错误处理
}
// 4. 故障注入测试
// 断开旋变信号,检查故障标志
// 超速旋转,检查过速故障
}
九、常见问题解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 无数据输出 | 电源问题 | 检查VDD电压(3.3V±5%) |
| 接线错误 | 检查SPI接线是否正确 | |
| CS信号未拉低 | 确认CS控制逻辑 | |
| 数据不稳定 | 时钟抖动 | 增加时钟缓冲器,优化PCB布局 |
| 电源噪声 | 增加去耦电容(0.1μF+10μF) | |
| 接地不良 | 检查接地回路 | |
| 角度跳变 | 旋变安装松动 | 检查机械安装 |
| 激励信号幅度不足 | 调整激励信号幅度 | |
| 速度读数异常 | 滤波器配置不当 | 调整AD2S1210的滤波器设置 |
| 机械振动 | 增加机械阻尼 | |
| 频繁报告故障 | 阈值设置不合理 | 根据实际工况调整故障阈值 |
十、总结
本程序实现了基于DSP F28335与AD2S1210旋变数字转换器的串行通信,主要功能包括:
SPI接口的初始化与配置
AD2S1210寄存器读写操作
角度和速度数据的读取与转换
故障检测与处理机制
性能优化措施(批量读取、DMA传输)