基于STM32F405平台的多摩川协议编码器通讯过程(1)

RS485通讯

多摩川通讯采用RS485通讯协议。
简单来说,485通讯的特点就是半双工差分信号,总线通讯。
下图是某国产品牌采用了多摩川通讯协议的绝对值编码器接口。
某国产品牌采用了多摩川通讯协议的绝对值编码器接口
差分:图中可以看到,该接口有485+、485-这两个数据接口,这两个接口电平信号的差值,作为传递数据的总线,此外还有5V和GND为编码器供电。
半双工:所谓半双工,即MCU既可以收,又可以发,但是不能同时收和发。

而我们一般用到的MCU芯片,不论是ST芯片上的串口USART,还是DSP上面的串口SCI,都是具有两条线的,一条TX用于发送数据,一条RX用于接收数据,这样的结构叫作单端信号。而且从原理上讲,这样的结构是可以同时实现数据的收和发的,这样的通讯方式叫作全双工
但是,对于STM32F405这款芯片来说,由于数据的发送和接收都用了同一个数据寄存器DR,所以在工程的开发过程中要注意合理调配数据的收发时刻。

为了将MCU的单端全双工信号,转成差分的半双工信号,我们要用到一款转换芯片SN65HVD75DR。
在这里插入图片描述
除去辅助电路,这款芯片的工作原理就是:

  • 当我们把2、3引脚同时拉低时,6、7引脚上的差分数据会被传递到1引脚上,1引脚连接MCU的RX引脚,进而实现读取数据。
  • 当我们把2、3引脚同时拉高时,4引脚上的数据会被传递到6、7引脚上变成差分数据,4引脚上的数据是MCU的TX引脚发出的,进而实现发送数据。
    好,现在我们已经具备了数据的收和发的功能了。那么我们怎样与采用了多摩川协议的编码器“对话”呢?

多摩川通讯协议

下图所示是多摩川通讯协议。
图片3
简单来说就是MCU发出一条CF指令,编码器就会接着返回一组报文,报文中包含CF、SF、DF以及CRC等内容。

  • CF
    在这里插入图片描述
    上图所示为多摩川文档对CF指令做出的解释。
    图中给出的bit位是线路上面的传送顺序,而STM32的串口通讯是小端模式。也就是先传输的是低字节,每个字节里先传输的也是低位。这也很好理解,硬件嘛,对于依次接收的每一位,都是由低地址到高地址保存下来的。所以字节之间的读取顺序和字节里每一位的读取顺序应该是一致的,那么就是小端模式。

    总的来说就是ID0=0x02,ID3=1A。这两个是我们经常用到的两个指令。
    需要说明的是,编码器返回的CF与MCU发出的CF是一致的,便于我们进行通讯检查。

  • SF
    SF是状态位,反应了编码器的状态,包括编码器是否过热、电池供电是否正常以及数据的解析是否正确等。
    在这里插入图片描述

  • DF
    根据MCU发出的CF的不同,编码器返回的DF也会随之而不同,具体的对应状态如下图所示。
    在这里插入图片描述
    ABS0~ABS2:表达的是编码器的单圈值。再一次,因为串口的传输是小端通讯,因此
    编码器单圈位置值 = (ABS2 << 16) | (ABS1 << 8) | (ABS0 << 0)

    ABM0~ABM2: 表达的是编码器的圈数值。
    圈数 = (ABM2 << 16) | (ABM1 << 8) | (ABM0 << 0)

    ALMC:编码器错误,每一位表达了不同的错误。
    在这里插入图片描述

  • CRC
    在这里插入图片描述
    同样是小端,计算方法在图中。

  • 7
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是基于 STM32F405 定时器3 的 PWM 输出代码示例: ```c #include "stm32f4xx.h" void PWM_Init(void) { // 使能 GPIOB 时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // 使能定时器3时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // 配置 GPIOB 引脚为复用模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); // 将 GPIOB 引脚连接到 TIM3 的通道2和通道3 GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM3); GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_TIM3); // 配置定时器3的时基 TIM_TimeBaseStructure.TIM_Period = 10000 - 1; // PWM 周期为 10ms TIM_TimeBaseStructure.TIM_Prescaler = 168 - 1; // 定时器时钟为 168MHz,分频系数为 168,得到 1MHz 的计数频率 TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); // 配置 TIM3 的通道2和通道3的 PWM 模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 5000 - 1; // 占空比为 50% TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC3Init(TIM3, &TIM_OCInitStructure); // 使能定时器3的通道2和通道3 TIM_CCxCmd(TIM3, TIM_Channel_2, TIM_CCx_Enable); TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Enable); // 启动定时器3 TIM_Cmd(TIM3, ENABLE); } ``` 在该代码中,我们使用了定时器3来控制 GPIOB 的引脚0和引脚1的 PWM 输出。其中,我们使用了STM32F405的168MHz时钟源,将定时器3的时钟分频为1MHz,设置了10ms的PWM周期和50%的占空比。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值