PWM实现电机的正反转和调速以及TIM定时器

news2024/11/15 16:31:22

pwm.c

#include "pwm.h"


/*
PWM --- PA2 --TIM2_CH3
//将电机信号控制一根接GND,一根接在PA2(TIM2_CH3),
输出PWM控制电机快慢
TIM2挂在APB1 定时器频率:84MHZ


*/
void Pwm_Init(void)
{
	GPIO_InitTypeDef  		GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef 		TIM_OCInitStruct;
	
	//2、使能定时器2和相关IO口时钟。
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	//3、使能GPIOA时钟:
	RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA,ENABLE);
	
	
	
	GPIO_InitStruct.GPIO_Pin	= GPIO_Pin_2; 						//引脚2
	GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_AF;       				//复用功能
	GPIO_InitStruct.GPIO_Speed	= GPIO_Speed_50MHz;					//速度
	GPIO_InitStruct.GPIO_OType	= GPIO_OType_PP;					//推挽
	GPIO_InitStruct.GPIO_PuPd	= GPIO_PuPd_UP;						//上拉
	//4、初始化IO口为复用功能输出。
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	
	
	//5、GPIOF9复用映射到定时器2选择哪个复用功能
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_TIM2); 
	
	//定时器2挂在APB1(42MHZ)  所以定时器频率:84MHZ
	TIM_TimeBaseInitStruct.TIM_Prescaler	= 84-1;  				//84分频  84MHZ/84=1MZ 
	TIM_TimeBaseInitStruct.TIM_Period		= 500-1;				//计数500 用时500us
	TIM_TimeBaseInitStruct.TIM_CounterMode	= TIM_CounterMode_Up; 	//向上计数
	TIM_TimeBaseInitStruct.TIM_ClockDivision= TIM_CKD_DIV1;			//分频因子
	//2、初始化定时器,配置ARR,PSC。
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
	
	
	TIM_OCInitStruct.TIM_OCMode			= TIM_OCMode_PWM1;  		//PWM模式1
	TIM_OCInitStruct.TIM_OCPolarity		= TIM_OCPolarity_High;		//极性电平 即输出的有效电平(电机需要的是高电平)
	TIM_OCInitStruct.TIM_OutputState    = TIM_OutputState_Enable; 	//通道使能
	//7、初始化输出比较参数: 0C3通道3
	TIM_OC3Init(TIM2, &TIM_OCInitStruct);
	
	//8、使能预装载寄存器: 
	TIM_OC3PreloadConfig(TIM2, 	TIM_OCPreload_Enable); 
	
	//9、使能自动重装载的预装载寄存器允许位	
	TIM_ARRPreloadConfig(TIM2,ENABLE);
		
	//10、使能定时器。
	TIM_Cmd(TIM2, ENABLE);

}

在这里,使用了TIM定时器,只能说像EXTI外部中断、TIM定时器这些是基础呀~

之前忘了写time.c的总结

以下是利用TIM定时器控制led灯的
/*

定时器4配置流程
	1、使能定时器时钟。
		   RCC_APB1PeriphClockCmd();
	2、初始化定时器,配置ARR,PSC。
		  TIM_TimeBaseInit();
	3、启定时器中断,配置NVIC。
		  NVIC_Init();
	4、设置 TIM4_DIER  允许更新中断
		TIM_ITConfig();
	5、使能定时器。
		  TIM_Cmd();
	6、编写中断服务函数。
		  TIMx_IRQHandler();
		  
		  */

#include "time.h"




/*

定时器TIM3挂APB1总线下,时钟频率:84MHZ

TIM3为16位定时器  最大计数值为:65535

*/
void Time3_Init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	NVIC_InitTypeDef  		NVIC_InitStruct;//定义结构体名称
	//1、能定时器时钟。
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	//1ms产生中断
	TIM_TimeBaseInitStruct.TIM_Prescaler	= 840-1;  				//84分频  84MHZ/840 = 100KHZ  100 000HZ
	TIM_TimeBaseInitStruct.TIM_Period		= 20000-1;				//计数1000 用时200ms
	TIM_TimeBaseInitStruct.TIM_CounterMode	= TIM_CounterMode_Up; 	//向上计数
	TIM_TimeBaseInitStruct.TIM_ClockDivision= TIM_CKD_DIV1;			//分频因子
	//2、初始化定时器,配置ARR,PSC。
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	

	
	//3、启定时器中断,配置NVIC。
	NVIC_InitStruct.NVIC_IRQChannel						= TIM3_IRQn;  	//选择通道
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority	= 2;			//抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority			= 2; 			//响应优先级
	NVIC_InitStruct.NVIC_IRQChannelCmd					= ENABLE;		//通道使能	
	//5、配置中断分组(NVIC),并使能中断。
	NVIC_Init(&NVIC_InitStruct);


	//4、设置 TIM3_DIER  允许更新中断
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	//5、使能定时器。
	TIM_Cmd(TIM3, ENABLE);


}




