使用STM32 再实现PWM小车两轮分别调速

news2024/11/26 3:32:30

关于PWM调速的原理,其实在之前89C52开发小车的时候也已经详细的描述过,所以主要的区别还是STM32和89C52的PWM实现区别。

关于STM32的PWM实现,是从CubeMX的配置开始的:

CubeMX

1. 在上节的CubeMX项目基础上进行修改

2. 两路PWM分别选择TIM2的CH1(对应PA0)和 TIM2的CH2(对应PA1),PWM的周期为20ms,在Tclk = 72000 000的前提下,将PSC设置为7199;ARR设置为199

另外,还要强调一点和89C52控制小车调速不同的地方:

  • 89C52中,生成PWM波后,在有效电平期间,对控制电机的引脚写数据让轮子进行前进或后退
  • 而在STM32中我直接将控制电机的引脚配成了时钟的PWM波输出

所以:

我如果希望对“前进”调速,应该将两路的PWM的有效电平设置为LOW,并把PB1和PB10的GPIO初值设为HIGH

我如果希望对“后退”调速,应该将两路的PWM的有效电平设置为HIGH,并把PB1和PB10的GPIO初值设为LOW

此处,我希望对前进调速,所以“应该将两路的PWM的有效电平设置为LOW,并把PB1和PB10的GPIO初值设为HIGH

2.1 同时注意,由于刚刚配置了PA0和PA1为GPIO的输出,所以TIM2的CH1和CH2会自动分配到其他复用引脚上,所以要将PA0和PA1设置回TIM2的CH1和CH2输出:

 3. 惯例设置更新代码

Keil

ARR的199对应20ms,所以CCRx的值是0到199,每增加1就说明在一个周期(20ms)内,增加了 20/199 约等于0.1ms的 有效电平持续时间!

void speed_left(int speed) //speed就是CCRx的值,理论在0到199之间,实际最好大于130
{
	__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, speed);//左轮调速
}

void speed_right(int speed) //speed就是CCRx的值,理论在0到199之间,实际最好大于130
{
	__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, speed);//左轮调速
}


int main(void)
{
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //打开Timer2的1号Channel, 1号通道对应 左轮
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); //打开Timer2的2号Channel, 2号通道对应 右轮

  while (1)
  {	
		speed_left(140);
		speed_right(199);
  }
}

实现效果

可见,右轮速度全力运转而左轮则慢些,这就是PWM实现的两轮分别调速:

代码封装 

在代码测试成功后,将两轮分别调速的代码封装到motor.c中:

motor.c:

#include "motor.h"
#include "gpio.h"
#include "tim.h"

#define left_B_1A_HIGH HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET)
#define left_B_1A_LOW HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET)

#define left_B_1B_HIGH HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET)
#define left_B_1B_LOW HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET)

#define right_A_1A_HIGH HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET)
#define right_A_1A_LOW HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET)

#define right_A_1B_HIGH HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET)
#define right_A_1B_LOW HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET)



void move_backward(void) //后退
{
	left_B_1A_HIGH;
	left_B_1B_LOW;
	
	right_A_1A_HIGH;
	right_A_1B_LOW;
}
 
void move_forward(void) //前进
{
	left_B_1A_LOW;
	left_B_1B_HIGH;
	
	right_A_1A_LOW;
	right_A_1B_HIGH;
}
 
void move_leftturn(void) //左转
{
	left_B_1A_LOW; //左轮不动
	left_B_1B_LOW;
	
	right_A_1A_LOW; //右轮往前
	right_A_1B_HIGH;
}
 
void move_rightturn(void) //右转
{
	left_B_1A_LOW; //左轮往前
	left_B_1B_HIGH;
	
	right_A_1A_LOW; //右轮不动
	right_A_1B_LOW;
}
 
void move_stop(void) //停止
{
	left_B_1A_LOW;
	left_B_1B_LOW;
	
	right_A_1A_LOW;
	right_A_1B_LOW;
}

