TMC2209与UART通信控制之搞不定
参考资料
githubTMC芯片驱动大全:此github上覆盖大多数的TMC驱动芯片,代码我也上传避免有些小伙伴下载不了。
问题概述
在使用STM32F334微控制器通过UART2与TMC2209电机驱动芯片进行通信时,遇到了无法正常读写寄存器的问题。尝试了多种波特率和配置方式,但始终无法成功通信,尤其是读取寄存器时没有返回数据。
主控芯片使用STMF334的型号,使用UART1作为打印输出,UART2与TMC2209进行通信,STM32CubeMX配置如下:
电机控制部分原理图

STM32CubeMX配置
使能外部时钟

配置下载方式

配置时钟树

开启USART1功能异步方式并设置为115200(用于调试输出)
配置UART2并开启DMA功能。XT和RX不使用循环模式,RX内存地址递增

使能UART2中断功能

.C和.H文件的生成方式。

对于串口DMA不是太懂的话观看哔哩哔哩的老师串口IDLE闲中断+DMA实现不定长数据收发,按照这个来的话,比较容易。
TMC2209的驱动
直接摘取TMC2209的驱动的.c和.h等相关文件。先看看他的使用说明

1.提供底层的串口收发
2.提供芯片的ID号
c
bool tmc2209_readWriteUART(uint16_t icID, uint8_t *data, size_t writeLength, size_t readLength) {
HAL_UART_Transmit_DMA(&huart2,data,writeLength);
if(readLength > 0)
{
// 使能空闲中断
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE) ;
// 启用DMA接收
HAL_UART_Receive_DMA(&huart2,(uint8_t*)RxBuffer,LENGTH) ;
}
return 1;
}
c
uint8_t tmc2209_getNodeAddress(uint16_t icID)
{
if (icID <= 5)
{
switch (icID) {
case 0: return 0;
case 1: return 1;
case 2: return 2;
case 3: return 3;
case 4: return 4;
case 5: return 6; // 注意:输入5时返回6
default: return -1; // 可选:处理无效输入
}
return 0;
}
}
参考另一位CSDN博主的教程使用uart串口配置TMC2209模块,他是用USB转串口方式配置的。先配置TMC2209芯片的通用配置寄存器(TMC2209_GCONF)写入05 00 80 00 00 00 81。后通过05 00 00 48 进行读取TMC2209芯片的通用配置寄存器(TMC2209_GCONF),芯片就返回 05 FF 00 00 00 00 81 0A。

很好!有人做过先例了,我就尝试一下。
通信协议详解


TMC2209的UART通信协议要求64位数据(16进制),格式如下:
- 0-7位 :同步+保留字节,固定为
0x05 - 8-15位:TMC2209从机地址位,通过MS1和MS2引脚配置(0-3)
- 16-23位 :寄存器地址,需要
|0x80(例如0x00 | 0x80 = 0x80) - 24-55位:要写入的寄存器数据(32位,高位在前)
- 56-63位:CRC校验位
写入数据格式示例
要写入寄存器0x00,数据为0x81(0b10000001),则发送数据为:
0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, CRC
读取数据格式示例
要读取寄存器0x00,发送数据为:
0x05, 0x00, 0x00, 0x00, CRC
实操演练
逻辑分析采集出两条数据

写入驱动芯片的参数数据,通过UART1打印输出的数据与逻辑分析采集的数据是一样的

下一条数据,读取驱动芯片的参数数据。通过UART1打印输出的数据与逻辑分析与采集的数据也是一样的,但是他没有任何返回数据参数。

小伙伴发现了吗?读取数据指令后就没有任何的数据返回了,我都怀疑写入数据是不是正常写入了!?
然后我尝试了三个波特率,范围从115200到230400的范围还是一样,依然没有进行有效的通讯。
查找原因
从芯片手册中的可以了解到,头数据0x05是检验波特自动适配波特率的特征:


翻译 :每次 TMC2209 传输前都会有一个同步半字节,嵌入在第一个传输的字节中,随后是一个寻址字节(TMC2209 的 0 到 3,取决于地址设置)。每次传输允许内部波特率分频器与主时钟同步。实际波特率会被调整,内部时钟频率的变化也会得到补偿。因此,波特率可以在有效范围内自由选择。每个传输字节以起始位(逻辑 0,SWIOP 中的低级)开始,以停止位结束(逻辑 1,SWIOP 中的高层)。比特时间通过测量从起始比特开始(1 到 0 的转换)到同步帧结束(从第 2 位到第 3 比特 1 到 0 的转换)的时间来计算。所有数据均按字节传输。32 位数据字以最高字节优先传输。
假设 20 MHz 时钟(低波特率最坏情况)允许最低 9000 波特率。由于波特时钟的稳定性要求,最特率为 f/16。
此处我也尝试过9600的波特率,但是在这个波特率的通信读取TMC芯片配置参数指令 05 00 00 48最后一位的48 变成00了,所以我就弃用了9600的通信方式,从115200开始。
其他原因确认和节点地址
再看芯片引脚与通信相关的其他影响,好像也没发现什么关系。除了MS2、MS1设置芯片的ID号引脚定义外。(MS2、MS1这里我确定是接了低电平,我还特意在程序上其他ID号都遍历了一遍也没有用)

CRC计算验证:使的CRC计算函数验证,是调用TMC-API GitHub仓库里面的也是官方的东西,这个不会错
其他的小伙伴有没有指导一下是什么原因?搞得很郁闷