使用小熊派进行PWM输入捕获

举报
ttking 发表于 2020/08/03 22:11:04 2020/08/03
【摘要】 以小熊派为例,使用TIM16(通用定时器)产生pwm,使用TIM2(通用定时器)的通道1、通道2捕获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,没有任何误差



【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。