cubemx hal stm32 舵机 可减速 任意位置停止 驱动代码

news2024/11/26 22:18:16

舵机样图

CubeMX配置

对于 STM32 F407VE
定时器配置

这里的84是来自APB1那路2倍频得到:
定时器频率

代码部分

两个舵机都是180度的

servo.c

#include "servo.h"
#include "tim.h"
#include "stdio.h"

__IO uint32_t g_SteerUWT[2] = {0};
uint16_t g_SteerDeg[2] = {0};
uint8_t g_SteerSele[2] = {0};

uint16_t g_servoMidAngle[2] = {SERVO1_MID, SERVO2_MID};


/*对于 舵机 设置角度值*/


//# 设置频率为50hz也就是20ms一个周期,
//# 控制舵机范围是在0.5ms到2.5ms之间,也就是2.50%到12.50%之间
//# 最小精度是0.01ms,也就是0.05%
//# 对于20000:
//#			 0.05% ==   10
//# 		 2.50% ==  500
//#			12.50% == 2500
void servo_Init(void)
{
	HAL_TIM_Base_Start_IT(&SERVO1_TIM);	//开启定时器
	HAL_TIM_Base_Start_IT(&SERVO1_TIM);	//开启定时器

	HAL_TIM_PWM_Start(&SERVO1_TIM, SERVO1_CHANNEL);
	HAL_TIM_PWM_Start(&SERVO1_TIM, SERVO2_CHANNEL);

	SERVO_1 = g_servoMidAngle[0];
	SERVO_2 = g_servoMidAngle[1];
}

/*
seleSteer:选择不同舵机
val:500~2500对应0~180度
*/
void servo_value_set(uint8_t seleSteer, uint16_t val)
{
	g_SteerDeg[seleSteer] = val;	// val*10+500;
	g_SteerSele[seleSteer] = 1;
}

uint16_t servo_get_value(uint8_t seleSteer)
{
	uint32_t getVal;
	switch(seleSteer)
	{
		case SERVO1:
			getVal = SERVO_1;
			break;
		case SERVO2:
			getVal = SERVO_2;
			break;
		default:
			break;
	}
	printf("servo : %d\n", getVal);

	return (uint16_t)getVal;
}

void serco_clear_move(uint8_t seleSteer)
{
	g_SteerSele[seleSteer] = 0;
}

// 舵机缓慢移动循环
void servo_scan(void)
{
	uint8_t i=0;
	while(i < SERV0_MAX)
	{
		if(g_SteerSele[i] == 1)
		{
			if(g_SteerUWT[i] < uwTick - SERVO_RETARD_VAL)
			{
				g_SteerUWT[i] = uwTick;
			}
			else
			{
				goto scan1;
			}
			switch(i)
			{
				case SERVO1:
					if(SERVO_1<=g_SteerDeg[i])
					{
						SERVO_1 += 10;
						if(SERVO_1>g_SteerDeg[i])
						{
							g_SteerSele[i] = 0;
						}
					}
					else if(SERVO_1>g_SteerDeg[i])
					{
						SERVO_1 -= 10;
						if(SERVO_1<=g_SteerDeg[i])
						{
							g_SteerSele[i] = 0;
						}
					}
					break;
				case SERVO2:
					if(SERVO_2<=g_SteerDeg[i])
					{
						SERVO_2 += 10;
						if(SERVO_2>g_SteerDeg[i])
						{
							g_SteerSele[i] = 0;
						}
					}
					else if(SERVO_2>g_SteerDeg[i])
					{
						SERVO_2 -= 10;
						if(SERVO_2<=g_SteerDeg[i])
						{
							g_SteerSele[i] = 0;
						}
					}
					break;
				default:
					break;
			}
		}
scan1:
		i++;
	}
}



servo.h

#ifndef __SERVO_H_
#define __SERVO_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include "main.h"


#define SERVO1_TIM        htim2
#define SERVO1_CHANNEL    TIM_CHANNEL_1

#define SERVO2_TIM        htim2
#define SERVO2_CHANNEL    TIM_CHANNEL_2

#define SERVO_1		SERVO1_TIM.Instance->CCR1
#define SERVO_2		SERVO2_TIM.Instance->CCR2

// 舵机循环减速值,减速值越大速度越慢
#define SERVO_RETARD_VAL 2

// 左加右减
// 上加下减
typedef enum
{
	SERVO1_MID = 1500,	// 
	SERVO2_MID = 1500,	// 
}SERVO_MID_ANGLE;

typedef enum
{
	SERVO1,			// 底部舵机,决定x位置
	SERVO2,			// 顶部舵机,决定y位置
	SERV0_MAX    
}SERVO_NUM;

