STM32使用PWM控制舵机

系列文章目录

STM32单片机系列专栏

C语言术语和结构总结专栏


文章目录

1. 舵机简介

2. 硬件连接

3. 代码实现

3.1 PWM.c

3.2 PWM.h

3.3 Servo.c

3.4 Servo.h

3.5 main.c

3.6 完整工程文件


PWM和OC输出详解:

STM32定时器的OC比较和PWM​​​​​​​

1. 舵机简介

舵机是一种位置伺服驱动器器,并且是一种根据输入PWM信号占空比来控制输出角度的装置。通过PWM向伺服器发送一个控制信号时,输出轴就可以转到特定的位置。只在控制信号持续不变,伺服机构就会保持相对的角度位置不变。如果控制信号发生变化,输出轴的位置也会相应发生变化。

图片中的舵机型号为SG90,具有三根输入线:电源线,地线和信号线,PWM就是输入到信号线来控制舵机。控制信号进入内部驱动电路以后,获得直流偏置电压,从而产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。电压差的正负输出到电机驱动芯片决定电机的正反转,并且内部有一个电位器,用来检测当前舵机的角度。

输入PWM信号要求为:周期为20ms,高电平宽度为0.5ms - 2.5ms,也就是说周期是20ms,如果高电平时0.5ms,那么舵机输出轴转角为 -90°。

2. 硬件连接

本文是以STM32F103C8T6作为主控芯片,通过PA0端口输出PWM,实现控制180°舵机。

实际应用时,电源线连接5V,GND连接单片机的GND,PWM只是一个通信线,不需要大功率,所以PWM信号线连接单片机的一个引脚。

STM32舵机
5V+5V
GNDGND
PA0PWM

3. 代码实现

这里实现的功能为:按键控制舵机角度,每次按下舵机的角度增加30°,并且通过oled显示。要使用的库函数文件依然为:stm32f10x_tim.h,拖到最下面,在这里可以找到定时器TIM需要使用到的函数。

3.1 PWM.c

#include "stm32f10x.h" //PWM初始化
void PWM_Init(void)
{//开启时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);			//开启TIM2的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟//GPIO初始化GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);							//将PA1引脚初始化为复用推挽输出	//受外设控制的引脚,均需要配置为复用模式//配置时钟源TIM_InternalClockConfig(TIM2);		//选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟//时基单元初始化TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;				//计数周期,即ARR的值TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;				//预分频器,即PSC的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元//输出比较初始化TIM_OCInitTypeDef TIM_OCInitStructure;							//定义结构体变量TIM_OCStructInit(&TIM_OCInitStructure);                         //结构体初始化,若结构体没有完整赋值//则最好执行此函数,给结构体所有成员都赋一个默认值//避免结构体初值不确定的问题TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;               //输出比较模式,选择PWM模式1TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;       //输出极性,选择为高,若选择极性为低,则输出高低电平取反TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   //输出使能TIM_OCInitStructure.TIM_Pulse = 0;								//初始的CCR值TIM_OC2Init(TIM2, &TIM_OCInitStructure);                        //将结构体变量交给TIM_OC2Init,配置TIM2的输出比较通道2//TIM使能TIM_Cmd(TIM2, ENABLE);			//使能TIM2,定时器开始运行
}//PWM设置CCR
void PWM_SetCompare2(uint16_t Compare)
{TIM_SetCompare2(TIM2, Compare);		//设置CCR2的值
}

RCC_APB1PeriphClockCmd

  • TIM2 代表定时器2,它是STM32的一个基础硬件定时器。在STM32的某些系列中,TIM2连接到的是APB1总线。
  • ENABLE 是一个宏定义,用来开启某项功能,这里用来开启TIM2的时钟。如果传递 DISABLE 则会关闭外设的时钟。
  • 简单来说,RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 这行代码的作用是开启连接到APB1总线的定时器2(TIM2)的时钟。只有开启了时钟,程序中关于TIM2的其他功能(如计时、计数、PWM发生等)才能正常工作。

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  • GPIO的初始化中,选择AF_PP复用推挽输出,因为对于普通的开漏推挽输出,引脚的控制权是来自于输出数据寄存器的,如果想用定时器来控制引脚,就需要使用复用开漏/推挽输出模式。

时基单元中的数值设置:

代入公式为:

  • 频率 = CK_PSC(72M) / (PSC + 1) / (ARR + 1) = 50
  • 占空比 = CCR / (ARR + 1) 
  • 分辨率为 = 1 / (ARR + 1)
  • 因为PSC和ARR的值不固定,所以通过验证得出最适合的值为:ARR = 20000, PSC = 71,这时,ARR的20000代表20ms,如果CCR = 500,就是0.5ms,对应0°(-90),CCR = 2500,就是2.5ms,对应180°(+90)

