STM32HAL库 总线舵机驱动库的编写

本文介绍了如何使用STM32 HAL库编写串行总线舵机驱动程序,包括硬件配置、电路原理、通信协议以及Cube MX和程序详细步骤。通过对USART1和USART3的配置,实现半双工UART异步串行总线通讯,支持多个舵机的精确控制。
摘要由CSDN通过智能技术生成

STM32 HAL库 总线舵机驱动库的编写


1 理论基础

1.1 硬件

版本一:幻尔串行总线舵机、亚博智能 ROS机器人控制器STM32主控

在这里插入图片描述
在这里插入图片描述

版本二:串行总线舵机、任意型号的STM32开发板、SN74AHC1G04DBV(单路反相器)、74HC126D(缓冲器)、MF-MSMF300自恢复保险丝等

1.2 电路图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0gy0zoRW-1684223384004)(C:\Users\77454\AppData\Roaming\Typora\typora-user-images\image-20230515093301452.png)]

1.3 原理

本次所用的舵机为串行总线舵机,采用异步串行总线通讯方式,理论多至 253 个机器人舵机可以通过总线组 成链型,一条总线上允许挂载多个舵机,且每个舵机均有一个唯一ID(0~253),通过 UART 异步串行接口统一控制。

每个舵机可以设定不同的节点地址,多个舵机可以统一运动也可以单个独立控制。通过异步串行接口与用户的上位机(控制器或PC机)通讯,可对其进行参数设置、功能控制。通过异步串行接口发送指令,可以设置为电机控制模式或位置控制模式。

在电机控制模式下,可以作为直流减速电机使用,速度可调;在位置控制模式下,拥有 0-240° 的转动范围,外加±30°的偏差可调范围,在此范围内具备精确位置控制性能,速度可调。只要符合协议的半双工UART异步串行接口都可以和舵机进行通讯,对舵机进行各种控制。

原理图如上图所示,舵机用程序代码对UART(本次示例中使用USART3)异步串口进行时序控制,实现半双工异步串行总线通讯,即半双工的主从问答式通信,通信波特率为115200bps。

原理可以理解为:舵机控制器作为主机发送读写指令给舵机,舵机作为从机根据具体情况执行相应动作或应答。

1.4 通信协议

(1)指令包格式

帧头 ID号 数据长度 指令 参数 校验和
0x55 0x55 ID Length Cmd Prm 1…Prm N Checksum
  • 帧头:连续收到两个 0x55 ,表示有数据包到达。
  • ID: 每个舵机都有一个 ID 号。ID 号范围 0~253,转换为十六进制 0x00~0xFD。 广播 ID: ID 号254(0xFE) 为广播 ID,若控制器发出的ID号为 254(0xFE),所有的舵机均接收指令,但都不返回应答信息,(读取舵机 ID 号除外,具体说明参见下面指令介绍)以防总线冲突。
  • 数据长度:等于待发送的数据(包含本身一个字节)长度,即数据长度Length加3等于这一包指令的长度,从帧头到校验和。
  • 指令:控制舵机的各种指令,如位置、速度控制等。
  • 参数:除指令外需要补充的控制信息。
  • 校验和:校验和 Checksum,计算方法如下:Checksum = ~ (ID + Length + Cmd+ Prm1 + … Prm N)若括号内的计算和超出 255, 则取最低的一个字节,“~”表示取反。

(2)指令类型

指令有两种,写指令和读指令。

  • 写指令:后面一般带有参数,将相应功能的参数写进舵机,来完成某种动作。
  • 读指令:后面一般不带参数,舵机接收到读指令后会立即返回相应数据,返回的指令值和发送给舵机的“读指令”值相同,并且带有参数。所以上位机发送读指令后要立马准备将自己变为读取状态。

2 程序编写

2.1 cube mx设置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zorh0bb7-1684223384005)(assets/image-20230516151529723.png)]

(1)USART1设置
  • 串口1模式配置为同步通讯,波特率改为115200bps,数据宽度8位,检验None,停止位1位
    在这里插入图片描述

  • 增加DMA发送通道
    在这里插入图片描述

  • 打开串口1中断设置
    在这里插入图片描述

(2)USART3设置
  • 串口3模式配置为同步通讯,波特率改为115200bps,数据宽度8位,检验None,停止位1位
    在这里插入图片描述

  • 由于默认串口3引脚是PB10和PB11,而扩展版原理图钟串口3连接的是PC10和PC11,所以串口需要重映射。

    先点击PC11引脚,然后选择USART3_RX,这样操作后,串口3的引脚就会被重映射为PC10和PC11了。
    在这里插入图片描述

  • 打开串口3中断设置

在这里插入图片描述


2.2 程序编写

(1)bsp_key.c
#include "bsp_key.h"
#include "bsp.h"