extern uint16_t g_servoMidAngle[2];


void servo_Init(void);
void servo_value_set(uint8_t seleSteer, uint16_t val);
uint16_t servo_get_value(uint8_t seleSteer);
void serco_clear_move(uint8_t seleSteer);
void servo_scan(void);

/*	//使用方法
	
初始化:
	servo_Init();

调用:
	// 选择舵机1,转动舵机范围为 500 -- 2500
	servo_value_set(seleSteer, val);

	// 获取舵机当前的占空比
	servo_get_value(seleSteer);
*/

#ifdef __cplusplus
}	/*extern "C"*/
#endif

#endif //__SERVO_H_


代码使用

初始化:

	// 舵机 初始化
	servo_Init();

循环:

	// 舵机循环
	servo_scan();

设置舵机占空比:

	// 选择舵机,转动舵机范围为 500 -- 2500
	servo_value_set(seleSteer, val);

获取舵机占空比:

	// 获取舵机当前的占空比
	servo_get_value(seleSteer);

使舵机停止在当前移动的位置:

serco_clear_move(seleSteer);

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

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

相关文章

开发一个RISC-V上的操作系统(七)—— 硬件定时器(Hardware Timer)

目录 往期文章传送门 一、硬件定时器 硬件实现 软件实现 二、上板测试 往期文章传送门 开发一个RISC-V上的操作系统&#xff08;一&#xff09;—— 环境搭建_riscv开发环境_Patarw_Li的博客-CSDN博客 开发一个RISC-V上的操作系统&#xff08;二&#xff09;—— 系统引导…

Monkey测试真的靠谱吗?

Monkey测试&#xff0c;顾名思义&#xff0c;就是模拟一只猴子在键盘上乱敲&#xff0c;从而达到测试被测系统的稳定性。Monkey测试&#xff0c;是Android自动化测试的一种手段&#xff0c;Monkey测试本身非常简单&#xff0c;Android SDK 工具支持adb Shell命令&#xff0c;实…

jvm里的内存溢出

目录 堆溢出 虚拟机栈和本地方法栈溢出&#xff08;栈溢出很少出现&#xff09; 方法区和运行时常量池溢出 本机内存直接溢出&#xff08;实际中很少出现、了解即可&#xff09; 堆溢出 堆溢出&#xff1a;最常见的是大list&#xff0c;list里面有很多元素 堆溢出该怎么解决…

C++红黑树

一、红黑树的概念 红黑树是一种二叉搜索树&#xff0c;在其每个节点上增加一个存储位用于表示节点的颜色&#xff0c;可以是Red或Black 通过对任何一条从根到叶子的路径上的各个节点着色方式的限制&#xff0c;红黑树确保没有一条路径比其他路径长两倍 红黑树的性质&#xff…

SQL | 汇总数据

9-汇总数据 9.1-聚集函数 在实际开发过程中&#xff0c;可能会遇到下面这些情况&#xff1a; 确定大于某个值的有多少行数据&#xff0c;比如游戏排行榜&#xff0c;查询玩家排行多少名。 获取表中某些行的和&#xff0c;比如双十一当天&#xff0c;某个用户总订单价格是多少…