3.2 PWM.h

接着是PWM.h文件,这部分引用声明一下即可

#ifndef __PWM_H
#define __PWM_Hvoid PWM_Init(void);
void PWM_SetCompare2(uint16_t Compare);#endif

 

3.3 Servo.c

这部分是舵机的角度参数设置代码: 

#include "stm32f10x.h"                  // Device header
#include "PWM.h"//函    数:舵机初始化
void Servo_Init(void)
{PWM_Init();									//初始化舵机的底层PWM
}//舵机设置角度
void Servo_SetAngle(float Angle)
{PWM_SetCompare2(Angle / 180 * 2000 + 500);	//设置占空比//将角度线性变换,对应到舵机要求的占空比范围上
}

0°代表500,180°代表2500,角度相差180,CCR相差2000,所以角度除以180再乘以2000,加上偏移500。例如角度为180,180/180*2000 + 500 = 2500,对应180°

3.4 Servo.h

同样进行声明

#ifndef __SERVO_H
#define __SERVO_Hvoid Servo_Init(void);
void Servo_SetAngle(float Angle);#endif

3.5 main.c

使用刚刚编写的PWM和舵机代码函数来实现功能:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "Key.h"uint8_t KeyNum;			//定义用于接收键码的变量
float Angle;			//定义角度变量int main(void)
{//模块初始化OLED_Init();		//OLED初始化Servo_Init();		//舵机初始化Key_Init();			//按键初始化//显示静态字符串OLED_ShowString(1, 1, "Angle:");	//1行1列显示字符串Angle:while (1){KeyNum = Key_GetNum();			//获取按键键码if (KeyNum == 1)				//按键1按下{Angle += 30;				//角度变量自增30if (Angle > 180)			//角度变量超过180后{Angle = 0;				//角度变量归零}}Servo_SetAngle(Angle);			//设置舵机的角度为角度变量OLED_ShowNum(1, 7, Angle, 3);	//OLED显示角度变量}
}

3.6 完整工程文件

STM32通过PWM驱动舵机

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/4786.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS 7虚拟机配置过程中所需组件的安装(二)

1.安装net-tools组件(解决无 ifconfig) # yum install net-tools 2.安装gcc、c编译器以及内核文件 # yum -y install gcc gcc-c kernel-devel 验证安装成功 3.安装nano(文本编辑器) # yum install nano

python监听html click教程

👽发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Python实现监听HTML点击事件 在Web开发中,经常需要在用户与页面交互时执行一些…

500V 直流充电桩测试负载箱的基础知识

500V直流充电桩测试负载箱是一种专门用于测试和验证直流充电桩性能的设备。它能够模拟真实的充电过程,对充电桩的输出电压、电流、功率等参数进行精确的测量和控制,以确保充电桩的稳定性和安全性。 一、工作原理 500V直流充电桩测试负载箱主要由电源模块…

【Linux】Linux上如何挂载磁盘

目录 一、查看磁盘使用情况df -h 查看已挂载磁盘的大概使用情况fdisk -l 查看主机上所有磁盘设备的详细情况lsblk 查看主机上所有磁盘设备基本信息 二、进行磁盘挂载mkfs 在特定的分区上建立 linux 文件系统mount 进行磁盘挂载文件系统配置 一、查看磁盘使用情况 df -h 查看已…

3分钟了解拍摄VR全景需要哪些硬件

VR全景图片是一张水平方向360度,垂直方向180度, 图片尺寸宽高比为2:1的图片。 通过720yun APP或720yun官网上传生成全景H5页面,即可360度全方位观看画面中的景象。 拍摄VR全景有很多方法,下面介绍用单反相机、全景相机、智能手机…

OceanBase开发者大会实录-杨传辉:携手开发者打造一体化数据库

本文来自2024 OceanBase开发者大会,OceanBase CTO 杨传辉的演讲实录—《携手开发者打造一体化数据库》。完整视频回看,请点击这里>> 各位 OceanBase 的开发者,大家上午好!今天非常高兴能够在上海与大家再次相聚&…

使用这 7 个绩效评估模板简化您的员工评估

绩效评估受到了不好的评价;员工发现它们压力很大,而管理者则发现它们很耗时。 但随着绩效管理成为 2024 年人力资源的首要任务,也许是时候重新思考了。绩效评估模板可以帮助减轻评估过程的麻烦。通过为管理者提供一种简单、标准化的方法来评…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 4月29日,星期一

