STM32使用PWM控制舵机

news2024/10/6 12:35:31

系列文章目录

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模式1
	TIM_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_H

void 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_H

void 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;				//角度变量自增30
			if (Angle > 180)			//角度变量超过180后
			{
				Angle = 0;				//角度变量归零
			}
		}
		Servo_SetAngle(Angle);			//设置舵机的角度为角度变量
		OLED_ShowNum(1, 7, Angle, 3);	//OLED显示角度变量
	}
}

3.6 完整工程文件

STM32通过PWM驱动舵机

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

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

相关文章

树莓派学习笔记--树莓派终端基本操作与系统备份(全卡备份,压缩备份)

树莓派终端基本操作 sudo su #切换为超级用户身份 su lyh #切换回普通用户lyh(用户名)#目录切换命令 pwd #显示当前所在目录 cd ~ #切换到主目录(/home/用户名),~也可省略不写 cd dir …

python程序设计语言超详细知识总结

Python 首先 python 并不是简单,什么语言都有基础和高级之分,要想掌握一门语言,必须把高级部分掌握才行。 HelloWorld helloWorld.py print(hello, world)数据类型与变量 变量的数据类型数据类型描述变量的定义方式整数型 (int)整数&…

OpenVINO安装教程 Docker版

从 Docker 映像安装IntelDistribution OpenVINO™ 工具套件 本指南介绍了如何使用预构建的 Docker 镜像/手动创建镜像来安装 OpenVINO™ Runtime。 Docker Base 映像支持的主机操作系统: Linux操作系统 Windows (WSL2) macOS(仅限 CPU exectuion) 您可以使用预…

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

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

实现堆的各种基本运算的算法(数据结构)

以小堆为例,大堆就举一反三了。 堆的物理结构就是普通的数组,但是逻辑结构看成了一颗完全二叉树。 小堆,就是树的每一个父节点都小于他的孩子节点。如图中第一排的a与b。大堆,就是树的每一个父节点都大于他的孩子节点。如图中第…

Mysql基础(三)DDL之create table语句

一 create table 创表 说明: create table相关语句从功能上进行讲解补充: 前面已经讲解过相关的约束,已进行相关的铺垫声明: 参考价值较少,了解即可 ① 基本语法 思考: 约束加在哪里? ② 创建新表 强调:使…

node环境创建Vue项目

node环境创建Vue项目 目录 node环境创建Vue项目安装node.js安装Vue创建Vue项目 安装node.js 【1】.官网下载 【2】.选择路径 【3】配置环境变量 后面就是一路next完成安装 【4】测试 cmd输入node指令,显示版本号证明安装成功 安装Vue 【1】安装cnpm 这是由淘宝…

8.SysTick定时器

SysTick为系统滴答定时器 定时器分类 内核级定时器(系统滴答定时器) 延时定时中断(给系统提供时钟节拍)给操作系统提供时基(任务调度)FreeRTOS UCOS5ms 基本定时器 延时定时中断时间片(实现两盏LED灯同时以一个不同速度闪烁,轮询…

超越GPT-4,清华发布网页导航智能体AutoWebGLM

随着大语言模型(LLMs)的发展,Agent在网络导航等任务中展现出了前所未有的能力。想象一下,一个基于LLM的Agent能够在你享用早餐时为你总结在线新闻,这样的场景已经不再遥不可及。这种将LLMs融入日常任务的做法&#xff…

1Panel - 现代化、开源的 Linux 服务器运维管理面板

产品介绍 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。 1Panel的官方网站:https://1panel.cn 1Panel的GitHub仓库:https://github.com/1Panel-dev/1Panel 体验环境:https://demo.1panel.cn 1Panel 特点 开源特性 Star 数…

LLaMA 3:大模型之战的新序幕

作者 | 符尧 OneFlow编译 翻译|杨婷、宛子琳、张雪聃 本文要点概览: 文本数据的扩展可能已经达到了极限,因为易于获取的网络文本资源(如Common Crawl、GitHub、ArXiv等)已基本被充分利用。 尽管如此,通过更…

JAVASE->数据结构|顺序表底层逻辑

✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 目标: 1. 什么是 List 2. List 常见接口介绍 3. …

js 中的非空断言操作符 (!.)叹号加点

js 中的非空断言操作符 (!.)叹号加点 在 TypeScript 或 JavaScript 中,!.并不是一个官方的语法结构。然而,!符号在 TypeScript 中确实有特定的用法,它被称为非空断言操作符。 !通常用作逻辑非操作符,用于…

cuda和cudnn的安装(ubuntu22.04环境)

一、安装准备 安装依赖 sudo apt-get update sudo apt-get install g sudo apt-get install gcc sudo apt-get install make禁用默认驱动 sudo gedit /etc/modprobe.d/blacklist.conf 在末尾加上 blacklist nouveau options nouveau modeset0更新一下initramfs -u的镜像 s…

自动驾驶横向控制算法

本文内容来源是B站——忠厚老实的老王,侵删。 三个坐标系和一些有关的物理量 使用 frenet坐标系可以实现将车辆纵向控制和横向控制解耦,将其分开控制。使用右手系来进行学习。 一些有关物理量的基本概念: 运动学方程 建立微分方程 主要是弄…

【跟我学RISC-V】认识RISC-V指令集并搭建实验环境

写在前面 现在计算机的体系架构正是发展得如火如荼的时候,占领桌面端市场的x86架构、占领移动端市场的arm架构、在服务器市场仍有一定地位的mips架构、国产自研的指令集loongarch架构、还有我现在要讲到的新型开源开放的RISC-V指令集架构。 我先说一说我的学习经历…

第9章 知识产权

一、著作权 (一)版权 版权,亦称“著作权”,符号:©。指作者或其他人(包括法人)依法对某一著作物享受的权利。 1、人身权 包括发表权、署名权、修改权、限制。发表权为著作人终身及其死后…

编程代码查重 比赛防作弊 图形界面代码查重工具SIM 支持c++ python java c语言下载

SIM,全称The software and text similarity tester SIM,是Dick grune开发的一款代码查重软件。比较轻量级,也被一些OJ集成用来查重(如hustoj)。但由于软件本身是命令行软件(就是小黑框框的那种)…

IDEA 中的奇技淫巧

IDEA 中的奇技淫巧 书签 在使用ctrlalt方向键跳转时,或者追踪代码时,经常遇到的情况是层级太多,找不到代码的初始位置,入口。可以通过书签的形式去打上一个标记,后续可以直接跳转到书签位置。 标记书签:c…

DevTools failed to load SourceMap: Could not load content for http://127.0.0

运行时报错: DevTools failed to load SourceMap: Could not load content for http://127.0.0.1:64311/.sourcemap/mp-weixin/pages/***/***.js.map: HTTP error: status code 403, net::ERR_HTTP_RESPONSE_CODE_FAILUREDevTools failed to load SourceMap: Could …