STM32具有多个定时器,这里采用的是STM32F103C8T6高级定时器TIM1的四个通道(CH1,CH2,CH3,CH4)。
操作顺序:
1.配置GPIO(根据stm32外设及其引脚映射,详解下方有图表)
2.配置TIM的PWM1模式
3.书写相应的函数
我们的目标是
在PA8和PA9实现呼吸灯效果:1.PA8呼吸,PA9呼吸
2.PA8呼吸,PA9不呼吸
1。配置GPIO
由GPIO引脚映射表(下图)可知,TIM1的CH1---PA8,CH2---PA9,先拿这两个试试刀,我们的目标是在PA8和PA9实现呼吸灯效果:1.PA8呼吸,PA9呼吸
2.PA8呼吸,PA9不呼吸
本图片来源于哔哩哔哩-江科大自化协-stm32入门教程资料,具体资料请移步哔哩哔哩-江科大自化协,如有侵权,请告知删除
由上图可知,在第29和30行,PA8引脚默认复用了USART1_CK和MCO和TIM1_CH1,PA9默认复用了USART1_TX和TIM1_CH2。
故配置PA8和PA9为推挽输出模式
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE );//开启TIM1时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//推挽模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8 |GPIO_Pin_9;//配置PA8,PA9
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//速度选最快
GPIO_Init (GPIOA ,&GPIO_InitStructure);
2.配置TIM1的pwm模式
首先是常规的定时器配置
先是ARR,PSC,CCR计算公式
本图片来源于哔哩哔哩-江科大自化协-stm32入门教程资料,具体资料请移步哔哩哔哩-江科大自化协,如有侵权,请告知删除
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE );//开时钟
TIM_InternalClockConfig (TIM1);//对不需要配置的项给默认值
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1 ;//时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up ;//向上计数
TIM_TimeBaseInitStructure.TIM_Period=100-1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=720-1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit (TIM1 ,&TIM_TimeBaseInitStructure);
接下来是定时器输出(OC,即Output Compare)配置,然后分别是TIM1的CH1和CH2
TIM_OCInitTypeDef TIM_OCInitStructure;//结构体初始化
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//开启PWM1模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//使能输出
TIM_OCInitStructure.TIM_Pulse = 0;// 设置占空比大小,因为接下来的是OC1,所以是通道1的占空比
TIM_OC1Init(TIM1, &TIM_OCInitStructure);//TIM1的通道1
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1(即通道1)上的预装载寄存器
TIM_OCInitStructure.TIM_Pulse = 0;// 设置占空比大小 ,同理是因为接下来的是OC2,所以是通道2的占空比
TIM_OC2Init(TIM1, &TIM_OCInitStructure);//TIM1的通道2
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR2(即通道2)上的预装载寄存器
这里我把两个通道的PWM都给了输出为0,后面可以再配置,如果你需要你可以先在这里配置,0-100的区间,因为我在上面是配置了ARR=99,PSC=719。
然后呢,是高级定时器必加函数和使能TIM1,配置了但是不工作可能是这个高级定时器使能函数没配TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);//高级定时器必加
TIM_Cmd (TIM1,ENABLE);//使能整个TIM1
以上就是void PWM_Init(void)的内容了,初始化配置ok
2.接下来是实现呼吸灯了,首先是介绍一个函数TIM_SetCompare1(TIM1,Compare );,它可以改变TIM1的pwm值,如果是TIM_SetCompare1,则是改变TIM1的通道1,若是TIM_SetCompare2,则是改变TIM1的通道2
先封装一下这个函数,便于理解
void PWM_Compare1(uint8_t Compare) //PA8
{
TIM_SetCompare1(TIM1,Compare );
}
上面的Compare就是要改变的PWM占空比,0-100
对CH2一样封装
void PWM_Compare2(uint8_t Compare) //PA9
{
TIM_SetCompare2(TIM1,Compare );
}
3.OK了,接下来是主函数
顺便提一下,uint8_t就是char,1字节
uint8_t i;
int main(void)
{
PWM_Init();
while(1)
{
for(i=0;i<100;i++)
{
PWM_Compare1(i);
Delay_ms (10);
}
}
}
对了还有Delay_ms()
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
以上是现象1代码,两灯同时呼吸
以下是现象2代码,红灯(PA8呼吸),黄灯(PA9)不亮,抱歉没有视频
uint8_t i;
int main(void)
{
PWM_Init();
while(1)
{
for(i=0;i<100;i++)
{
PWM_Compare1(i);
PWM_Compare2(i);
Delay_ms (100);
}
}
}
常见问题:1.没有添加
TIM_CtrlPWMOutputs(TIM1, ENABLE);//高级定时器必加
TIM_Cmd (TIM1,ENABLE);//使能整个TIM1
2.分别控制单通道需要分别应用不同OC1,OC2
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
3.改变不同的通道的占空比(PWM)需要不同的TIM_SetCompare1(TIM1,Compare );
TIM_SetCompare1(TIM1,Compare );
TIM_SetCompare2(TIM1,Compare );