每天一分钟,知晓天下事! 2024年4月29日 星期一 农历三月廿一 1、 移民管理局:5月6日起换发补发出入境证件可“全程网办”。 2、 文旅部宣布恢复两岸旅游新措施:将率先恢复福建居民到马祖旅游。 3、 网信办:整治用夸…

微软最新季度业绩结果充分说明了云和AI的增长、谷歌和AWS的竞争

微软最新的季度业绩超出了华尔街的各种预期,但对其服务合作伙伴来说,最重要的是这家科技巨头的预期:人工智能不仅能够增长,而且其云产品尚未达到稳定状态——人工智能是云的潜在增长加速器。 周五的一份分析师报告称,…

yo!这里是网络入门初识

目录 前言 基本概念 网络 协议 地址 网络传输流程 OSI七层模型 TCP/IP四层(五层)模型 流程图 数据封装&&分用 后记 前言 对于上一个专栏——Linux操作系统,我们学习了操作系统的基础知识以及基本的系统编程,其…

setTimeout回调函数 this指向问题

本文主要介绍setTimeout的回调函数的this指向问题 例子1:回调函数是一个普通函数 setTimeout 的回调函数是一个普通函数,而不是箭头函数,因此它有自己的上下文,this 指向全局对象(在浏览器中是 window 对象&#xff…

挤压激励注意力 SE | Squeeze-and-Excitation Networks

论文名称:《Squeeze-and-Excitation Networks》 论文地址:https://arxiv.org/pdf/1709.01507.pdf 代码地址: https://github.com/hujie-frank/SENet 卷积神经网络 (CNN) 的核心构建块是卷积运算符,它使网络能够通过在每一层的局…

Linux进程基础概念子进程的创建

有着上一节我们对操作系统和冯诺依曼体系结构的理解,本篇我们便可以开始对 Linux 中的进程开始讲解。在本篇中对进程的基本概念进行了简单的介绍,然后通过对描述进程的 PCB,与 Linux 中的 task_struct 的详细讲解,使得对进程的概念…

Android Widget开发代码示例详细说明

因为AppWidgetProvider扩展自BroadcastReceiver, 所以你不能保证回调函数完成调用后,AppWidgetProvider还在继续运行。 a. AppWidgetProvider 的实现 /*** Copyright(C):教育电子有限公司 * Project Name: NineSync* Filename: SynWidgetProvider.java * Author(S…

界面组件DevExpress Blazor UI v23.2 - 网格、工具栏功能全新升级

DevExpress Blazor UI组件使用了C#为Blazor Server和Blazor WebAssembly创建高影响力的用户体验,这个UI自建库提供了一套全面的原生Blazor UI组件(包括Pivot Grid、调度程序、图表、数据编辑器和报表等)。 DevExpress Blazor控件目前已经升级…

数字文旅重塑旅游发展新生态:以数字化转型为契机,推动旅游产业的创新发展,提升旅游服务的智能化、网络化和个性化水平

目录 一、引言 二、数字化转型推动旅游产业创新发展 1、数字化转型提升旅游产业效率 2、数字化转型拓展旅游产业边界 3、数字化转型促进旅游产业可持续发展 三、提升旅游服务智能化、网络化和个性化水平 1、智能化提升旅游服务体验 2、网络化拓宽旅游服务渠道 3、个性…

爬虫的实战应用之短信炸弹playwright现代网页测试工具

不讲废话,先上原理: 短信炸弹,也就是说持续对一个手机进行发送短信,实现的方式就是,利用某些网站的登录 ,注册的时候,发送短信验证码来实现。 如下图,其中有一个id为phone的输入框&a…

配置nodejs的俩小脚本

介绍:共两个脚本。 脚本1,用来配置环境变量,生成环境变量所需的配置信息,然后自己添加到系统环境变量里去 特别注意:该脚本需要放到nodejs目录下面,如果不是,则无法生成环境变量配置文本内容 另…

Java代码审计-flink-streaming-platform-web

前言 项目地址:GitHub - zhp8341/flink-streaming-platform-web: 基于flink的实时流计算web平台 flink-streaming-platform-web是一个将flink封装的一个可视化的、轻量级的flink web客户端系统,用户只需在web 界面进行sql配置就能完成流计算任务。 项目…

【Elasticsearch<一>✈️✈️】简单安装使用以及各种踩坑

目录 🍸前言 🍻一、软件安装(Windows版) 1.1、Elasticsearch 下载 2.1 安装浏览器插件 3.1、安装可视化工具 Kibana 4.1、集成 IK 分词器 🍺二、安装问题 🍹三、测试 IK 分词器 ​🍷 四、章…