当前位置: 首页 > news >正文

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

 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();	//初始化OLEDTimer_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.初始化GPIOGPIO_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;	//通道1TIM_ICInitStructure.TIM_ICFilter = 0xF;	//滤波器为0xF//TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	//电平极性为上升沿,这里的上升沿参数代表的是高低电平极性不反转;等会配置编码器接口的时候也有极性配置,属于重复配置,这个其实可以删掉;这里的上升沿并不代表上升沿有效,因为编码器接口始终都是上升沿、下降沿都有效TIM_ICInit(TIM3, &TIM_ICInitStructure);TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;	//通道2TIM_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);//读取CNTTIM_SetCounter(TIM3,0);//CNT清零	return temp;}

Encoder.h

#ifndef __ENCODER_H
#define __ENCODER_Hvoid Encoder_init(void);
int16_t Encoder_Get(void);#endif

http://www.lryc.cn/news/180652.html

相关文章:

  • 【超详细】Fastjson 1.2.24 命令执行漏洞复现-JNDI简单实现反弹shell(CVE-2017-18349)
  • 【牛客网】JZ39 数组中出现次数超过一半的数字
  • 【Mysql】Lock wait timeout exceeded; try restarting transaction
  • python生成中金所期权行权价
  • CentOS7.9 安装postgresql
  • qt线程介绍
  • 记一次用dataframe进行数据清理
  • 《Jetpack Compose从入门到实战》 第二章 了解常用UI组件
  • Vue3 引入使用 vant组件详解
  • NOSQL Redis Ubuntu系列 常用的配置 及密码登录
  • C语言解析GPS源数据
  • 【论文阅读】(CVPR2023)用于半监督医学图像分割的双向复制粘贴
  • [Linux 基础] 一篇带你了解linux权限问题
  • FPGA project :HDMI
  • 基于微信小程序的物流快递信息查询平台同城急送小程序(亮点:寄件、发票申请、在线聊天)
  • idea插件推荐
  • Arcgis快速计算NDVI
  • SpringCloud Alibaba - 基于 FeignClient 整合 Sentinel,实现“线程隔离”和“熔断降级”
  • Acwing 906. 区间分组
  • 阿里云 Oss 权限控制
  • CSS详细基础(六)边框样式
  • 支持向量机SVM:从数学原理到实际应用
  • 【办公自动化】在Excel中按条件筛选数据并存入新的表(文末送书)
  • 第三章:最新版零基础学习 PYTHON 教程(第十一节 - Python 运算符—Python 中的any与all)
  • Pytorch单机多卡分布式训练
  • asp.net coremvc+efcore增删改查
  • Java基础面试,什么是面向对象,谈谈你对面向对象的理解
  • Ubuntu系统初始设置
  • 焕新古文化传承之路,AI为古彝文识别赋能
  • 毛玻璃动画交互效果