STM32Cube学习之八:输入捕获
假设已经安装好STM32CubeMX和STM32CubeF4支持包。
Step1.打开STM32CubeMX,点击“New Project”,选择芯片型号,STM32F407ZETx。
Step2. 在Pinout界面下配置晶振输入引脚。
配置TIM2使用内部时钟源,CH1作为输入捕获通道,默认映射到PA0引脚。
配置TIM3使用内部时钟,CH1~CH4为PWM输出通道,默认映射引脚分别为PA6,PA7,PB0,PB1。
配置TIM4使用内部时钟,CH1,CH2为PWM输出通道,映射引脚分别为PD12,PD13。
配置串口,作为信息输出接口。
Step3.在Clock Configuration界面配置时钟源。
使用外部8M晶振作PLL时钟输入,并使用PLL输出作为系统时钟。为了后面的计算方便,将系统时钟配置成160MHz。
Step4.配置外设参数。
在configuration界面中点击TIM2/ TIM3/ TIM4按钮,可以进入参数配置界面。
TIM2:在Parameter Settings页配置预分频系数为7,其计数时钟就是80MHz/(7+1)=10MHz。计数周期(自动加载值),转换为十六进制形式,输入32bit最大值0xFFFFFFFF。
注意,TIM2的自动加载寄存器ARR和各个通道的捕获/比较寄存器CCRx都是32bit的。
在NVIC页面使能捕获/比较中断。
在GPIO页面设置捕获输入引脚下拉电阻,设置成上拉也可以,主要是为了使在没有信号输入时在输入引脚上得到稳定的电平。
TIM3:在Parameter页配置预分频系数为7,计数周期(自动加载值)为9999。其溢出频率就是80MHz/(7+1)/(9999+1)=1kHz,这就是TIM3各通道输出的PWM信号的频率。
各通道输出PWM的占空比参数如上图红框标注,其他参数使用默认值。按照图中参数,CH1~CH4输出的PWM周期都是1ms,而高电平时间分别是123.4us,234.5us,567.8us,678.9us。
在GPIO页面配置相关引脚的特性。
TIM4:在Parameter页配置预分频系数为7,计数周期(自动加载值)为999。其溢出频率就是80MHz/(7+1)/(999+1)=10kHz,这就是TIM4各通道输出的PWM信号的频率。
各通道输出PWM的占空比参数如上图红框标注,其他参数使用默认值。CH1,CH2输出的PWM周期都是100us,而高电平时间分别是23.4us,56.7us。
在GPIO页面配置相关引脚的特性。
串口参数配置,使用默认值即可。
Step5.生成源代码。
点击生成源代码按钮。
在设置界面中输入工程名,保存路径,工程IDE类型,点OK即可。
生成代码完成后可直接打开工程。
弹出如下对话框时,如果已经安装了F4的支持包,则点击OK关闭。如果没有安装,则点击界面中的https://www.wendangku.net/doc/0a1100287.html,/...链接,找到芯片的支持包,然后安装。
关闭后面的界面。
点击“是”,然后选择芯片型号。可以在搜索框中输入关键字,加快选择速度。
Step6.添加功能代码。
先在main.c文件用户代码区输入包含标准输入输出头文件。
在用户代码区4实现标准输出printf()的底层驱动函数fputc(),功能是在UART1输出一个字符。
在主函数前面的用户代码区0,定义一些全局变量。
在while(1)之前的用户代码区2,使能TIM3、TIM4的各个通道PWM输出。
在while(1)中的用户代码区3,写入TIM2 CH1通道的输入捕获控制和数据处理。
在main文件的用户代码区4,写入TIM2输入捕获中断处理回调函数。
至此,工程完成。功能是使用TIM的输入捕获功能,实现对PWM信号的周期和占空比测量,并将数据通过串口发送出去。用杜邦线将PA0和其他PWM信号输出脚相连,即可测量信号的周期,高电平所占时间,以及占空比,在串口1会输出这些信息。输出信息示例如下:
Cycle:1.0000ms
High :0.1234ms
Duty :12.3%
Cycle:0.1000ms
High :0.0567ms
Duty :56.7%
按照本例的配置,测量精度是0.1us,测量信号周期范围是0~0xFFFFFFFF*0.1us,即0~429.4967295秒
测量基本思路是:
1.设置TIM2 CH1为输入捕获功能;
2.设置上升沿捕获;
3.使能TIM2 CH1捕获功能;
4.捕获到上升沿后,存入capture_buf[0],改为捕获下降沿;
5.捕获到下降沿后,存入capture_buf[1],改为捕获上升沿;
6.捕获到上升沿后,存入capture_buf[2],关闭TIM2 CH1捕获功能;
7.计算:capture_buf[2] - capture_buf[0]就是周期,capture_buf[1] - capture_buf[0]就是高电
平所占时间。
特别说明:
printf()函数的详细使用方法可到网上查找,在此仅解释本例的语句。
printf("Cycle:%.4fms\r\n", pwm_cycle/10000.0);
其中“%f”是输出浮点数的格式,加了“.4”就是保留4位小数。
pwm_cycle是32bit无符号整形,除以10000.0就是先将其变成小数,在除以10000。
printf("Duty :%.1f%%\r\n", duty/10.0);
因为%在printf()函数的格式转换中是格式转换的特殊符号,因此要打印一个“%”时,就要写成“%%”。
HAL_TIM_PWM_Start()函数用于使能定时器某一通道的PWM输出。
HAL_TIM_IC_Start_IT()函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断。对应的HAL_TIM_IC_Stop_IT()函数和其功能相反,是关闭定时器某一通道的输入捕获功能和相应中断。
__HAL_TIM_SET_CAPTUREPOLARITY不是函数,而是底层操作的一个宏定义。
在stm32f4xx_hal_tim.h文件中可以找到。其作用是修改定时器某一通道的输入捕获极性。
__HAL_TIM_GET_COMPARE也是一个宏定义。
在stm32f4xx_hal_tim.h文件中可以找到。其作用是获取定时器某一通道的捕获/比较寄存器值。
根据我使用CubeMX开发的经验,发现HAL库并没有把所有的操作都封装成函数。对于底层的寄存器操作(如本例中的读取捕获/比较寄存器),还有修改外设的某个配置参数(如本例中的改变输入捕获的极性),HAL库会使用宏定义来实现。而且会用__HAL_作为这类宏定义的前缀。获取某个参数,宏定义中一般会有_GET,而设置某个参数的,宏定义中就会有_SET。在开发过程中,如果遇到寄存器级别或者更小范围的操作时,可以到该外设的头文件中查找,一般都能找到相应的宏定义。
官方例程请参考stm32cubef4.zip解压后
STM32Cube_FW_F4_V1.11.0\Projects\STM324xG_EVAL\Examples\TIM\TIM_InputCapture目录下的工程。
S.D.Lu 于深圳
2016年8月