正点原子的输入捕获程序解读
2017-04-10 15:58
204 查看
正点原子的输入捕获程序是利用TIM5的单通道实现的,通过先捕获上升沿,清除计数器值,再更改捕获极性为下降沿,第二次进中断时读出高电平脉宽。一次捕获过程完成,下面解释程序中的问题和疑惑。
程序中省略了相关定时器的配置,相关配置参考正点原子的输入捕获程序。下面重点对信号进行捕获的定时器5的中断服务程序进行解读
捕获状态TIM5CH1_CAPTURE_STA这个寄存器是作者自己定义的一个,stm32中无硬件对应,无相应硬件置位复位。这个寄存器大家可以把它当做两个标志位flag1+flag2+一个存次数的数length。
flag1(or2)=1有一次成功捕获过程完成或已经捕获到高电平。
flag1(or2)=0未有一次成功捕获过程完成或未捕获到高电平。
捕获状态TIM5CH1_CAPTURE_STA各位功能
//[7]: 0,没有成功捕获,1,已经成功捕获一次
//[6]: 0,还没有捕获到高电平,1,已经捕获到高电平了
//[5:0]: 捕获高电平后溢出的次数
//定时器5的中断服务程序
void TIM5_IRQHandler(void)
{
//1.程序进更新中断的原因是,TIM5只有65536/1M=0.06s的时长,按占空比50%计算,不溢出能计算1/0.12=8.33Hz以上的频率脉宽,8hz以下的要有更新中断。
//2.程序初始化后,第一次进中断是进捕获中断,而且是进入else语句,将极性改为下降沿且STA=0x40;计数溢出后才会进更新中断,执行if((TIM5CH1_CAPTURE_STA&0X80)==0)语句,最后进入if(TIM5CH1_CAPTURE_STA&0X40)语句里。
//3.在if(TIM5CH1_CAPTURE_STA&0X40)语句里,如果溢出次数未达到3F,STA++继续,达到3F,高电平时间太长超出计数范围,默认捕获一次高电平,VAL=0xffff计数输出。
//4.退出更新中断进主函数中,与下面步骤3相同。
//
//1.初始化后,程序第一次上升沿进捕获中断,第一次进中断,进else语句,将STA和VAL清零,清零CNT,标记捕获到了高电平(也就是上升沿,因为初始化是上升沿被捕获嘛),将极性改为下降沿捕获,退出中断后,在主函数中由于if(TIM5CH1_CAPTURE_STA&0x80)语句不成立,所以不进if中,STA状态保持。
//2.下降沿到来时,进中断里的if(TIM5CH1_CAPTURE_STA&0x40)语句,是高电平再进if语句里,STA=1,成功捕获一次高电平信号,将数据给VAL,将极性改为上升沿捕获。
//3.退出中断进主函数后,如果一次捕获成功,有溢出就计算溢出次数再加上VAL的值就是高电平时间,打印输出。并将STA清零,保证在下一个上升沿进捕获中断后,程序又进入else语句,不进入if(TIM5CH1_CAPTURE_STA&0x40)语句中,因为STA在主函数中被清零了。然后循环上述步骤,一个周期产生一次捕获,得到高电平时间。
整个程序就是这样,一个通道完成后,可以开始写四路通道同时捕获高电平的程序了,用一个定时器就可以完成,还是比较简单的。
extern u8 TIM5CH1_CAPTURE_STA; //输入捕获状态 extern u16 TIM5CH1_CAPTURE_VAL; //输入捕获值 int main(void) { u32 temp=0; delay_init(); //延时函数初始化 NVIC_Configuration(); //中断优先级配置 uart_init(9600); //波特率为9600 LED_Init(); //LED初始化 TIM3_PWM_Init(899,0); //PWM频率=72000/(899+1)=80Khz TIM5_Cap_Init(0XFFFF,72-1); //以1Mhz频率计数 while(1) { delay_ms(10); TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);//设置占空比,300是900的1/3,高电平最大持续时间是4.16us if(TIM_GetCapture2(TIM3)==300) { TIM_SetCompare2(TIM3,0); } if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获了一次上升沿 { temp=TIM5CH1_CAPTURE_STA&0X3F;//统计溢出次数 temp*=65536;//溢出时间总和 temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间 printf("HIGH:%d us\r\n",temp);//打印高电平时间 TIM5CH1_CAPTURE_STA=0;//开启下一次捕获 } }
程序中省略了相关定时器的配置,相关配置参考正点原子的输入捕获程序。下面重点对信号进行捕获的定时器5的中断服务程序进行解读
u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态 u16 TIM5CH1_CAPTURE_VAL; //输入捕获值
捕获状态TIM5CH1_CAPTURE_STA这个寄存器是作者自己定义的一个,stm32中无硬件对应,无相应硬件置位复位。这个寄存器大家可以把它当做两个标志位flag1+flag2+一个存次数的数length。
flag1(or2)=1有一次成功捕获过程完成或已经捕获到高电平。
flag1(or2)=0未有一次成功捕获过程完成或未捕获到高电平。
捕获状态TIM5CH1_CAPTURE_STA各位功能
//[7]: 0,没有成功捕获,1,已经成功捕获一次
//[6]: 0,还没有捕获到高电平,1,已经捕获到高电平了
//[5:0]: 捕获高电平后溢出的次数
//定时器5的中断服务程序
void TIM5_IRQHandler(void)
{
//1.程序进更新中断的原因是,TIM5只有65536/1M=0.06s的时长,按占空比50%计算,不溢出能计算1/0.12=8.33Hz以上的频率脉宽,8hz以下的要有更新中断。
//2.程序初始化后,第一次进中断是进捕获中断,而且是进入else语句,将极性改为下降沿且STA=0x40;计数溢出后才会进更新中断,执行if((TIM5CH1_CAPTURE_STA&0X80)==0)语句,最后进入if(TIM5CH1_CAPTURE_STA&0X40)语句里。
//3.在if(TIM5CH1_CAPTURE_STA&0X40)语句里,如果溢出次数未达到3F,STA++继续,达到3F,高电平时间太长超出计数范围,默认捕获一次高电平,VAL=0xffff计数输出。
//4.退出更新中断进主函数中,与下面步骤3相同。
//
if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获 { if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) { if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了 { if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了 { TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次 TIM5CH1_CAPTURE_VAL=0XFFFF; }else { TIM5CH1_CAPTURE_STA++; } } }
//1.初始化后,程序第一次上升沿进捕获中断,第一次进中断,进else语句,将STA和VAL清零,清零CNT,标记捕获到了高电平(也就是上升沿,因为初始化是上升沿被捕获嘛),将极性改为下降沿捕获,退出中断后,在主函数中由于if(TIM5CH1_CAPTURE_STA&0x80)语句不成立,所以不进if中,STA状态保持。
//2.下降沿到来时,进中断里的if(TIM5CH1_CAPTURE_STA&0x40)语句,是高电平再进if语句里,STA=1,成功捕获一次高电平信号,将数据给VAL,将极性改为上升沿捕获。
//3.退出中断进主函数后,如果一次捕获成功,有溢出就计算溢出次数再加上VAL的值就是高电平时间,打印输出。并将STA清零,保证在下一个上升沿进捕获中断后,程序又进入else语句,不进入if(TIM5CH1_CAPTURE_STA&0x40)语句中,因为STA在主函数中被清零了。然后循环上述步骤,一个周期产生一次捕获,得到高电平时间。
if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件 { if(TIM5CH1_CAPTURE_STA&0X40) //捕获到一个下降沿 { TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次上升沿 TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5); TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获 }else //还未开始,第一次捕获上升沿 { TIM5CH1_CAPTURE_STA=0; //清空 TIM5CH1_CAPTURE_VAL=0; TIM_SetCounter(TIM5,0); TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿 TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获 } } } TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
整个程序就是这样,一个通道完成后,可以开始写四路通道同时捕获高电平的程序了,用一个定时器就可以完成,还是比较简单的。
相关文章推荐
- (正点原子例程)lwip以太网程序
- 正点原子按键程序分析
- STM32串口采样与仪表步进电机控制程序(主程序与串口程序,需用正点原子定时器中断实验程序模板)
- [ZT]如何在图形界面中实时捕获控制台程序的标准输出,让图形界面程序向控制台程序输入特定的命令行指令
- 在stm32f4(正点原子“探索者”的板子)上,如何移植ds1302芯片程序
- 原子战舰STM32——定时器捕获中断库函数程序中中断处理函数说明
- pyhook学习—捕获某程序过程键盘输入
- 【程序】AVR单片机ATMega16A使用定时器1的输入捕获功能进行红外遥控解码
- 屏幕捕获程序
- 如何调用命令行程序, 并得到输出, 还有输入交互?
- 关于"无法定位程序输入点 RtlUnhandledExceptionFilter 于动态链接库"解决方法
- 编程常见问题记录:明明有响应按钮的事件,但程序就是无法捕获到
- .NET 异常捕获机制的小技巧应用(实例:端口扫描程序)
- 基于Delphi的VFW视频捕获程序的开发
- 用vs制作安装程序的时候 如何获取用户输入的序列号,并进行判定
- 关于asp.net web程序的访问,为什么老提示输入用户名和密码?
- 如何执行本地程序并捕获out和err输出(written in Java)
- *自定义原子交易组件开发示例程序Samp.ccs
- Console程序输入信息显示星号
- 经典c程序 输入输出