/*

定时器TIM4挂APB1总线下,时钟频率:84MHZ

TIM4为16位定时器  最大计数值为:65535

*/
void Time4_Init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	NVIC_InitTypeDef  		NVIC_InitStruct;
	//1、能定时器时钟。
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
	
	//1ms产生中断
//	TIM_TimeBaseInitStruct.TIM_Prescaler	= 84-1;  				//84分频  84MHZ/84 = 1MHZ  1us数一个数
//	TIM_TimeBaseInitStruct.TIM_Period		= 1000-1;				//计数1000 用时1ms
//	TIM_TimeBaseInitStruct.TIM_CounterMode	= TIM_CounterMode_Up; 	//向上计数
//	TIM_TimeBaseInitStruct.TIM_ClockDivision= TIM_CKD_DIV1;			//分频因子
//	//2、初始化定时器,配置ARR,PSC。
//	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStruct);
	
	//练习3
	
	TIM_TimeBaseInitStruct.TIM_Prescaler	= 8400-1;  				//84分频    84MHZ/8400 = 10KHZ  10000HZ
	TIM_TimeBaseInitStruct.TIM_Period		= 10000-1;				//计数10000 用时1s
	TIM_TimeBaseInitStruct.TIM_CounterMode	= TIM_CounterMode_Up; 	//向上计数
	TIM_TimeBaseInitStruct.TIM_ClockDivision= TIM_CKD_DIV1;			//分频因子
	//2、初始化定时器,配置ARR,PSC。
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStruct);	
	
	//3、启定时器中断,配置NVIC。
	NVIC_InitStruct.NVIC_IRQChannel						= TIM4_IRQn;  	//选择通道
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority	= 2;			//抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority			= 2; 			//响应优先级
	NVIC_InitStruct.NVIC_IRQChannelCmd					= ENABLE;		//通道使能	
	//5、配置中断分组(NVIC),并使能中断。
	NVIC_Init(&NVIC_InitStruct);


	//4、设置 TIM4_DIER  允许更新中断
	TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
	//5、使能定时器。
	TIM_Cmd(TIM4, ENABLE);


}	


//6、编写中断服务函数。1ms
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
	{
	
		//定时器处理事件
		GPIO_ToggleBits(GPIOA,GPIO_Pin_6);
	}
	TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}


//6、编写中断服务函数。1ms
void TIM4_IRQHandler(void)
{
	static int num=0;
	if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
	{
	if(num == 0)
		{
			GPIO_ResetBits(GPIOA, GPIO_Pin_7);//D31一灭4
			//GPIO_ToggleBits(GPIOF, GPIO_Pin_9);
			num++;
		}else
		{
			if(num == 4)
			{
			   num=0;
			}else
			{
			  num++;
			} 
			GPIO_SetBits(GPIOA, GPIO_Pin_7);//灭
		}
		//定时器处理事件
		//GPIO_ToggleBits(GPIOA,GPIO_Pin_7);
	}
	TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}

就是上两篇说到的,TIM定时器和EXTI外部中断都会用到NVIC和中断服务函数,配置流程差不多。

在PWM中TIM定时器的作用

TIM(定时器)在嵌入式系统中通常用于生成精确的时间延迟、定时触发等功能。

TIM2 被配置为 PWM 模式,用于生成 PWM 信号来控制电机的速度或位置。

具体来说,TIM 定时器的作用包括:

1. 生成定时的基准时钟信号:定时器可以生成一个基于系统时钟的定时信号,用于精确计时。这对于需要精确时间间隔的应用非常有用,比如周期性任务的触发

2. 生成 PWM 信号:定时器可以通过配置输出比较通道,生成 PWM(脉冲宽度调制)信号。PWM 信号的占空比可以通过定时器的参数配置来调整,从而控制电机的转速或位置

3. 产生精确的时间延迟:定时器可以用来产生精确的时间延迟,比如在需要精确控制时序的情况下,比如在通信协议中生成特定的时钟信号。

4. 实现定时触发功能:定时器可以配置为在达到特定时间后触发中断,用于执行定时任务。这对于需要周期性执行的任务非常有用,比如传感器数据的定时采集、周期性数据传输等。

