编码器计速及测速(理论+代码)√

一、参考信息

       注意:

(1)此工程是建立在OLED的基础上,所以需要先把OLED的工程测试成功再开始编码器测速

(2)不管是霍尔编码器还是旋转编码器都是一样的学,不会有太大的区别     

(3) 使用的是STM32F103C8T6的开发板

(4)快捷键:F7是编译;F8是下载

        学习资料来源:(B站)

【15.定时器编码器接口【HAL库复现江协全部STM32例子合集】】

https://www.bilibili.com/video/BV1Q1421y7Us?vd_source=70e3aaa6cbfe13f5858272f48dacf336

【15.定时器编码器接口【HAL库复现江协全部STM32例子合集】】https://www.bilibili.com/video/BV1Q1421y7Us?vd_source=70e3aaa6cbfe13f5858272f48dacf336

二、基本原理

(1)电机的正反转判断

正转时,A信号比B信号会快半个周期先变成高电平

(A上升沿时B是低电平;A下降沿时B是高电平

   B上升沿时A是高电平:B下降沿是A是低电平)

反转时,B信号比A信号会快半个周期先变成高电平

(A上升沿时B是高电平;A下降沿时B是低电平

   B上升沿时A是低电平:B下降沿是A是高电平)

(2)电机的计数及编码器选择 

         一般使用TI1和TI2计数,B上升沿A此时高电平(电机正转,向上计数):A上升沿B此时高电平(电机反转,向下计数):选择编码器模式3

三、CubeMx配置

1、打开编码器模式

         选择定时器-->选择编码器模式(不需要选择内部时钟)

2、设置定时器的相关参数。由于是检测速度,所以这里就不分频,尽可能让定时器快点。计数器设置最大,防止输入信号频率太高溢出

3、设置计数模式,TI1计数和TI2计数

4、A相和B相都设置为上升沿

5、GPIO端口配置

        定时器中的编码器模式配置好之后,就可以看见板子上使用的端口是 PA6和PA7,所以此时接线就需要接在PA6和PA7上

6、OLED不需要在CubeMx中配置

        OLED不需要在CubeMx中配置,但是需要看OLED.c文件里面的引脚是不是一致的。不一致的话是无法显示的

7、电机的定时器PWM
8、记住再开一个专门用中断的定时器

四、计数代码

(1)首先要引用OLED.h的头文件

(2)声明一下中断回调函数

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef 
(3)重点

        初始化OLED ,打开控制电机PWM的定时器,打开控制编码器的定时器,打开使用定时器中断的定时器

  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);//PA0,控制电机的定时器
  HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL);//PA6,PA7控制编码器的定时器
  HAL_TIM_Base_Start_IT(&htim6);//开启中断函数的定时器
  
  OLED_Init();
(4)在while函数下面写中断函数

(5)新知识点:获取并显示计数值位置
OLED_ShowSignedNum(2,5,__HAL_TIM_GET_COUNTER(&htim3),5);

        这个函数就是获取编码器的计数值的

(6)改进为有符号的代码

        编码器反转时计数器应该返回负数才对,这是因为__HAL_TIM_GET_COUNTER(&htim3)返回时一个无符号的uint32_t数,需要把它强制转换成有符号的int16_t数即可

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器的中断函数
{
	int16_t CNT;//强制转化成有符号的数
	if(htim->Instance==TIM6)//控制中断的定时器
	{
		__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,300);//电机的转动速度
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);//这个不要用0,1;因为会出现警报,最好底层函数不要出现警报
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET);

		CNT=__HAL_TIM_GET_COUNTER(&htim3);
		OLED_ShowSignedNum(2,5,CNT,5);//把OLED的显示放在中断里面,不会卡顿
	}

}

五、测速代码

        原理就是1秒钟读取 一次定时器的计数值(编码器的脉冲)并清空。得到的数字就是当前的速度,单位就是(脉冲每秒)一秒钟有多少个脉冲

(1)测速的函数代码
int16_t hhGetEncoderSpeedCountAndReset()
{
	int16_t Tmp;
	Tmp=__HAL_TIM_GET_COUNTER(&htim3);//每隔一秒去获取一次这个计数值
	__HAL_TIM_SET_COUNTER(&htim3,0);//获取之后就清空
	return Tmp;

}

 (2)放在中断里面测速

        不能直接把TIM6设成1s来计算,因为这样很耽误进程。可以把TIM6设置成10ms,然后下面用计数的方式让他计数成1s之后再去显示你的速度

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器的中断函数
{
	int16_t CNT;//强制转化成有符号的数
	uint16_t A;
	if(htim->Instance==TIM6)//控制中断的定时器,此时是定义的10ms
	{
		__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,300);//电机的转动速度
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);//这个不要用0,1;因为会出现警报,最好底层函数不要出现警报
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET);
		A++;
		if(A>100)
		{
			
			OLED_ShowSignedNum(2,5,hhGetEncoderSpeedCountAndReset(),5);
			A=0;
		}
		
	
//		CNT=__HAL_TIM_GET_COUNTER(&htim3);
//		OLED_ShowSignedNum(2,5,CNT,5);//把OLED的显示放在中断里面,不会卡顿
	}

}

六、额外补充

(1)编码器的端口

         除了最上面和最下面的电机正负极其它的都是属于编码器的端口

(2)接线
2.1

        如果不驱动电机,只需要实验编码器的话,可以电机不直接接在TB6612驱动板上,直接接在单片机上

        编码器A相接在PA6上,编码器B相接在PA7上(VCC和GND可以接在单片机上)PA6和PA7正好是开的编码器的定时器的端口

2.2

        电脑可以通过ST-Link来给单片机供电。也可以电源给TB6612驱动板供电,然后TB6612给电机以及单片机供电,只是需要注意用此种供电方法时,在电脑给单片机下载程序的时候,驱动板上要关掉开关或者拔掉单片机连接在TB6612驱动板上的VCC和GND

(3)开定时器中断读数

        可以把这一句放在定时器的中断函数里面,不然在计数上面会有一些卡

 (4)特别注意

         一定要勾选这个,否则下载不进去程序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值