STM32 SPI通信实战:BISS-C编码器协议解析与实现

1次阅读
没有评论

共计 2023 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

工业编码器通信新选择:BISS- C 协议

在工业自动化领域,编码器作为位置检测的核心部件,其通信协议的选择直接影响系统性能。传统 ABZ 接口(A/ B 相增量信号 + Z 相零位信号)虽然简单,但存在明显短板:

  • 传输效率低 :需通过脉冲计数间接计算位置,实时性差
  • 无错误校验 :长线传输易受干扰导致位置丢失
  • 单工通信 :无法读取编码器参数或状态信息

而 BISS- C 协议作为开放标准,展现出三大优势:

  1. 全双工通信 :单根电缆同时传输位置数据和配置信息
  2. CRC 校验保障 :6 位 CRC 校验码可检测传输错误
  3. 绝对位置输出 :上电即获绝对位置,无需寻零操作

硬件设计:STM32 SPI 配置黄金法则

关键参数匹配

BISS- C 协议本质是 SPI 协议的变种,STM32 硬件 SPI 需注意以下配置(以 72MHz 主频为例):

hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH; // CPOL=1
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;      // CPHA=1
hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;       // 硬件 NSS
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; // 2.25MHz

为什么必须用硬件 NSS?

  • 精确时序控制 :硬件 NSS 的拉低到时钟启动有固定延迟(tCSS),确保编码器准备就绪
  • 避免信号竞争 :GPIO 模拟时若中断干扰会导致 CS 信号抖动,引发通信失败
  • 自动管理 :配合 DMA 使用时无需 CPU 干预 CS 信号状态

协议解析:BISS- C 帧结构拆解

典型报文时序

┌───┬───┬─────┬──────┬──────┐
│CD│SC│Data│ CRC  │  ACK  │
└───┴───┴─────┴──────┴──────┘
CD: 1bit 控制位 (0: 位置请求,1: 参数读写)
SC: 1bit 传感器通道选择
Data: 32/64bit 有效数据
CRC: 6bit 校验码
ACK: 1bit 应答 (主机需拉高 MOSI)

位置数据帧解析(0x4A 开头)

typedef struct {
    uint8_t head;      // 0x4A
    uint32_t position:24;
    uint8_t crc:6;
    uint8_t ack:1;
} __attribute__((packed)) BissCFrame;

代码实战:DMA 双缓冲实现

SPI 初始化关键代码

// DMA 双缓冲配置
__HAL_LINKDMA(&hspi1, hdmatx, hdma_spi1_tx);
__HAL_LINKDMA(&hspi1, hdmarx, hdma_spi1_rx);

// 启动接收
HAL_SPI_Receive_DMA(&hspi1, rx_buf[0], FRAME_LEN);

// DMA 中断回调
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {if(hspi->Instance == SPI1) {
        // 切换缓冲区
        active_buf ^= 1;
        HAL_SPI_Receive_DMA(hspi, rx_buf[active_buf], FRAME_LEN);

        // 处理已接收数据
        process_data(rx_buf[!active_buf]);
    }
}

CRC6 查表法实现

// 预计算 CRC6 表格(多项式 x^6 + x + 1)const uint8_t crc6_table[256] = {0x00,0x03,0x06,0x05,0x0C,0x0F,0x0A,0x09,...};

uint8_t calc_crc6(uint8_t *data, uint8_t len) {
    uint8_t crc = 0x3F; // 初始值
    while(len--) {crc = crc6_table[crc ^ *data++];
    }
    return crc & 0x3F; // 取低 6 位
}

避坑指南:血泪经验总结

  1. 时钟毛刺问题
  2. 现象:位置数据偶尔跳变
  3. 对策:在 SCK 信号线上并联 100pF 电容 +22Ω 电阻

  4. 多从机 CS 竞争

  5. 错误做法:多个 GPIO 模拟 CS 信号
  6. 正确方案:使用 74HC138 等译码器扩展硬件 NSS

  7. CRC 累积误差

  8. 现象:连续运行 8 小时后校验失败
  9. 解决:每 1000 次通信后主动发送复位命令(CD=1,SC=1)

性能验证数据

方式 CPU 占用率 最小响应时间
查询式 78% 150μs
DMA 双缓冲 12% 45μs

STM32 SPI 通信实战:BISS- C 编码器协议解析与实现
左:查询方式明显看到 CPU 频繁响应 右:DMA 传输期间 CPU 可处理其他任务

思考题

当需要多个编码器严格同步采样时(如机器人关节协作),如何利用 STM32 的 TIMER 触发 SPI+DMA 实现硬件级同步?

(提示:研究 TIMx_TRGO 信号与 SPI 的硬件联动配置)

正文完
 0
评论(没有评论)