前言
其实一个嵌入式设备的引脚基础使用无非就是各种输入与输出,基本的基础输出、有控制的输出,前面的文章里已经涉及完全了。那么本章就来讲输入的功能,本篇任务为利用定时器来测量一个外部脉冲信号的周期和频率,外部脉冲信号利用引脚输入。预期为定时器3的PWM输出频率为100KHz,占空比50%的方波
一、引脚配置
1、配置定时器为输入捕获模式
选择时钟源为内部时钟,选择通道为直接输入的输入捕获模式
设置预分频系数 89 以此获得 1MHz 捕获频率
90000000
H
z
/
(
89
+
1
)
=
1000000
H
z
90 000 000 Hz / (89+1)=1000 000 Hz
90000000Hz/(89+1)=1000000Hz
,自动重装载值设为 0xFFFFFFFF ,即最大的计数周期,这样可以扩大测量频率的脉宽,采用上升沿触发(默认配置无需修改)。
使能定时器的全局中断,优先级无需调整
可以看到该输入通道的引脚为 PA0
2、设置定时器输出方波
同样选择时钟源为内部时钟,不同的是选择通道生成 PWM
还是这张图找到所使用的时钟 TIM3 使用的 APB1
在 datasheet 中也可以找到对应定时器的时钟频率
在 CubeMX 中有其时钟时钟的设置
我们要输出一个频率为 100KHz,占空比 50% 的方波
100000 H z = 90000000 H z / (( 89 + 1 ) ∗ ( 9 + 1 )) 100 000 Hz = 90 000 000 Hz /((89+1)*(9+1)) 100000Hz=90000000Hz/((89+1)∗(9+1))
因此设置预分频系数为 89 ,自动重装载值为 9 ,那么为了获得 50%占空比 CRR值设置为 5
可以看到该输出通道的引脚为 PA6
二、代码编写
采用前后台编程模式。在输入捕获中断的回调函数中,设置测量完成标志,主程序中检测该标志,一旦置位则计算信号的周期和频率,并清除标志位。
1、变量定义
uint32_t Diff =0; //存放捕获的差值
uint8_t MeasureFlag =0; //测量完成标志
uint8_t CapIndex =0; //开始捕获指示
uint32_t CapVal1=0; //存放第一次捕获值
uint32_t CapVal2=0; //存放第二次捕获值
2、初始化代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eatH0kMk-1691584222522)(/Users/darian/Documents/博客/stm32/五、信号捕获/pic/11.png)]
printf("The Capture Function running now !");
HAL_TIM_Base_Start_IT(&htim2); /*开启此条才能进入定时器的回调函数*/
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
3、循环内添加持续捕获代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fKJp3XKp-1691584222523)(/Users/darian/Documents/博客/stm32/五、信号捕获/pic/12.png)]
if(MeasureFlag==1)
{
//两次捕获在同一个计数周期大
if(CapVal2 >= CapVal1)
{
Diff = CapVal2- CapVal1;
}
//两次捕获不在同一个计数周期内
else
{
Diff =((0xFFFFFFFF + 1 - CapVal1) + CapVal2);
}
printf("Period is:%.4f ms\r\n",Diff/1000.0); //
printf("Frequency is:%d Hz\r\n",(int)(1000000/Diff));// 1 MHz /差值
MeasureFlag = 0;// 清除测量完成标志
HAL_Delay(1000);
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//启动下一次捕获
}
4、编写捕获中断回调函数
代码具体含义见注释
三、烧录代码观察现象
首先使用一根杜邦线连接输入 PA0 与输出 PA6
结果符合预期输出以及捕获任务完成!总结方法就是看定时、分频、重装载值、占空比即可获得预期的输出信号!