使用小熊派进行PWM输入捕获
开发板为小熊派开发板(STM32L431RCT6),CubeMX+keil进行程序烧写。使用TIM16(通用定时器)产生pwm,使用TIM2(通用定时器)的通道1、通道2捕获pwm的高电平时间、周期。
为了快速开发,我们直接在小熊派官方的LCD例程上开发,通过LCD显示捕获的PWM信息。
一、准备工作
一块stm32板子+LCD屏(我使用的是小熊派)
一根杜邦线
安装好KeilMDK,保证导入有对应stm32芯片的包
安装STM32CubeMX
下载LCD例程(本贴附件)
二、修改MDK工程
1.配置时钟源
选择外部高速时钟HSE,即在RCC中选择
如下图:
2.配置定时器
STM32L431RCTC的定时器有 1.高级定时器:TIM1 2.通用定时器:TIM2 TIM15 TIM16 3.基本定时器:TIM6 TIM7 4.低功耗定时器:LPTIM1 LPTIM2
打开通用定时器TIM16(产生PWM)
在Timers中打开TIM16(根据自己,可选择其他通用定时器),选择通道1。注意TIM16->Channel1默认是PA6引脚,我们将他映射到PB8(根据映射关系表),即将PB8配置为TIM16_CH1
配置PWM的周期、占空比
TIM16选择的是内部时钟PCLK2 = 80Mhz。PWM周期 = ((分频系数+1)*(自动重装载值+1))/80MHz (单位:S);比如我们配置周期为10ms,则可以设置预分频系数 = 80-1,自动重装载值 = 10000-1,即PWM周期= 80*10000 / 80000000 = 0.01s=10ms.
注意,预分频系数和自动重装载值是从0开始
其他保持默认即可;
**占空比配置**
就是在自动重装载值中,哪些值为高电平。设置占空比为1/10,即配置Pluse为1000-1.
打开通用定时器TIM2(PWM输入捕获)
打开从属模式,使用触发信号源TI1FP1,也就是在TI1FP1的上升沿,会复位所有的计数器,并更新对应的寄存器。
配置信号源、捕获方式
将定时器2时钟源进行8分频,即信号源为10Mhz;将自重重装载值设为最大即可;将IC1捕获设置为上升沿捕获,且设置为直连模式,IC2设置为下降沿捕获。
打开TIM2中断
如图:
3.生成工程文件
点击GENERATE CODE,然后 Open Project
三、编写程序
删除示例程序中主函数的代码
1.修改LCD显示程序
我们希望LCD能够像printf一样,显示任意字符串,还可以%d %f %s。
在lcd.c中添加如下代码(当然,记得在lcd.h中添加声明):
/* ************************************************************ *函数名称:SPILCD_DisString * *函数功能:显示一个字符串 * *入口参数:x:X坐标 *y:Y坐标 *size:字符尺寸 *... * *返回参数:无 * *说明: ************************************************************ */ void SPILCD_DisString(unsigned short x, unsigned short y, unsigned char size,char *fmt, ...) { char LCD_Printf_Buf[256]; va_list ap; char *pStr = LCD_Printf_Buf; va_start(ap, fmt); vsprintf(LCD_Printf_Buf, fmt, ap); va_end(ap); while(*pStr != 0) { LCD_ShowChar(x, y, *pStr++, size); x += size >> 1; } }
此时,我们可以像printf一样,将信息打印在LCD上。
2.重写输入捕获回调函数
在TIM2通道1、2捕获中断触发后,记录第一次的值(为0),再第二次触发后,两次相减+1即为对应的时间。
比如通道1捕获周期时间。第一次上升时,Capture_Data1=0,(第二次上升沿时间+1 - Capture_Data1) = 周期时间
uint32_t Capture_Data1 = 0; //存放下降沿数据 uint32_t Capture_Data2 = 0; //存放上升沿数据 float Cycle= 0.0; float HighLevel = 0.0; void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { Capture_Data1 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1) ; if(Capture_Data1 != 0) { Cycle = (Capture_Data1+1) * 1000 / 10000000.0; HighLevel = (Capture_Data2+1) * 1000 / 10000000.0; } } else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { Capture_Data2 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2); } }
3.打开中断
LCD_Init();//初始化LCD HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1); //打开pwm HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2); LCD_Clear(BLACK);//清屏为黑色
四、效果
LCD上显示周期、以及不断变化的占空比。
注意,网上很多示例在计算周期的时候没有+1,因为是从0开始计数,为了避免误差,需要+1
从效果上看出,完全符合我们TIM16产生的PWM,没有任何误差
- 点赞
- 收藏
- 关注作者
评论(0)