208、仿真-51单片机脉搏心率与心电报警Proteus仿真设计(程序+Proteus仿真+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件设计 二、设计功能 三、Proteus仿真图 四、程序源码 资料包括&#xff1a; 需要完整的资料可以点击下面的名片加下我&#xff0c;找我要资源压缩包的百度网盘下载地址及提取码。 方案选择 单片机的选择 方案一&a…

回归预测 | MATLAB实现基于PSO-LSSVM-Adaboost粒子群算法优化最小二乘支持向量机结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于PSO-LSSVM-Adaboost粒子群算法优化最小二乘支持向量机结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于PSO-LSSVM-Adaboost粒子群算法优化最小二乘支持向量机结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考…

MySQL8安装和删除教程 保姆级(Windows)

下载 官网: mysql官网点击Downloads->MySQL Community(GPL) Downloads->MySQL Community Server(或者点击MySQL installer for Windows) Windows下有两种安装方式 在线安装 一般带有 web字样 这个需要联网离线安装 一般没有web字样 安装 下载好之后,版本号可以不一样&…

Web 自动化测试学会这一招,下班至少早一小时

♥ 前 言 大家都知道&#xff0c;我们在通过 Selenium 执行 Web 自动化测试时&#xff0c;每次都需要启动/关闭浏览器&#xff0c;如果是多线程执行还会同时打开多个&#xff0c;比较影响工作的正常进行。那有没有办法可以不用让浏览器的自动化执行干扰我们的工作呢&#xf…

graphab 教程 ——生成廊道

Graphab软件包括图谱创建、基于图谱的连通性计算、分析与推广、制图四个模块。Graphab软件的图谱创建基于栅格数据进行,包括斑块识别和连接建立两个步骤。Graphab 软件可识别的栅格数据格式包括TIFF、ASCI和RST,栅格像元记录数值用于识别斑块类型,识别规则可以选择四邻域或八邻…

B100-技能提升-线程池分布式锁

目录 线程池什么是线程池&#xff1f;为什么用线程池?线程池原理常见四种线程池和自定义线程池 线程池 什么是线程池&#xff1f; 池化技术 为什么用线程池? 1 由于设置最大线程数&#xff0c;防止线程过多而导致系统崩溃。 2 线程复用&#xff0c;不需要频繁创建或销毁…

WebAPIs 第三天

DOM 事件进阶 事件流事件委托其他事件元素尺寸与位置 一.事件流 事件流与两个阶段说明事件捕获事件冒泡阻止冒泡解绑事件 1.1 事件流与两个阶段说明 ① 事件流&#xff1a;指的是事件完整执行过程中的流动路径 ② 事件流分为捕获阶段和冒泡阶段 1.2 事件捕获 从DOM根元素…

opsForHash() 与 opsForValue 请问有什么区别?

&#x1f449;&#xff1a;&#x1f517;官方API参考手册 如图&#xff0c;opsForHash()返回HashOperations<K,HK,HV>但是 opsForValue()返回ValueOperations<K,V>… 区别就是opsForHash的返回值泛型中有K,HK,HV,其中K是Redis指定的某个数据库里面某一个关键字(由…

三分钟带你快速掌握MongoDB数据库和集合基础操作

文章目录 前言一、案例需求二、数据库操作1. 选择和创建数据库2. 数据库的删除 三、集合操作1. 集合的显式创建&#xff08;了解&#xff09;2. 集合的隐式创建3. 集合的删除 总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便…

太牛了!国内版ChatDoc企业知识库,直接操作Doc、Docx、PDF、txt等文件

自ChatGPT问世以来&#xff0c;国外就有ChatPDF、ChatDOC等基于文档问答的项目&#xff0c;但是国内还一直处于对话类产品的研发中。 贵州猿创科技研发了基于本地向量模型的ChatDoc知识库系统&#xff0c;可以直接上传Doc、Docx、PDF、txt、网页链接等进行问答。 体验地址&…

【算法篇C++实现】常见查找算法

文章目录 &#x1f680;一、预备知识⛳&#xff08;一&#xff09;查找的定义⛳&#xff08;二&#xff09;数组和索引 &#x1f680;二、二分查找&#x1f680;三、穷举搜索&#x1f680;四、并行搜索⛳&#xff08;一&#xff09;并发的基本概念⛳&#xff08;二&#xff09;…

修改VS Code终端的显示行数

文章目录 前言修改VS Code终端显示行数参考 前言 在我们使用VS Code运行代码的过程中&#xff0c;有时需要再终端中显示很多的运行过程信息或者结果。然而&#xff0c;VS Code的终端默认显示1000行的内容&#xff0c;随着显示内容的增多&#xff0c;之前的内容就丢失了。为了解…

【单片机毕业设计2-基于stm32c8t6的智能台灯系统】

【单片机毕业设计2-基于stm32c8t6的智能台灯系统】 前言一、功能介绍二、硬件部分三、软件部分总结 前言 &#x1f525;这里是小殷学长&#xff0c;单片机毕业设计篇2 基于stm32的智能台灯系统 &#x1f9ff;创作不易&#xff0c;拒绝白嫖 企鹅号&#xff1a;2836235214 一、功…

Java IO流——【从零构建信息管理系统】

Java I/O流——【从零构建信息管理系统】 文章目录 什么是Java I/O流介绍理解字节流和字符流的区别 Java I/O流的作用Java I/O流方法InputStream方法Reader方法OutputStream方法Writer方法Java I/O体系的全体类 使用示例Java I/O流在实际应用中使用效果 什么是Java I/O流 介绍…

多线程事务怎么回滚?

项目中用到了多线程去批量处理一些数据&#xff0c;当时想当然认为只要方法上加上Transactional注解就好了&#xff0c;实际并未达到想要的处理效果。特此去学习了下关于多线程事务回滚相关方案&#xff0c;参考了网上其他资料&#xff0c;这里整理并记录下学习历程。 站在巨人…