嵌入式开发–STM32G431RBTx-产生pwm
定时器工作原理
如图有反映stm32g431的定时器资源。
共10个定时器
定时器 | 定时器类型 | 个数 |
---|---|---|
TIM6,7 | 基本定时器 | 2 |
TIM2,3,4 | 全功能通用定时器 | 3 |
TIM15,16,17 | 通用定时器(只有1或2个通道) | 3 |
TIM1,8 | 高级控制定时器 | 2 |
- 当APB1/2分频系数为1时,给定时器的时钟为X1
- 当APB1/2分频系数不为1时,给定时器时钟需X2
基本定时功能,当累加的时钟脉冲数超过预定值时,能触发中断或者触发DMA请求。
是专门用于驱动数模转换器(DAC)
基本定时器TIM16/17内部结构图
配置定时器
设定TIM16定时器
设定系数
第一个是分频系数
(Prescaler)
第二个是周期计数值,按照分频后的时间进行计数(Counter Period)
80M的晶振除以8000,得到的工作频率为80 000 000/8 000=10 000
计算到ARR,就让ARR设置为100-1
此时可以得到一个频率为100hz的PWM波
此处为占空比的设置,后续可以继续更改。
使用中断
TIM17设置同上。
关于按键中断的实现
struct keys key[4]={0,0,0};
if(htim->Instance==TIM3)
{
key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
}
这段代码是一个中断回调函数,用于处理定时器 TIM3 的中断事件。代码中包含一个名为 key
的结构体数组,用于记录按键的状态。
在函数体中,首先通过读取 GPIO 引脚的状态,将按键的状态存储到 key
数组中的相应位置。其中,key[i].key_sta
表示第 i 个按键的状态。
接下来,使用一个循环遍历 key
数组的每个元素,对每个按键的状态进行判断和处理。
for(int i=0;i<4;i++)
{
switch (key[i].judge_sta)
{
case 0: //
{
if(key[i].key_sta==0) key[i].judge_sta=1;
}
break;
case 1:
{
if(key[i].key_sta==0)
{
key[i].judge_sta=2;
key[i].single_flag=1;
}
else key[i].judge_sta=0;
}
break;
case 2:
{
if(key[i].key_sta==1)
{
key[i].judge_sta=0;
}
}
break;
}
}
在 switch
语句中,根据 key[i].judge_sta
的值来确定需要执行的操作。key[i].judge_sta
表示按键的判断状态。
当key[i].judge_sta
的值为 0 时,表示按键处于初始状态。
- 如果按键的状态为按下(
key[i].key_sta
等于 0),则将key[i].judge_sta
的值设为 1,表示按键已按下。
当 key[i].judge_sta
的值为 1 时,表示按键已按下。
- 如果按键的状态仍然为按下,维持
key[i].judge_sta
的值为 1。 - 如果按键的状态变为松开(
key[i].key_sta
等于 1),则将key[i].judge_sta
的值设为 2,表示按键已松开,并将key[i].single_flag
的值设为 1,表示按键被单击。
当key[i].judge_sta
的值为 2 时,表示按键已松开。
- 如果按键的状态变为按下,将
key[i].judge_sta
的值设为 0,表示按键已按下。
功能实现
一共有四个按键,按键0,按键1,按键2,按键3
按键 | 功能 |
---|---|
按键0 | LCD显示PA6,PA7的占空比 |
按键1 | LCD显示PA6,PA7的占空比;PA6占空比加10 |
按键2 | LCD显示PA6,PA7的占空比;PA7占空比加10 |
按键3 | LCD显示PA6,PA7的占空比 |
添加如下配置
extern uint frq1,frq2;
extern float duty1,duty2;
uchar view=0;
uchar pa6_duty=10;
uchar pa7_duty=10;
HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);//pwm输出开启
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//频率测量捕获定时器开启
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);//频率测量捕获定时器开启 间接通道
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
__HAL_TIM_SetCompare(&htim16,TIM_CHANNEL_1,pa6_duty);//设置初始pwm频率
__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,pa7_duty);
按键功能
void key_proc(void)
{
if(key[1].single_flag==1)
{
pa6_duty+=10;
if(pa6_duty>=100) pa6_duty=10;
__HAL_TIM_SetCompare(&htim16,TIM_CHANNEL_1,pa6_duty);
key[1].single_flag=0;
}
if(key[2].single_flag==1)
{
pa7_duty+=10;
if(pa7_duty>=100) pa7_duty=10;
__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,pa7_duty);
key[2].single_flag=0;
}
}
void disp_proc(void)
{
char text[30];
sprintf(text," Para ");
LCD_DisplayStringLine(Line1, (uint8_t *)text);
sprintf(text," PA6:%d ",pa6_duty);
LCD_DisplayStringLine(Line2, (uint8_t *)text);
sprintf(text," PA7:%d ",pa7_duty);
LCD_DisplayStringLine(Line4, (uint8_t *)text);
//清理界面残留
sprintf(text," ");
LCD_DisplayStringLine(Line3, (uint8_t *)text);
LCD_DisplayStringLine(Line5, (uint8_t *)text);
}