18.示例程序(编码器接口测速)

news2025/1/15 12:52:01

 STM32标准库开发-各章节笔记-查阅传送门_Archie_IT的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_61712829/article/details/132434192?spm=1001.2014.3001.5501

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "Encoder.h"


uint16_t speed;

int main(void)
{
	
	OLED_Init();	//初始化OLED
	Timer_Init();    //初始化定时器
	Encoder_init();
	
	OLED_ShowString(1,1,"speed:");

	while(1)
	{
		OLED_ShowSignedNum(1,7,speed,5);//每隔一段时间读取一次;用定时中断
	}

}


//定时器2中断函数放在使用中断的main.c文件中;在startup文件中;定时中断每隔1s执行一次
void TIM2_IRQHandler(void) //当定时器产生更新中断时,这个函数就会自动被执行
{
	//检查中断标志位
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
	//执行相应的用户代码
		speed = Encoder_Get();   //定时器每隔1s读取一下速度,存在speed变量里
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
	}

}

Encoder.c

#include "stm32f10x.h"                  // Device header

//编码器旋转控制CNT自增自减	
//编码器初始化函数,编码器电路初始化后,CNT就会随着编码器旋转而自增自减;直接读出CNT值就能测量编码器的位置;测量编码器的速度和方向就需要每隔一段固定的闸门时间取出一次CNT然后再把CNT清零这就是测频法测量速度了
/*
第一步,RCC开启时钟,开启GPIO和定时器的时钟
第二步,配置GPIO,需将PA6和PA7配置成输入模式
第三步,配置时基单元,预分频器一般选择不分频,ARR一般给最大值655535,只需要CNT执行计数就行了
第四步,配置输入捕获单元,这里只有滤波器和极性两个参数有用,后面的参数没有用到,与编码器无关
第五步,配置编码器接口模式,直接调用一个库函数
最后,调用TIM_Cmd,启动定时器
*/

