频率、占空比任意可调的ATIM PWM设计
本例程的功能为,通过按键的短按去调整PWM当前输出的频率,按键长按时则修改当前输出的占空比,设计精度为小数点后两位。TFTLCD上实时显示当前的PWM的频率和占空比信息。功能截图如下,演示视频如上
逻辑分析仪抓取的波形图如下图
实物展示功能如下图
实现过程:
一、设计ATIM高级定时器输出PWM,输出通道为1B,对应IO口为PA7
ATIM初始化函数如下
void DriverAtimInit()
{
__RCC_ATIM_CLK_ENABLE();
ATIM_InitTypeDef ATIM_InitStruct;
ATIM_OCInitTypeDef ATIM_OCInitStruct;
ATIM_InitStruct.BufferState = DISABLE;
ATIM_InitStruct.ClockSelect = ATIM_CLOCK_PCLK;
ATIM_InitStruct.CounterAlignedMode = ATIM_COUNT_MODE_EDGE_ALIGN;
ATIM_InitStruct.CounterDirection = ATIM_COUNTING_UP;
ATIM_InitStruct.CounterOPMode = ATIM_OP_MODE_REPETITIVE;
ATIM_InitStruct.OverFlowMask = DISABLE;
ATIM_InitStruct.Prescaler = ATIM_Prescaler_DIV1; // 计数时钟1MHz
ATIM_InitStruct.ReloadValue = 6400; // 溢出周期10ms
ATIM_InitStruct.RepetitionCounter = 0;
ATIM_InitStruct.UnderFlowMask = DISABLE;
ATIM_Init(&ATIM_InitStruct);
ATIM_OCInitStruct.BufferState = ENABLE;
ATIM_OCInitStruct.OCDMAState = DISABLE;
ATIM_OCInitStruct.OCInterruptSelect = ATIM_OC_IT_UP_COUNTER;
ATIM_OCInitStruct.OCInterruptState = ENABLE;
ATIM_OCInitStruct.OCMode = ATIM_OCMODE_PWM1;
ATIM_OCInitStruct.OCPolarity = ATIM_OCPOLARITY_NONINVERT;
ATIM_OC1BInit(&ATIM_OCInitStruct);
//ATIM_ITConfig(ATIM_CR_IT_OVE, ENABLE);
ATIM_CH1Config(ATIM_CHxB_CIE, ENABLE);
ATIM_SetCompare1B(5000);
ATIM_Cmd(ENABLE);
ATIM_CtrlPWMOutputs(ENABLE);
}
ATIM修改PWM频率跟占空比函数如下
void DriverAtimPwmSet( const uint32_t Freq,const uint16_t Duty)
{
uint16_t FreqSetVlaue = 0;
uint16_t DutySet = 0;
ATIM_InitTypeDef ATIM_InitStruct;
ATIM_OCInitTypeDef ATIM_OCInitStruct;
ATIM_InitStruct.BufferState = DISABLE;
ATIM_InitStruct.ClockSelect = ATIM_CLOCK_PCLK;
ATIM_InitStruct.CounterAlignedMode = ATIM_COUNT_MODE_EDGE_ALIGN;
ATIM_InitStruct.CounterDirection = ATIM_COUNTING_UP;
ATIM_InitStruct.CounterOPMode = ATIM_OP_MODE_REPETITIVE;
ATIM_InitStruct.OverFlowMask = DISABLE;
ATIM_InitStruct.Prescaler = ATIM_Prescaler_DIV1; 钟1MHz
ATIM_InitStruct.RepetitionCounter = 0;
ATIM_InitStruct.UnderFlowMask = DISABLE;
FreqSetVlaue = _64M_HZ/Freq;
ATIM_InitStruct.ReloadValue = FreqSetVlaue;
DutySet = ( FreqSetVlaue * Duty)/10000;
ATIM_Init(&ATIM_InitStruct);
ATIM_SetCompare1B(DutySet);```
}
按键需要支持长按短按,本例程采用KEY1为操作按键,main函数处理逻辑如下
int main(void )
{
uint32_t time;
uint32_t Freq=1000;
uint16_t Duty=5000;
uint32_t FreqPeriod = 10000;
uint16_t DutyPeriod=1000;
uint8_t state =0;
SysClikInit();
GpioInit();
Uart_Init();
Lcd_Init();
Lcd_Clear(GRAY0);
Gui_DrawFont_GBK16(15,5,BLACK,GRAY0,"Current Freq");
numToString(Freq/1000);
Gui_DrawFont_GBK16(15,25,BLACK,GRAY0,strValue);
Gui_DrawFont_GBK16(45,25,BLACK,GRAY0,"k");
Gui_DrawFont_GBK16(15,45,BLACK,GRAY0,"Current Duty");
numToString(Duty/100);
Gui_DrawFont_GBK16(15,65,BLACK,GRAY0,strValue);
Gui_DrawFont_GBK16(45,65,BLACK,GRAY0,"%");
DriverAtimInit();
DriverAtimPwmSet(5188,8777);
DriverKeyStructInit(&keyStruct_S1,DriverS1_KeyRead);
while(1)
{
`
if(globlTimes - time >500)
{
CW_GPIOC->ODR ^= GPIO_PIN_13;
time = globlTimes ;
}
switch(DriverKeyCheck(&keyStruct_S1))
{
case ShortPressState:
Freq+=FreqPeriod;
if(Freq>=200000)
{
Freq = 1000;
}
Lcd_Clear(GRAY0);
Gui_DrawFont_GBK16(15,5,BLACK,GRAY0,"Current Freq");
numToString(Freq/1000);
Gui_DrawFont_GBK16(15,25,BLACK,GRAY0,strValue);
Gui_DrawFont_GBK16(45,25,BLACK,GRAY0,"k");
Gui_DrawFont_GBK16(15,45,BLACK,GRAY0,"Current Duty");
numToString(Duty/100);
Gui_DrawFont_GBK16(15,65,BLACK,GRAY0,strValue);
Gui_DrawFont_GBK16(45,65,BLACK,GRAY0,"%");
break;
case LongPressState :
Duty+=DutyPeriod;
if(Duty>=10000)
{
Duty = 500;
}
Lcd_Clear(GRAY0);
Gui_DrawFont_GBK16(15,5,BLACK,GRAY0,"Current Freq");
numToString(Freq/1000);
Gui_DrawFont_GBK16(15,25,BLACK,GRAY0,strValue);
Gui_DrawFont_GBK16(45,25,BLACK,GRAY0,"k");
Gui_DrawFont_GBK16(15,45,BLACK,GRAY0,"Current Duty");
numToString(Duty/100);
Gui_DrawFont_GBK16(15,65,BLACK,GRAY0,strValue);
Gui_DrawFont_GBK16(45,65,BLACK,GRAY0,"%");
break;
default:break;
}
}
return 0;
}