总之,TIM 定时器在嵌入式系统中是非常重要的功能模块,它提供了精确的时间控制能力,可以满足各种定时、PWM 生成、延迟等需求。

在这个代码中,通过配置 TIM2 定时器和相关的输出比较通道,实现了 PWM 信号的生成,用于控制电机。

 

pwm.h

#ifndef __PWM_H
#define __PWM_H
#include "stm32f4xx.h"


void Pwm_Init(void);

#endif

 

main.c

#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "pwm.h"



//这是一个主函数
int main(void)
{
	
	u32 count = 0;
	
	//NVIC分组 抢占优先级两位:0~3  响应优先级两位:0~3 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	Delay_Init();
	Led_Init();
	Pwm_Init();
	
	
	//不断改变比较值CCRx,达到不同的占空比效果:
	TIM_SetCompare3(TIM2,499);
	
	
	//GPIO_ToggleBits(GPIOE,GPIO_Pin_14);
	while(1)
	{
		for(count=499; count>200; count -= 20)
		{
			TIM_SetCompare3(TIM2,count);
			delay_s(1);
		}
		
		
		
	}
	
	return 0;
}

反转只需将PA2和GND调换位置,从快速到慢速,或者从慢速到快速只需要更改count的数法。 

README

实现电机的正反转和调速只需要用到PWM和delay相关函数 (pwm.c、pwm.h、delay.c、delay.h还要main.c),其中在PWM中使用了TIM定时器、delay相关函数在上几篇(用systick定时器写的精准延时)。

我所实验成功的电机是这种:

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

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

相关文章

查询所有进程及线程端口占用情况,并关闭某端口的方法

** 查询所有进程及线程端口占用情况,并关闭某端口的方法 ** 1、windows 查系统下( cmd 模式下): 1)查询当前系统所有网络连接和监听端口以及对应的进程标识(PID): netstat -aon…

QT----基于QT的人脸考勤系统ubuntu系统运行,编译开发板

目录 1 Ubantu编译opencv和seetaface库1.1 Ubantu编译opencv1.2 Ubuntu编译seetaface1.3 安装qt 2 更改代码2.1 直接运行报错/usr/bin/ld: cannot find -lGL: No such file or directory2.2 遇到报错摄像头打不开2.3 修改部分代码2.4 解决中文语音输出问题 3 尝试交叉编译rk358…

电脑哥的励志创业路:蹭别人的电脑做抖店

我是王路飞。 没有一步到位的创业项目,也没有一击必中的解决方法,有的只是需要时刻解决的当下问题。 做事/创业/成长/生活/人生,都不要追求百分百的圆满,不要抱有一帆风顺的幻想,不要期待十全十美的结果。 它们的第…

毕业设计:日志记录编写(3/17起更新中)

目录 3/171.配置阿里云python加速镜像:2. 安装python3.9版本3. 爬虫技术选择4. 数据抓取和整理5. 难点和挑战 3/241.数据库建表信息2.后续进度安排3. 数据处理和分析 3/17 当前周期目标:构建基本的python环境:运行爬虫程序 1.配置阿里云pytho…

使用GaLore在本地GPU进行高效的LLM调优

训练大型语言模型(llm),即使是那些“只有”70亿个参数的模型,也是一项计算密集型的任务。这种水平的训练需要的资源超出了大多数个人爱好者的能力范围。为了弥补这一差距,出现了低秩适应(LoRA)等参数高效方法,可以在消费级gpu上对…

【Canvas与艺术】暗蓝网格汽车速度仪表盘

【关键点】 采用线性渐变色&#xff0c;使上深下浅的圆有凹下效果&#xff0c;使上浅下深的圆有凸起效果&#xff0c;两者结合就有立体圆钮的感觉。 【图例】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type&quo…

【Python机器学习系列】机器学习中的模型微调---随机搜索(案例+源码)

这是我的第245篇原创文章。 一、引言 如果探索的组合数量较少时&#xff0c;网格搜索是一种不错的方法&#xff0c;但当超参数的搜索范围较大时&#xff0c;通常会优先选择使用 RandomizedSearchCV 。它与 GridSearchCV 用法相似&#xff0c;但它不会尝试所有可能的组合&…

华为升级FIT AP示例(通过AC的命令行)

升级FIT AP示例&#xff08;通过AC的命令行&#xff09; 前提条件 从官网下载升级目标版本对应的系统软件包&#xff0c;保存在PC本地。如果下载的文件是压缩文件&#xff0c;则需要解压缩出系统软件包。 AP已在WAC上线。 背景信息 升级的过程是先将系统软件包传到设备上&…