void Encoder_init(void)
{
	//1.打开时钟,选择内部时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//2.初始化GPIO
	GPIO_InitTypeDef GPIO_InitStructure;		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入,与外部模块保持默认电平一致(上拉与下拉的选择原则);一般来说是默认高电平,所以一般上拉输入用的比较多;若不确定外部模块输出的默认状态或外部信号输出功率非常小,这时就尽量选择浮空输入(浮空输入:没有上拉和下拉电阻去影响外部信号,缺点是当引脚悬空,没有默认的电平了,输入就会受噪声干扰,来回不断地跳变)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;	
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_Init(GPIOA,&GPIO_InitStructure);		
	
	//不需要初始化时基单元下面这个内部时钟函数,因为编码器接口会托管时钟,编码器接口就是一个带方向控制的外部时钟,所以内部时钟就不用了
	//TIM_InternalClockConfig(TIM3);
	
	//3.配置时基单元 
	/*
	公式:
	PWM 频 率:Freq = CK_PSC / (PSC + 1) / (ARR + 1)
	PWM占空比:Duty = CCR / (ARR + 1)
	PWM分辨率:Reso = 1 / (ARR + 1)
	*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //指定时钟分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,这个参数也是没有作用的,计数方向也是被编码器接口托管的
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;  //ARR 周期 ,满量程计数,这样计数的范围是最大的而且方便换算成负数
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;  //PSC 预分频器,不分频,编码器的时钟直接驱动计数器
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;  //重复计数器的值
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);	//初始化TIM3
	
	//4.配置输入捕获单元(通道),编码器接口只使用了通道1和2的滤波器和极性选择
	//首先定义结构体变量,然后StructInit给结构体赋一个初始值,再部分修改我们想要的参数,调用ICInit配置一遍电路,结构体变量的配置在调用ICInit函数之后就写入到硬件的寄存器了,所以ICInit之后这个结构体我们可以换个值继续使用、不需要重新定义新的结构体
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICStructInit(&TIM_ICInitStructure);//结构体初始化,防止结构体中出现不确定值可能造成问题,最好用StructInit给结构体赋一个初始值
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;	//通道1
	TIM_ICInitStructure.TIM_ICFilter = 0xF;	//滤波器为0xF
	//TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	//电平极性为上升沿,这里的上升沿参数代表的是高低电平极性不反转;等会配置编码器接口的时候也有极性配置,属于重复配置,这个其实可以删掉;这里的上升沿并不代表上升沿有效,因为编码器接口始终都是上升沿、下降沿都有效
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;	//通道2
	TIM_ICInitStructure.TIM_ICFilter = 0xF;	//滤波器为0xF
	//TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	//电平极性为上升沿,这里的上升沿参数代表的是高低电平极性不反转;等会配置编码器接口的时候也有极性配置,属于重复配置,这个其实可以删掉;这里的上升沿并不代表上升沿有效,因为编码器接口始终都是上升沿、下降沿都有效
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	//5.配置编码器接口,只需调用一个函数就行了;;需保证TIM_EncoderInterfaceConfig在TIM_ICInit函数之后,否则TIM_ICInit覆盖TIM_EncoderInterfaceConfig函数的配置
	TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);//选择Rising是通道不反相,选择Falling是通道反相;重复配置TIM_ICPolarity_Rising,后面的参数会覆盖前面的参数配置
	
	//6.启动定时器
	TIM_Cmd(TIM3,ENABLE);
}

int16_t Encoder_Get(void)
{
	//测速,在固定的匝门时间读一次CNT然后把CNT清零
	int16_t temp;//因为要先读取CNT再清零,所以要用temp缓存一下
	temp = TIM_GetCounter(TIM3);//读取CNT
	TIM_SetCounter(TIM3,0);//CNT清零	
	return temp;

}


 

Encoder.h

#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_init(void);
int16_t Encoder_Get(void);

#endif


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

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

相关文章

数据结构:KMP算法的原理图解和代码解析

文章目录 应用场景算法方案算法原理完整代码 本篇总结的是关于串中的KMP算法解析 应用场景 现给定两个串,现在要看较短的一个串是不是较长的串的子串,如果是就输出子串后面的内容,如果不是则输出Not Found 能匹配到: 长串&…

基于SSM的连锁经营商业管理系统设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

JavaSE | 初识Java(五) | 方法的使用

方法就是一个代码片段, 类似于 C 语言中的 " 函数 "。 方法可以是我们代码逻辑更清晰,并且可以服用方法使代码更简洁 方法语法格式 // 方法定义 修饰符 返回值类型 方法名称([参数类型 形参 ...]){ 方法体代码; [return 返回值]; } 实例&…

自媒体文章改写工具-自媒体文章改写软件

自媒体时代已然来临,每个人都有机会成为自己的内容创作者,分享自己的观点和故事。在竞争激烈的自媒体领域,如何让自己的文章脱颖而出,吸引更多读者成为了一个重要的问题。 自媒体文章改写是一项旨在提高文章原创性和吸引力的关键任…

Arcgis打开影像分析窗口没反应

Arcgis打开影像分析窗口没反应 问题描述 做NDVI计算的时候,一直点击窗口-影像分析,发现影像分析的小界面一直不跳出来。 原因 后来发现是被内容列表给遮住了,其实是已经出来了的。。 拖动内容列表就能找到。 解决方案 内容列表和影像分…

热点文章采集-热点资讯采集工具免费

在信息时代,掌握热点资讯、了解热门时事、采集热门文章是许多自媒体从业者和信息追踪者的重要任务。然而,这并不是一项容易的任务。信息的海洋庞大而繁杂,要从中捞取有价值的热点和文章需要耗费大量时间和精力。 热点资讯采集:信息…

[Linux 基础] 一篇带你了解linux权限问题

文章目录 1、Linux下的两种用户2、文件类型和访问权限(事物属性)2.1 Linux下的文件类型2.2 基本权限2.3 文件权限值的表示方法(1)字符表示方法(2)8进制数值表示方法 2.4 文件访问权限的相关设置方法(1) chm…

番外4:VMware安装

step4: 安装过程中,有些选项不需要点(安装地址建议选C盘或默认,装载在其他盘后续会报错),如: may error(本人猜测安装虚拟机完整版需要C盘的一些桥插件支持): step5: 安装虚拟机成功…

爆文采集器-热点爆文章采集工具

当信息在互联网上迅速传播,新闻迅速变化,自媒体创作者和信息追踪者们都希望能够捕捉到瞬息万变的热点话题,以吸引更多的关注和流量。爆文采集器成为了一项关键的工具,有助于他们在信息的海洋中找到并分享最新、最热门的内容。 热点…

MAC手动修复『已损坏』问题 终端运行命令报错处理

安装一些第三方软件会出现已损坏的报错提醒,需要用命令sudo xattr -rd com.apple.quarantine进行修复,但是终端提示命令错误,怎么版 错误有几种: No module named ‘pkg_resources’ 这是mac电脑上python2,python3并…

eBPF 的发展历程及工作原理

目录 eBPF 是什么 掌握 eBPF 是不是得先成为内核开发者? eBPF 的发展历程是什么样的? eBPF 是怎么工作的? eBPF 是万能的吗? 小结 eBPF 是什么 eBPF 是什么呢? 从它的全称“扩展的伯克利数据包过滤器 (Extended Berkeley Packet Filter)” 来看…

2023年(24届)计算机保研推免经历(保研边缘人)| (吉大AI、华师cs、东南、浙软)

前言 写下这篇博客的原因在于自己保研期间刷了很多很多的经验贴,听很多学长学姐讲述了自己的经历,感觉收获颇丰。所以希望能将自己的经历也分享下去,如果以后的学弟学妹能获得一点点帮助,那就再好不过了。 保研基础知识&#xff0…

借助ChatGPT的神奇力量,解锁AI无限可能!

🚀欢迎来到本文🚀 🍉个人简介:陈童学哦,目前学习C/C、算法、Python、Java等方向,一个正在慢慢前行的普通人。 🏀系列专栏:陈童学的日记 💡其他专栏:CSTL&…

1.基本概念 进入Java的世界

1.1 Java的工作方式 1.2 Java的程序结构 类存于源文件里面,方法存于类中,语句(statement)存于方法中 源文件(扩展名为.java)带有类的定义。类用来表示程序的一个组件,小程序或许只会有一个类…

win系统玩游戏出现d3dx9_43.dll错误,找不到d3dx9_43.dll的解决方法

d3dx9_43.dll 是 DirectX 中的一部分,对于许多游戏和应用程序的运行至关重要。如果丢失了这个文件,可能会导致游戏无法运行或者系统出现问题。本文将详细介绍 d3dx9_43.dll 丢失的解决方法以及 d3dx9_43.dll 是什么文件和总体属性介绍。 一、d3dx9_43.dl…

Tomcat下载安装配置

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

5.5线程同步机制类封装及线程池实现

文章目录 5.5线程同步机制类封装及线程池实现线程池线程同步机制类封装线程池实现 5.5线程同步机制类封装及线程池实现 线程池 线程池是由服务器预先创建的一组子线程,线程池中的线程数据应该与CPU数据差不多。线程池中的所有子线程都运行着相同的代码。当有新的任…

探索腾讯企业邮箱替代方案:选择适合你的新邮件服务

腾讯企业邮箱作为一款广受欢迎的企业级电子邮件服务,已经在国内市场占据了相当大的份额。然而,随着全球市场竞争的加剧,腾讯企业邮箱也面临着海外市场的挑战。本文将探讨腾讯企业邮箱出海的劣势,并推荐一些替代品牌,以…

iPhone苹果手机复制了淘宝天猫优惠券领取淘口令打开淘宝APP没有弹窗怎么办?

获得淘宝/天猫优惠券领取的淘口令后,iPhone苹果手机打开淘宝APP无法识别淘口令,没有弹窗显示淘宝/天猫优惠券领取入口。 解决办法:复制淘宝/天猫商品链接,打开手机上安装的「草柴」APP,查询该商品淘宝/天猫内部隐藏优…

Mysql 分布式序列算法

接上文 Mysql分库分表 1.分布式序列简介 在分布式系统下,怎么保证ID的生成满足以上需求? ShardingJDBC支持以上两种算法自动生成ID。这里,使用ShardingJDBC让主键ID以雪花算法进行生成,首先配置数据库,因为默认的注…