实验内容:使用通用定时器输入捕获测量信号的脉宽(检测按键按下的时间)。
一、原理图
二、 CubeMX配置
Step1.打开 STM32CubeMX,点击“New Project”,选择芯片型号,STM32F103VETx。
Step2.选择时钟源,并配置时钟树。选择Crystal/Ceramic Resonator,并配置系统时钟为72M。
Step3.配置SYS,我们这里选择的是Serial Wire。(正常情况配置不配置不影响,debug可以使用。但是你不可以把这两个引脚用于其他复用功能,如果用于其他复用功能,debug就不起作用了。)
Step4.串口配置(主要为了在串口调试助手显示测试的时间),因为没有用到中断和DMA所以我们就不过多讲解。
Step5.接下来进行最主要的定时器配置。原理图中按键引脚PA0和定时器2通道1相关,因此我们选用定时器2进行配置。
到这里关于相关参数配置基本已经完成,只需要根据之前文章《STM32Cube HAL:GPIO输入/输出(一)》Step4-Step8,设置相关工程参数和生成代码。
三、添加功能代码
1、我们等会会向串口调试助手发送数据,进行实验结果的验证。 发送数据我们采用printf函数,所有需要重定向c库函数printf到串口。注意使用时需要在keil设置中勾选微库(use mircolib),同时需要添加头文件#include <stdio.h>。重定向代码如下(usart.c)
//重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口DEBUG_USART */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return (ch);
}
//重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
int ch;
HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);
return (ch);
}
2、定义相关变量,以及使能相关定时器和计数处理代码(main.c)
//全局变量
uint32_t ccr_cnt,period_cnt;//CCR寄存器值,中断次数
uint8_t tri_flag,end_flag;//触发方式标志位,捕获标记位
//局部变量
uint32_t cnt_cl=72000000/72;;//计数器时钟
float time;//按键时间
//使能相关定时器以及计数结果处理代码
__HAL_TIM_CLEAR_FLAG(&htim2,TIM_IT_UPDATE);//清除中断标志位,防止一使能定时器就进入中断
HAL_TIM_Base_Start_IT(&htim2);//使能定时器及更新中断
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);//使能定时器及捕获中断
printf("\r\n——————————开始按键测试——————————\r\n");
while (1)
{
if(end_flag==1)//结束捕获
{
time=(float)(period_cnt*1000+(ccr_cnt+1))/cnt_cl;//结果强制转换为浮点型
printf( "\r\n测得高电平脉宽时间:%.2fs\r\n",time);//输出结果保留小数点后两位
end_flag=0;
}
}
3、中断回调函数(更新中断和捕获中断)(main.c)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
period_cnt++;//中断计数
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(tri_flag==0)//上升沿触发时进入(tri_flag 0 上升沿触发 / 1 下降沿触发)
{
period_cnt=0;//中断次数清零
__HAL_TIM_SET_COUNTER(&htim2,0); //计数器清零
ccr_cnt=0;//存捕获寄存器获取的值的变量清零
__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);//改变触发极性-下降沿触发
tri_flag=1;
}
else//下降沿触发时进入
{
ccr_cnt=__HAL_TIM_GET_COMPARE(&htim2, TIM_CHANNEL_1);//获取捕获寄存器的值
//ccr_cnt=HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);//功能同上
__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);//改变触发极性-上降沿触发
tri_flag=0;
end_flag=1;//捕获完成标志
}
}
总体来这个实验还算简单,主要的思路是先捕获第一个上升沿,然后将计数器值,中断计数值以及CCR寄存器(存捕获寄存器获取的值的变量)清零,同时变换为下降沿触发,进行第二次捕获,通过第二次的触发获取中断计数值以及CCR寄存器的值来计算出按键按住的时间。