【蓝桥杯嵌入式】定时器的PWM输出与脉冲输 入捕获(测量频率与占空比)
- PWM输出
- cubemx配置
- 程序设计
- 输入捕获
- cubemx配置
- 程序设计
- 真题典例分析
PWM输出
cubemx配置
PWM输出引脚配置,这里使用PA6和PA7引脚输出两路PWM信号,分别对应的是由TIM16和TIM17的通道1产生的PWM信号,同时配置定时器的预分频系数PSC和自动重装载值CCR,PWM信号频率即为:
frq = 80000000 / (PSC+1)/ (ARR+1)
这里预分频系数为800-1,自动重装载值为100,则频率 frq = 80000000 / 800 / 100 = 1K Hz,占空比预设置为20%
同理 对TIM17通道1进行相关配置,使得输出频率为2KHz,占空比初始化为20%的PWM信号
程序设计
通过cubemx配置后,初始化信号的参数如下所示
//PA6 1KHz 20%
TIM16->PSC = 800-1;
TIM16->ARR = 100-1;
TIM16->CCR1 = 20;
//PA7 2KHz 20%
TIM17->PSC = 400-1;
TIM17->ARR = 100-1;
TIM17->CCR1 = 20;
启动PWM输出: 启动TIM16与TIM17的通道1输出PWM信号
HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
修改PWM信号占空比: 通过改变TIM16与TIM17通道1的自动重装载值来改变PWM信号的占空比
TIM16->CCR1 = 50;
TIM17->CCR1 = 25;
修改PWM信号的频率:,可以通过改变预分频系数PSC,或者改变自动重装值,但通过修改自动重装载值修改频率的同时会修改占空比。
TIM16->PSC = 400-1; //将PA6引脚的频率改为2000 Hz 占空比保持不变
TIM17->ARR = 50-1; //将PA7的频率改为4000 Hz 但占空比变为原来的2倍
输入捕获
- 输入捕获可以用来测量PWM波的频率与占空比
- 输入捕获模式下,当通道输入引脚出现指定高电平跳变时,当前CNT的值将被锁存到CCR中
cubemx配置
通过查看原理图发现,开发板自带2路555信号发生器,分别通过接口J9和J10接到开发板的PB4和PA15端口,这里取下跳线帽,通过杜邦线将PA6、PA7的PWM信号接入到PA15、PB4引脚,用于检测PWM信号的频率与占空比。
通过配置PB4引脚为TIM3_CH1,开启定时器3,设置预分频系数,配置从模式、触发源及其时钟源,分别设置通道1和通道2为直接模式与间接模式,同时设置为上升沿触发和下降沿触发。
同理对TIM2进行同样的配置
程序设计
初始化开启定时器的通道捕获
HAL_TIM_IC_Start(&htim2,TIM_CHANNEL_1);
HAL_TIM_IC_Start(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start(&htim2,TIM_CHANNEL_2);
HAL_TIM_IC_Start(&htim3,TIM_CHANNEL_2);
频率和占空比的测量
void pwm_process(void)
{
//测量频率
frq1 = 1000000.0f / (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)+1);
frq2 = 1000000.0f / (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1)+1);
//测量占空比
duty1 = (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2)+1) * 100.0f / (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)+1);
duty2 = (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2)+1) * 100.0f / (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1)+1);
}
真题典例分析
- PA6输出信号占空比通过电位器R37进行调节如图调节
- 通过B2按键切换高低频模式,并通过LCD进行实时显示
adc数据采集功能函数:
double getAdcVal(ADC_HandleTypeDef *pin)
{
double dat;
HAL_ADC_Start(pin);
dat = HAL_ADC_GetValue(pin);
return dat * 3.3 / 4096;
}
adc业务逻辑程序进程函数: 首先确定adc数据采集周期为200ms采集一次,并进行数字滤波,最后通过电压与占空比的关系,来确定PA6引脚的占空比。
u32 adc_tick = 0;
double adc_sum = 0;
void adc_process(void)
{
//adc采集周期 200ms
if(uwTick - adc_tick < 200)
return;
adc_tick = uwTick;
//adc数字滤波
for(uchar i = 0; i < 10; i++)
adc_sum += getAdcVal(&hadc2);
vr37 = adc_sum / 10.0f;
adc_sum = 0;
//通过电压改变PWM占空比
if(vr37 <= 1.0f)
TIM16->CCR1 = 10;
else if(vr37 >= 3.0f)
TIM16->CCR1 = 85;
else
TIM16->CCR1 = (uchar)(37.5 * (vr37 - 1.0f) + 10);
}
按键二: 启动5秒定时,并确定是从高频到低频,还是从低频到高频
if(key[1].single_flag == 1)
{
//按键2短按业务逻辑程序
//shake_flag = !shake_flag;
up_flag = !up_flag; //从低频到高频标志
sec5_flag = !sec5_flag; //5秒定时标志
HAL_TIM_Base_Start_IT(&htim7); //启动定时器 改变分频系数
key[1].single_flag = 0;
}
定时器中断服务函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM7) //50ms
{
if(up_flag)
psc--;
else
psc++;
}
}
PWM进程函数: 频率、占空比的修改与测量
void pwm_process(void)
{
//通过修改预分频系数修改频率
TIM16->PSC = psc;
//检测PWM信号频率
frq1 = 1000000.0f / (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)+1);
frq2 = 1000000.0f / (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1)+1);
//检测PWM信号占空比
duty1 = (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2)+1) * 100.0f / (HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)+1);
duty2 = (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2)+1) * 100.0f / (HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1)+1);
}
最后将实时的频率与占空比显示在LCD屏幕
void lcd_process(void)
{
if(ui == 0) //第一个界面显示的内容
{
sprintf(text," Title1 ");
LCD_DisplayStringLine(Line1, (unsigned char *)text); //LCD显示函数
sprintf(text," frq1:%dHz ",frq1);
LCD_DisplayStringLine(Line3, (unsigned char *)text); //LCD显示函数
sprintf(text," duty1:%d%% ",duty1);
LCD_DisplayStringLine(Line4, (unsigned char *)text); //LCD显示函数
sprintf(text," frq2:%dHz ",frq2);
LCD_DisplayStringLine(Line5, (unsigned char *)text); //LCD显示函数
sprintf(text," duty2:%d%% ",duty2);
LCD_DisplayStringLine(Line6, (unsigned char *)text); //LCD显示函数
}
}