微信小程序button动态跳转到页面

微信小程序中如何动态的跳转到某个页面。 目录 1、首先在js文件中定义事件函数 2、在页面中进行传参调用 3、其它跳转方法简单说明 1、首先在js文件中定义事件函数 goto(e){const urle.currentTarget.dataset.url;wx.navigateTo({url: url})}, 2、在页面中进行传参调用 &l…

C++之char16_t*与char*类型相互转换(二百六十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

国内ip修改用什么软件下载?

在特定情况下&#xff0c;可能需要修改你的国内IP地址以实现网络访问需求或绕过地域限制。许多软件和工具可以帮助你实现这一目标&#xff0c;无论是为了隐私保护还是访问特定内容。虎观代理小二将介绍一些推荐的软件下载途径&#xff0c;以便你修改国内IP地址。 1. IP代理软件…

深度解析:Elasticsearch写入请求处理流程

版本 Elasticsearch 8.x 原文链接&#xff1a;https://mp.weixin.qq.com/s/hZ_ZOLFUoRuWyqp47hqCgQ 今天来看下 Elasticsearch 中的写入流程。 不想看过程可以直接跳转文章末尾查看总结部分。最后附上个人理解的一个图。 从我们发出写入请求&#xff0c;到 Elasticsearch 接收请…

5个适用于 Windows/PC 的水印去除软件(视频/图像)

水印是文本、徽标、印记、图像或签名&#xff0c;通常叠加在视频、其他图像或具有较高透明度的 PDF 文档上。当您免费使用某些产品&#xff08;例如视频编辑器&#xff09;时&#xff0c;最终输出通常带有代表您使用的编辑器的水印。您可能需要出于您的目的从此类媒体文件中删除…

Django之Celery篇(三)

一、任务交给Celery Django任务交给Celery的方法和普通使用Celery任务的调用基本无区别,只是将执行代码的放到到View视图中 而获取结果,往往并不能把结果和第1次请求一起响应,若想获取结果是通过第2次请求获取结果 代码如下: from django.http import HttpResponsefrom …

我们是如何在 IDE 中设计 AutoDev 的 AI 编程开发智能体语言与框架?

上周微软发布了自家的 AI 编程和软件开发智能体框架&#xff1a;AutoDev&#xff0c;其与我们开发的 IDE 插件 AutoDev 有颇多的相似之处&#xff0c;特别是一些设计思路&#xff0c;以及在对于辅助软件开发任务的智能体以及一些基础设施上。 稍有不同的是&#xff1a; 交互介质…

Axure RP 9 for mac中文版密钥激活版下载

Axure RP 9是一款专业的快速原型设计工具&#xff0c;它可以帮助产品设计师、交互设计师和用户体验设计师等创建高保真度、交互性强的原型&#xff0c;以便在产品开发之前进行测试和用户验证。 软件下载&#xff1a;Axure RP 9 for mac中文版密钥激活版下载 该工具具有丰富的功…

微信小程序实现多张照片上传

hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff1a;code袁 &#x1f4a5; 所属专栏&…

python绘图matplotlib——使用记录1

本博文来自于网络收集&#xff0c;如有侵权请联系删除 使用matplotlib绘图 1 常用函数汇总1.1 plot1.2 legend1.3 scatter1.4 xlim1.5 xlabel1.6 grid1.7 axhline1.7 axvspan1.8 annotate1.9 text1.10 title 2 常见图形绘制2.1 bar——柱状图2.2 barh——条形图2.3 hist——直…

浏览器工作原理与实践--渲染流程(上):HTML、CSS和JavaScript,是如何变成页面的

在上一篇文章中我们介绍了导航相关的流程&#xff0c;那导航被提交后又会怎么样呢&#xff1f;就进入了渲染阶段。这个阶段很重要&#xff0c;了解其相关流程能让你“看透”页面是如何工作的&#xff0c;有了这些知识&#xff0c;你可以解决一系列相关的问题&#xff0c;比如能…

服务端高并发分布式结构

前言 本文以⼀个 “电子商务” 应用为例&#xff0c;介绍从⼀百个到千万级并发情况下服务端的架构的演进过程&#xff0c;同时列举出每个演进阶段会遇到的相关技术&#xff0c;让大家对架构的演进有⼀个整体的认知&#xff0c;方便⼤家对后续知识做深⼊学习时有⼀定的整体视野…