STM32F103C8T6拥有72MHz的主频,我们通过一个小小的应用来直观的感受下她的速度。
通过Timer3和Timer4的PWM实现一个简单的正交方波信号发生器(可用来模拟正交编码器)。
首先,在定时器初始化函数中启动定时器,定时器及引脚配置如下:
void TIMER3_INIT(void)//模拟霍尔A相
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//配置为上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//打开6引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);//GPIOA初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_InternalClockConfig(TIM3);//定时器1启用内部时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//时基单元配置
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100-1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1;//10k载频
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//初始化其他未设置的变量
// TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
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 = 50;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);//(第1通道)
TIM_SetCounter(TIM3, 0);
TIM_Cmd(TIM3, ENABLE);//开定时器3
}
void TIMER4_INIT(void)//虚拟PWM,模拟霍尔B相
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//配置为上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//打开6引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);//GPIOA初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_InternalClockConfig(TIM4);//定时器1启用内部时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//时基单元配置
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100-1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1;//10k载频
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 25;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//初始化其他未设置的变量
// TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
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 = 50;
TIM_OC1Init(TIM4, &TIM_OCInitStructure);//(第1通道)
TIM_SetCounter(TIM4, 0);
TIM_Cmd(TIM4, ENABLE);//开定时器3
}
主函数中,直接调用两个定时器初始化函数,
int main()
{
TIMER3_INIT();
TIMER4_INIT();
while(1)
{
}
}
然后用示波器的1,2通道测量GPIOA6和GPIOB6,得到如下波形:
可以看出, 2通道滞后1通道9.6us,原因在于在Timer3开启与Timer4开启之间还间隔了Timer4的配置过程。由此可以比较直观的展现这款MCU的速度。
在做正交前,先尽可能的使两个定时器的PWM波同步,一种比较简单的方法是在主函数中顺次调用TIM_Cmd(),而不在初始化函数中调用。
int main()
{
TIMER3_INIT();
TIMER4_INIT();
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM4, ENABLE);
while(1)
{
}
}
再次测量得到下图:
两个PWM波对齐后,考虑实现正交,一种比较简单的方法是在初始化中调用TIM_SetCounter(),考虑本文设置的计数周期为100,为了实现两个方波正交(Timer3超前),则在Timer3的计数器中预装25(1/4周期)。测量结果如下: