栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

STM32+DMA串口+RC信号控制舵机

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

STM32+DMA串口+RC信号控制舵机

文章目录
  • 前言
  • 一、RC遥控器PWM信号
  • 二、关于舵机
  • 三、STM32串口DMA
  • 四、CUBEMX配置设置
  • 五、串口+DMA通讯
  • 六、PWM输出
  • 七、串口控制舵机
  • 八、通讯测试
  • 九、PWM输出测试
  • 十、舵机测试
  • 总结


前言

给学校团队成员培训的内容
YC YC


一、RC遥控器PWM信号

根据航模标准,PWM信号线的频率应该是50Hz,对应的每个周期总时长是20ms,输出到舵机的油门线(控制线,也就是细细的,除了红的是接5V电源,黑的GND,另外那个就是数据线)。
这是航模无线遥控模型的一个标准。信号的有效值与1ms~ 2ms的脉宽有关,与脉冲重复率无关。1~ 2ms的方波脉宽渐变过程对应信号的从小到大的渐变。 脉宽的幅度2.5V~ 6V;所以3~5V工作电压的单片机都适用。
这个PWM信号标准不仅对航模舵机适用对航模电调、飞控同样适用。

二、关于舵机

舵机知识

三、STM32串口DMA

串口DMA

四、CUBEMX配置设置

用定时器2输出PWM信号,其配置如下图

使用串口1作为控制串口,其配置如下图中


在NVIC配置中打开串口1的中断

五、串口+DMA通讯

在usart.h文件适当位置添加下列代码

#include "stdio.h"

#define U1_BUFFER_SIZE 200 //定义最长接收字节
//定义u1_printf功能,兼容我们平时的使用习惯,功能与printf相似	                       
#define u1_printf(...)    HAL_UART_Transmit_DMA(&huart1,
										      (uint8_t *)u1_printf_buf,
										      sprintf((char*)u1_printf_buf,__VA_ARGS__))
	
extern uint8_t u1_rx_buf[U1_BUFFER_SIZE];//接收缓存
extern volatile uint8_t u1_rx_len;//接收长度
extern volatile uint8_t u1_recv_end_flag;//接收完成标志
extern uint8_t u1_printf_buf[U1_BUFFER_SIZE];//发送缓存

在usart.c文件适当位置添加下列代码

uint8_t u1_rx_buf[U1_BUFFER_SIZE];
volatile uint8_t u1_rx_len=0;
volatile uint8_t u1_recv_end_flag=0;
uint8_t u1_printf_buf[U1_BUFFER_SIZE];
	
  
	
	
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能idle中断
	HAL_UART_Receive_DMA(&huart1,u1_rx_buf,U1_BUFFER_SIZE);//打开DMA接收,数据存入rx_buffer数组中
  

在stm32f1xx_it.c文件中的串口中断函数修改如下

#include "usart.h"


void USART1_IRQHandler(void)
{
  
	uint32_t tmp_flag = 0;
	uint32_t temp;
	tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
	if((tmp_flag != RESET))//idle标志被置位
	{ 
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
		temp = huart1.Instance->SR;  //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
		temp = huart1.Instance->DR; //读取数据寄存器中的数据
		HAL_UART_DMAStop(&huart1); //
		temp  = hdma_usart1_rx.Instance->CNDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
		u1_rx_len =  U1_BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
		u1_recv_end_flag = 1;	// 接受完成标志位置1	
	 }
  
  HAL_UART_IRQHandler(&huart1);
  

  
}

之后便可以在引用了 usart.h 的文件下则可以通过判断u1_recv_end_flag标志位来知道是否完成串口数据接收,并可以调用u1_printf函数通过串口1发送数据。
例子如下

if(u1_recv_end_flag ==1)
	{
		u1_printf("rx_len=%drn%srn ",u1_rx_len,u1_rx_buf);//打印接收长度与接收数据
		for(uint8_t i=0;i
				u1_rx_buf[i]=0;//清接收缓存
			}
		u1_rx_len=0;//清除计数
		u1_recv_end_flag=0;//清除接收结束标志位
		HAL_UART_Receive_DMA(&huart1,u1_rx_buf,U1_BUFFER_SIZE);//重新打开DMA接收
	}
六、PWM输出

HAL_TIM_PWM_Start 使能PWM输出

HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);

__HAL_TIM_SetCompare 函数修改CCR,修改比较值,修改占空比

__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 100); //控制占空比

七、串口控制舵机

main函数中while代码

  int angle = 0;
  
  
  while (1)
  {
		if(u1_recv_end_flag ==1)
		{
			u1_printf("rx_len=%drn%srn ",u1_rx_len,u1_rx_buf);//打印接收长度与接收数据
			sscanf((char *)u1_rx_buf,"%drn",&angle);
			
			if(angle>100)angle = 100;
			else if(angle<0)angle = 0;
			
			__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 1000 + angle * 10); //控制占空比
			 
			memset(u1_rx_buf,0,200);
			u1_rx_len=0;//清除计数
			u1_recv_end_flag=0;//清除接收结束标志位
			HAL_UART_Receive_DMA(&huart1,u1_rx_buf,U1_BUFFER_SIZE);//重新打开DMA接收
		}
    
八、通讯测试


向串口发送0-100的数字 串口回复符合预期 通讯成功 注意选择发送新行

九、PWM输出测试


将PWM的输出口PA0和GND连接到示波器表笔的两端 上电观察示波器

示波器可以看到PA0脚的对地电压波形为PWM方波,频率为50Hz,高电平持续时间1.5ms

通过串口向单片机发送100,可以看到PWM波形的高电平持续时间变成2ms

同样通过串口向单片机发送100,可以看到PWM波形的高电平持续时间变成1ms
至此PWM输出测试完成

十、舵机测试


先对舵机进行接线黄色为信号线 红色为5V电源线 棕色为GND
完成接线后对系统进行上电,可以看到舵机旋转动作
通过串口向单片机发送控制指令,舵机也会有相应的运动动作。


总结

实验成功,加油诶!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/882884.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号