// 判断按键是否被按下,按下返回KEY_PRESS,松开返回KEY_RELEASE
// Determine if the key is pressed, press to return KEY_PRESS, release to return KEY_RELEASE  
static uint8_t Key1_is_Press(void)
{
   
	if (!HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin))
	{
   
		return KEY_PRESS; // 如果按键被按下,则返回KEY_PRESS
	}
	return KEY_RELEASE;   // 如果按键是松开状态,则返回KEY_RELEASE
}


// 读取按键K1的状态,按下返回KEY_PRESS,松开返回KEY_RELEASE. 
// mode:设置模式,0:按下一直返回KEY_PRESS;1:按下只返回一次KEY_PRESS
// Read the state of key K1, press down to return KEY_PRESS, release to return key_release. 
// mode: setting mode, 0: press down to return KEY_PRESS;  1: KEY_PRESS is returned only once  
uint8_t Key1_State(uint8_t mode)
{
   
	static uint16_t key1_state = 0;

	if (Key1_is_Press() == KEY_PRESS)
	{
   
		if (key1_state < (mode + 1) * 2)
		{
   
			key1_state++;
		}
	}
	else
	{
   
		key1_state = 0;
	}
	if (key1_state == 2)
	{
   
		return KEY_PRESS;
	}
	return KEY_RELEASE;
}


/*********************************************END OF FILE**********************/

(2)bsp_key.h
#ifndef __BSP_KEY_H__
#define __BSP_KEY_H__

#include "gpio.h"


#define KEY_PRESS           1
#define KEY_RELEASE         0

#define KEY_MODE_ONE_TIME   1
#define KEY_MODE_ALWAYS     0


uint8_t Key1_State(uint8_t mode);


#endif /* __BSP_KEY_H__ */

(3)bsp_uart.c
/*
 * bsp_uart.c
 *
 *  Created on: Mar 4, 2022
 *      Author: Administrator
 */

#include "bsp_uart.h"
#include "bsp.h"

#define ENABLE_UART_DMA    1

uint8_t RxTemp = 0;
uint8_t RxTemp_3 = 0;
uint8_t UART_RX_BUF[16];
bool isUartRxCompleted= false;

// Initialize USART1  初始化串口1
void USART1_Init(void)
{
   
    HAL_UART_Receive_IT(&huart1, (uint8_t *)&RxTemp, 1);
}

// The serial port sends one byte  串口发送一个字节
void USART1_Send_U8(uint8_t ch)
{
   
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
}

// The serial port sends a string of data  串口发送一串数据
void USART1_Send_ArrayU8(uint8_t *BufferPtr, uint16_t Length)
{
   
    #if ENABLE_UART_DMA
    HAL_UART_Transmit_DMA(&huart1, BufferPtr, Length);
    #else
    while (Length--)
    {
   
        USART1_Send_U8(*BufferPtr);
        BufferPtr++;
    }
    #endif
}

// Initialize USART3  初始化串口3
void USART3_Init(void)
{
   
    HAL_UART_Receive_IT(&huart3, (uint8_t *)&RxTemp, 1);
}

// The serial port sends one byte  串口发送一个字节
void USART3_Send_U8(uint8_t ch)
{
   
    HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
}

// The serial port sends a string of data  串口发送一串数据
void USART3_Send_ArrayU8(uint8_t *BufferPtr, uint16_t Length)
{
   
    while (Length--)
    
你可以使用STM32微控制器来控制总线舵机。一种常用的总线协议是I2C(Inter-Integrated Circuit),它可以实现多个设备通过同一根总线进行通信。 首先,确保你的STM32微控制器已经连接到舵机的I2C总线上。然后,你需要在STM32上配置I2C外设,并编写代码来与舵机进行通信。 以下是一个简单的示例代码,展示了如何使用STM32HAL库来控制I2C总线舵机的位置: ```c #include "stm32f4xx_hal.h" #define SERVO_I2C_ADDRESS 0x40 // 舵机的I2C地址 I2C_HandleTypeDef hi2c1; // 初始化I2C外设 void I2C_Init() { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 400000; // I2C总线速度为400kHz hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; HAL_I2C_Init(&hi2c1); } // 控制舵机位置 void SetServoPosition(uint8_t position) { uint8_t data[2]; data[0] = 0x00; // 寄存器地址为0 data[1] = position; // 设置舵机位置 HAL_I2C_Master_Transmit(&hi2c1, SERVO_I2C_ADDRESS, data, 2, 100); } int main(void) { HAL_Init(); // 初始化I2C外设 I2C_Init(); // 设置舵机位置为90度 SetServoPosition(90); while (1) { // 主循环 } } ``` 请注意,这只是一个简单的示例代码,你可能需要根据你的具体舵机型号和需求进行适当的修改。另外,确保连接正确的I2C总线和正确的舵机地址。 希望这个示例能帮到你!如有任何疑问,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZRob

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值