void speed_left(int speed) //speed就是CCRx的值,理论在0到199之间,实际最好大于130
{
	__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, speed);//左轮调速
}

void speed_right(int speed) //speed就是CCRx的值,理论在0到199之间,实际最好大于130
{
	__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, speed);//左轮调速
}

motor.h:

#ifndef __motor_H__ // "XXXX"就是h文件的名字
#define __motor_H__
 
void move_backward(void);
void move_forward(void);
void move_leftturn(void);
void move_rightturn(void);
void move_stop(void);

void speed_left(int speed);
void speed_right(int speed);
 
 
#endif 

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

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

相关文章

2023牛客暑期多校训练营2

题目顺序不分难度 KBox 状态dp,因为每个棋子只能移动到 i-1 到 i1的位置,所以直接用4个状态表示棋子在哪 f[i][0] 表示前i个位置中,i-1到i1都没有棋子 f[i][1] 表示前i个位置中,i-1有棋子 f[i][2] 表示前i个位置中&#xff0…

Autosar - PDUR简介与配置

文章目录 一、PDUR是什么二、不同报文类型的信号流ECUC(EcucPduCollection)三、时序图CanIfs之间的路由CanIf与Com之间的路由CanTp通道间的路由一、PDUR是什么 PDU Router(路由器)在本文将简称为PduR,在AUTOSAR的架构中,通信部份中很重要的一个模块就是PduR,它能将IPdu…

C++: day6

1 思维导图 2 顺序栈模板和顺序队列模板 #include <iostream>using namespace std;template <typename T> class My_stack { private:T *ptr; //指向堆区空间int top; //记录栈顶元素public://无参构造My_stack():ptr(new T[10]), top(-1){}//有参构造My_sta…

ROS-Moveit机械臂追踪二维码(四)

ROS-Moveit机械臂追踪二维码(四) 在仿真环境增加相机 <gazebo reference"camera_depth_frame"><sensor name"camera1" type"depth"><always_on>true</always_on><update_rate>20.0</update_rate><came…

多路选择器设计实现

文章目录 一、多路选择器二、二选一多路选择器三、四选一多路选择器设计 一、多路选择器 多路选择器是数据选择器的别称。在多路数据传送过程中&#xff0c;能够根据需要将其中任意一路选出来的电路&#xff0c;叫做数据选择器&#xff0c;也称多路选择器或多路开关。 二、二…

【从删库到跑路】MySQL数据库的索引(一)——索引的结构(BTree B+Tree Hash),语法等

&#x1f38a;专栏【MySQL】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出小吉的问题 文章目录 &#x1f354;概述&#x1f354;索引结构⭐B-Tree多路平衡查找树&#x1f3f3;️‍&a…

【分布式事务】CAP定理和Base理论

文章目录 1、事务的ACID原则2、分布式服务案例3、CAP定理4、Base理论5、分布式事务模型 1、事务的ACID原则 所有的事务都要满足ACID原则&#xff0c;在单体架构中&#xff0c;只有一个服务&#xff0c;这个服务访问一个数据库&#xff0c;场景简单。基于数据库本身的特性&…

React 组件使用

React 组件是一个 js 函数&#xff0c;函数可以添加 jsx 标记 当前页使用组件&#xff0c;基本使用 注意&#xff1a;组件的名称&#xff0c;第一个字母一定要大写&#xff0c;否则会报错 import { createRoot } from "react-dom/client"; import "./index.c…

深度学习(30)—— DeformableDETR(1)

深度学习&#xff08;30&#xff09;—— DeformableDETR&#xff08;1&#xff09; 原本想在一篇文章中就把理论和debug的过程都呈现&#xff0c;但是发现内容很多&#xff0c;所以就分开两篇&#xff0c;照常先记录理论学习过程&#xff0c;然后是实践过程。 注&#xff1a;…

Flutter学习—— Vscode创建项目

