最近在调编码器,网上的大多没有F429 的HAL例程,并且没有圈数的准确计算。此例程在其他的基础上进行编码器圈数的准确计算。圈数通过串口打印小数形式。
欢迎大家讨论!
附件上传不了???
主要是main和timer 。我贴出来吧!
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "timer.h"
/************************************************
ALIENTEK 阿波罗STM32F429开发板实验7
定时器中断实验-HAL库函数版
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
/************************************************
A、B 相的接PD12 和PD13 ,由于编码器能正反转,具体的接法看实际需求
这里只是一个编码器例程,其他需要只需要在配置几个定时器和引脚即可使用
************************************************/
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
uart_init(9600); //初始化USART
LED_Init(); //初始化LED
KEY_Init(); //初始化按键
TIM4_Init(2000,3); //定时器3初始化,定时器时钟为60M
Interupt_Num=0 ;
Pulse_Num =0 ;
Circle_NUm =0;
while(1)
{
Circle_Print();
delay_ms(100);
LED0 = !LED0;
}
}
/////////////////////////////////////////timer.h///////////////////////////////////////////////////////////////////////////////
#ifndef _TIMER_H
#define _TIMER_H
#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F429开发板
//定时器驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/6
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////
extern TIM_HandleTypeDef TIM3_Handler; //定时器句柄
extern TIM_Encoder_InitTypeDef Code_Config;
extern TIM_MasterConfigTypeDef Master_Config;
extern long Interupt_Num ; //因为编码器配置的定时器数值溢出进入中断次数
extern long Pulse_Num ; //计算得到的所有的脉冲数
extern float Circle_NUm ; //计算得到的所有圈数,有正负之分
void TIM4_Init(u16 arr,u16 psc);
void Circle_Print();
#endif
/////////////////////////////////////////timer.c///////////////////////////////////////////////////////////////////////////////
#include "timer.h"
#include "led.h"
#include "usart.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F429开发板
//定时器中断驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/6
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////
TIM_HandleTypeDef TIM4_Handler; //定时器句柄
TIM_Encoder_InitTypeDef TIM4_Encoder_Handler;
//通用定时器3中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!(定时器3挂在APB1上,时钟为HCLK/2)
long Interupt_Num=0 ;
long Pulse_Num =0 ;
float Circle_NUm =0;
void TIM4_Init(u16 arr,u16 psc)
{
TIM4_Handler.Instance=TIM4;
TIM4_Handler.Init.Prescaler=psc; //分频系数
TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器
TIM4_Handler.Init.Period=arr; //自动装载值
TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频银子
//HAL_TIM_Base_Init(&TIM4_Handler); //HAL_TIM_OC_Init(&TIM4_Handler);
//不要用这句话,他是基本定时器的设置,这里使用了编码器模式,没必要配置
TIM4_Encoder_Handler.EncoderMode=TIM_ENCODERMODE_TI12;
TIM4_Encoder_Handler.IC1Filter=0;
TIM4_Encoder_Handler.IC1Polarity=TIM_ICPOLARITY_RISING;
TIM4_Encoder_Handler.IC1Prescaler=TIM_ICPSC_DIV1;
TIM4_Encoder_Handler.IC1Selection=TIM_ICSELECTION_DIRECTTI;
TIM4_Encoder_Handler.IC2Filter=0;
TIM4_Encoder_Handler.IC2Polarity=TIM_ICPOLARITY_RISING;
TIM4_Encoder_Handler.IC2Selection=TIM_ICSELECTION_DIRECTTI;
TIM4_Encoder_Handler.IC2Prescaler=TIM_ICPSC_DIV1;
HAL_TIM_Encoder_Init(&TIM4_Handler,&TIM4_Encoder_Handler);
HAL_TIM_Encoder_Start(&TIM4_Handler,TIM_CHANNEL_ALL);
HAL_TIM_Encoder_Start_IT(&TIM4_Handler,TIM_CHANNEL_ALL);//开启中断
TIM4->CNT=1000;
__HAL_TIM_ENABLE_IT(&TIM4_Handler,TIM_IT_UPDATE); //使能更新中断
__HAL_TIM_ENABLE(&TIM4_Handler);
}
void TIM4_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM4_Handler);
}
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_Initure;
if(htim->Instance==TIM4)
{
__HAL_RCC_TIM4_CLK_ENABLE(); //使能TIM4时钟
HAL_NVIC_SetPriority(TIM4_IRQn,1,3); //设置中断优先级,抢占优先级1,子优先级3
HAL_NVIC_EnableIRQ(TIM4_IRQn); //开启ITM4中断
HAL_TIM_Base_Start_IT(&TIM4_Handler); //使能定时器4和定时器4更新中断:TIM_IT_UPDATE
__HAL_RCC_GPIOD_CLK_ENABLE(); //开启GPIOD时钟
GPIO_Initure.Pin=GPIO_PIN_12|GPIO_PIN_13;
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //输入
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Alternate=GPIO_AF2_TIM4;
HAL_GPIO_Init(GPIOD,&GPIO_Initure);
}
}
//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&TIM4_Handler))
{
LED1 = !LED1 ;
if ( (TIM4->CR1&0x0010) == 0 ) //向上计数溢出
{
Interupt_Num++ ;
}
else //向下计数溢出
{
Interupt_Num-- ;
}
}
}
void Circle_Print()
{
if (Interupt_Num ==0 ) //CNT从1000开始,刚开始的时候计算脉冲的方法
Pulse_Num = TIM4->CNT-1000 ;
else
{
Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法
}
Circle_NUm = Pulse_Num/1000.0f ; //所有人脉冲除以细分数就可以得到转的圈数(正负之分)
printf("Interupt_Num的值是:%ld--捕获到的总数是%ld*****转过的圈数是%f
" , Interupt_Num, Pulse_Num , Circle_NUm );
} |