STM32 实现输入捕获 寄存器版
上一篇实现了输入捕获库函数版点此出
寄存器实现功能和库函数版本一样的,如果需要了解原理,可以查看库函数版本或者查看STM32F10x开发手册
代码如下
#include "Cap.h"
#include "Nvic.h"
u8 Cap_Sta;
u16 Cap_Val;
void Cap_Init(u16 pre, u16 psc)
{
RCC->APB2ENR |= 1 << 2;
RCC->APB1ENR |= 1 << 3;
GPIOA->CRL &= ~(0x0f);
GPIOA->CRL |= 0x00000008; //下拉输入
GPIOA->ODR |= 0; //下拉
TIM5->ARR = pre;
TIM5->PSC = psc;
//比较模式寄存器
TIM5->CCMR1 |= 1; //CC1S=01 选择输入端 IC1 映射到 TI1
TIM5->CCMR1 |= 0 << 4; //IC1F=0000 配置输入滤波器 不滤波
TIM5->CCMR1 |= 0 <<10; //IC2PS=00 配置输入分频,不分频
//捕获/比较使能寄存器
TIM5->CCER |= 0 << 1; //输入/捕获1输出使能
TIM5->CCER |= 1 << 0; //捕获发生在IC1的上升沿;
//中断使能寄存器
TIM5->DIER |= 1 << 1; //允许捕获/比较1中断。
TIM5->DIER |= 1 << 0; //允许更新中断。
// 控制寄存器 使能
TIM5->CR1 |= 0x01;
Nvic_Init(2,3,TIM5_IRQn,2);
}
//捕获状态
// SR 状态寄存器
//[7]:0,没有成功的捕获;1,成功捕获到一次.
//[6]:0,还没捕获到高电平;1,已经捕获到高电平了.
//[5:0]:捕获高电平后溢出的次数
void TIM5_IRQHandler(void)
{
u16 res;
res = TIM5->SR;
if((Cap_Sta & 0x80) == 0)
{
if(res & 0x01) //发生溢出
{
if(Cap_Sta & 0x40) //已经捕获到高电平
{
if(Cap_Sta & 0x3F)
{
Cap_Sta |= 0x80;
Cap_Val = 0xFFFF;
}
else
{
Cap_Sta++;
}
}
}
if(res & 0x02) //发生捕获
{
if(Cap_Sta & 0x40) //捕获到下降沿
{
Cap_Sta |= 0x80;
Cap_Val = TIM5->CCR1;
TIM5->CCER &= ~(1 << 1);
}
else //还未开始,第一次捕获上升沿
{
Cap_Sta = 0; //清空
Cap_Val = 0;
Cap_Sta |= 0X40; //标记捕获到了上升沿
TIM5->CNT = 0; //计数器清空
TIM5->CCER |= 1<<1; //CC1P=1 设置为下降沿捕获
}
}
}
TIM5->SR=0;//清除中断标志位
}
主函数如下
#include "stm32f10x.h"
#include "Usart.h"
#include "SysTick.h"
#include "Led.h"
#include "Cap.h"
void SystemInit()
{
}
int main()
{
// 10:20:20
u32 indata = 0;
Stm32_Clock_Init(9);
Delay_Init();
Uart_Init(72,9600);
//Led_Init();
printf ("捕获开始\r\n");
//预装值0xFFFF 分频1M
Cap_Init(0xFFFF,71); //1M频率计数
while(1)
{
if(Cap_Sta & 0x80)
{
indata = Cap_Sta & 0x3F;
indata *= 0xFFFF;
indata += Cap_Val;
printf("高电平持续时间:%d us \r\n",indata);
Cap_Sta = 0;
}
}
}
如果需要了解Nvic_Init() 函数
点此出查看串口通信 寄存器版