目录 一、Vscode创建项目 二、补充五种项目类型 Application: Module 模块开发&#xff0c; Package开发 Plugin 插件开发 Skeleton 骨架开发 一、Vscode创建项目 1.快捷键 CtrlShiftP 打开命令面板&#xff0c;选择新项目 2.选择需要开发的项目类型 Application 应用开…

勾股dev部署

1.克隆项目 项目的地址&#xff1a; https://gitee.com/gouguopen/dev?_fromgitee_search#-%E5%BC%80%E6%BA%90%E5%8A%A9%E5%8A%9B 可以采用git clone https://gitee.com/gouguopen/dev.git 或者使用下载压缩包的形式 2.进入项目的根目录 cd gougudev 3.下载php依赖 需要…

三种策略改进的沙猫群优化算法(MSCSO),与白鲸、蜣螂、麻雀等多种算法进行比较,MATLAB代码...

沙猫群优化算法(sand cat swarm optimiza⁃ tion,SCSO)是 2022年提出的元启发式优化算法&#xff0c;该算法灵感来源于沙猫的捕食行为&#xff0c;沙猫群会通过搜索阶段和捕食阶段获得食物。其中算法额外使用自适应的rG和R以达到搜索阶段和捕食阶段的无缝 切换。该算法具有寻优…

刷题日记09《图论基础》

图的存储结构 对于图结构而言&#xff0c;常见的存储结构主要有两种&#xff1a;邻接表和邻接矩阵&#xff1a; 邻接表很直观&#xff0c;我把每个节点 x 的邻居都存到一个列表里&#xff0c;然后把 x 和这个列表关联起来&#xff0c;这样就可以通过一个节点 x 找到它的所有相邻…

java 8树结构返回前端

接口&#xff1a; EntityResult getOrgReal(Map<String, Object> mapParam); 实现类&#xff1a; PMethodHandle(runMethodName "TQmsZjxmzbImpl.getOrgReal", timeout 600) Override public EntityResult getOrgReal(Map<String, Object> mapParam…

vs2015 工程组织与动态加载

10.Visual Studio动态加载_哔哩哔哩_bilibili 1.工程组织 ① researcher.cpp #include "nn/nn.h"#include "nn/factory.h" #include "nn/factory_impl/factory_impl.h"#include <iostream>int main() {int ret 0;factory_i* fct new f…

Invalid bound statement (not found),springboot扫描不到jar包中mapper文件的问题处理

参考这位大佬的博客&#xff1a;Invalid bound statement (not found)&#xff0c;springboot扫描不到jar包中mapper文件的问题处理_springboot扫描不到mapper_Jamesharden13的博客-CSDN博客 classpath:和classpath*:的区别_classpath和classpath*区别_明快de玄米61的博客-CSD…

JavaWeb课程设计项目实战(06)——项目编码实践3

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 在本教程教程中&#xff0c;我们实现学生列表的显示。 Student 请在bean包下创建Student类&#xff0c;代码如下&#xff1a; package com.cn.bean; /*** 本文作者&#…

MIMIC数据库申请流程

MIMIC是一个公开的临床数据库&#xff0c;之前查找了很多资料&#xff0c;在这里记录一下整个申请流程。 一、CITI证书 要申请mimic数据库的使用权限&#xff0c;首先需要有CITI证书&#xff0c;这是一个国际知名的网络训练课程&#xff0c;其中就有用于健康资讯隐私及保护 (…

Spring 用了哪些设计模式

关于设计模式&#xff0c;如果使用得当&#xff0c;将会使我们的代码更加简洁&#xff0c;并且更具扩展性。本文主要讲解Spring中如何使用策略模式&#xff0c;工厂方法模式以及Builder模式。 策略模式 关于策略模式的使用方式&#xff0c;在Spring中其实比较简单&#xff0c…

408-2009

一、选择题&#xff08;2 分/题&#xff09; 1.为解决计算机主机与打印机之间速度不匹配问题&#xff0c;通常设置一个打印数据缓冲区&#xff0c;主机将要输出的数据一次写入该缓冲取&#xff0c;而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是______。 A.栈 …