这里我用通用定时器3的通道1来测量转速霍尔转速传感器基本介绍霍尔传感器分类和原理我用的是开关型常开PNP型的霍尔传感器 开关型的有2种分类,一种是常开,另外一种就是常闭了 常开通俗来讲,就是霍尔传感器没有检测到磁铁的时候开关就是断开的,常闭相反 霍尔传感器具体分类
说明
关于为什么选用开关型常开PNP型霍尔传感器单片机只能接收高低电平,0或者是1, STM32程序实现程序介绍单片机STM32F103ZE 程序源码TIM3_CAP.H#ifndef __TIM3_CAP_H #define __TIM3_CAP_H #include "sys.h" extern u32 TIM3_RES;//保存2次高电平之间的时间 extern u16 TIM3_CAP;//保存第二次捕获高电平时候的计数器的数值 extern u8 TIM3_FLAG;//逻辑标志 void tim3_cap_init(u16 arr,u16 psc); #endif TIM3_CAP.H解读定时器只能在捕获到高电平的时候,把当前计数器的数值保存下次,由于我们需要计算2次高电平的时间,所有需要一个逻辑位TIM3_FLAG TIM3_CAP.C#include "TIM3_CAP.h" //定时器3 通道1 输入捕获模式 u32 TIM3_RES;//保存2次高电平之间的时间 u16 TIM3_CAP;//保存第二次捕获高电平时候的计数器的数值 u8 TIM3_FLAG;//逻辑标志 void tim3_cap_init(u16 arr,u16 psc) { RCC->APB1ENR|=1<<1;//开启定时器3的时钟 RCC->APB2ENR|=1<<2;//开启PA时钟 GPIOA->CRL&=0XF0FFFFFF;//PA6配置清零 GPIOA->CRL|=0X08080000;//PA6下拉输入 默认下拉 GPIOA->ODR|=0<<6;//PA6下拉 TIM3->ARR=arr;//设置自动重载值 TIM3->PSC=psc;//设置预分频值 //*********通道1设置 TIM3->CCMR1|=1<<0;//选择输入端 IC1 映射到 TI1 上 TIM3->CCMR1|=0<<2;//输入不分频 TIM3->CCMR1|=0<<4;//不滤波 TIM3->CCER|=1<<0;//允许通道1捕获计数器的值到捕获寄存器中 TIM3->CCER|=0<<1;//通道1上升沿捕获 TIM3->DIER|=1<<0;//允许更新中断 TIM3->DIER|=1<<1;//允许通道1捕获中断 MY_NVIC_Init(2,0,TIM3_IRQn,2);//抢占2,子优先级0,组2 TIM3->CR1|=1<<0;//开启定时器3 } void TIM3_IRQHandler(void) { if((TIM3_FLAG&0X80)==0)//还未成功捕获 { if(TIM3->SR&0X01)//溢出 { if(TIM3_FLAG&0X40)//已经捕获到高电平了 { if((TIM3_FLAG&0X3F)==0X3F)//高电平太长了 { TIM3_FLAG|=0X80;//标记成功捕获了一次 TIM3_CAP=0XFFFF; }else TIM3_FLAG++; } } if(TIM3->SR&0x02)//捕获1发生捕获事件 { if(TIM3_FLAG&0X40)//捕获到一个上升沿 { TIM3_FLAG|=0X80;//标记成功捕获到一次高电平脉宽 TIM3_CAP=TIM3->CCR1;//获取当前的捕获值. }else//还未开始,第一次捕获上升沿 { TIM3_FLAG=0;//清空 TIM3_CAP=0; TIM3_FLAG|=0X40;//标记捕获到了上升沿 TIM3->CNT=0;//计数器清空 } } } TIM3->SR=0;//清除中断标志位 } TIM3_CAP.C解读
RCC->APB1ENR|=1<<1;//开启定时器3的时钟 RCC->APB2ENR|=1<<2;//开启PA时钟
GPIOA->CRL&=0XF0FFFFFF;//PA6配置清零 GPIOA->CRL|=0X08080000;//PA6下拉输入 默认下拉 GPIOA->ODR|=0<<6;//PA6下拉
TIM3->ARR=arr;//设置自动重载值 TIM3->PSC=psc;//设置预分频值
TIM3->CCMR1|=1<<0;//选择输入端 IC1 映射到 TI1 上 TIM3->CCMR1|=0<<2;//输入不分频 TIM3->CCMR1|=0<<4;//不滤波 关于什么是分频,什么是滤波 滤波 分频 什么是TIM3->CCR1寄存器呢
TIM3->CCER|=1<<0;//允许通道1捕获计数器的值到捕获寄存器中 TIM3->CCER|=0<<1;//通道1上升沿捕获
TIM3->DIER|=1<<0;//允许更新中断 TIM3->DIER|=1<<1;//允许通道1捕获中断
MY_NVIC_Init(2,0,TIM3_IRQn,2);//抢占2,子优先级0,组2
TIM3->CR1|=1<<0;//开启定时器3 TIM3中断函数解读TIM3_FLAG是8位的,其中第7位用于标志第一次捕获,如果检测到第一次捕获就置1,第8位用于标志第二次捕获,检测到了就置1,1~6用于在检测到第一次捕获的时候定时器更新的次数 MAIN.C#include "sys.h" #include "usart.h" #include "delay.h" #include "led.h" #include "tim3_cap.h" int main(void) { Stm32_Clock_Init(9);//系统时钟设置 delay_init(72); //延时初始化 uart_init(72,115200); //串口初始化为115200 tim3_cap_init(0XFFFF,72-1);//每计一个数1us 每溢出一次10ms led_init();//LED初始化 while(1) { if(TIM3_FLAG&0X80) { TIM3_RES=TIM3_FLAG&0X3F; TIM3_RES*=65536;//溢出时间总和 TIM3_RES+=TIM3_CAP;//得到总的高电平时间 printf("%.3fs\r\n",0.000001*TIM3_RES);//打印总的高点平时间 TIM3_FLAG=0;//开启下一次捕获 } LED1=!LED1; delay_ms(200); } } MAIN.C解读主函数是检测到2次高电平就通过串口打印出高电平的时间 以下头文件中是用了原子哥的头文件 #include "sys.h" #include "usart.h" #include "delay.h" 结果LED1每0.2s切换亮灭状态一次,故每0.4s亮一次,结果和下图一样 用飞线把PA6(通道1)和PE5(LED1)连接起来 |
|