GeBalanceBot/Hardware/Firmware/GeBalanceBot_Firmware v1.0/DRV/bsp_timer.c

248 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/******************** (C) COPYRIGHT 2024 GeekRebot *****************************
* File Name : bsp_timer.c
* Current Version : V1.0 & ST 3.5.0
* Author : zhanli 719901725@qq.com
* Date of Issued : 2024.01.09
* Comments : oled的iic方式驱动
SCL -> PA10SDA -> PA11
timer3 电机控制pwm,用到了timer3的ch3和ch4即 PB0-PB1连接电机驱动
的使能端PWMA左电机和 PWMB右电机
timer1 用于系统100ms定时功能
timer2 用于左电机编码器计数
timer4 用于右电机编码器计数
********************************************************************************/
#include "bsp_timer.h"
//***************************定时器3初始化 给电机提供PWM***************************//
// TIM_Period / Auto Reload Register(ARR) = 1000 TIM_Prescaler--71
//arr自动重装寄存器psc分频系数
//PWM的频率 = 72MHz/ARR/PCS 例如 20K = 72M/3600/1 = 20K
//=====初始化PWM 20KHZ 高频可以防止电机低频时的尖叫声
// ARR= 3599 时频率为20Khz
//PB0控制PWMA--right motoPB1控制PWMB--left moto。STBY直接拉高
//arr自动重装寄存器psc分频系数
//PWM的频率 = 72MHz/ARR/PCS 例如 20K = 72M/3600/1 = 20K
void MOTO_PWM_Init(u32 arr, int psc)
{
TIM_OCInitTypeDef TIM_OCInitSructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = arr-1; //自动重新装载寄存器周期的值澹ㄥ计数值澹)
TIM_TimeBaseStructure.TIM_Prescaler = psc; //时钟分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //对外部时钟进行采样的时钟分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //参数初始化
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
//配置pwm输出端口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//设置通道3 pwm参数
TIM_OCInitSructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitSructure.TIM_OutputState= TIM_OutputState_Enable;
TIM_OCInitSructure.TIM_Pulse = 0;//占空比= 50/100
TIM_OCInitSructure.TIM_OCPolarity = TIM_OCPolarity_High;//当定时器计数值小于CCR1_Val时为高电平
TIM_OC3Init(TIM3, &TIM_OCInitSructure);//参数初始化
TIM_OC3PolarityConfig(TIM3, TIM_OCPreload_Enable);//开始输出pwm
//设置通道4 pwm参数
TIM_OCInitSructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitSructure.TIM_OutputState= TIM_OutputState_Enable;
TIM_OCInitSructure.TIM_Pulse = 0;//占空比= 50/100
TIM_OCInitSructure.TIM_OCPolarity = TIM_OCPolarity_High;//当定时器计数值小于CCR1_Val时为高电平
TIM_OC4Init(TIM3, &TIM_OCInitSructure);//参数初始化
TIM_OC4PolarityConfig(TIM3, TIM_OCPreload_Enable);//开始输出pwm
TIM_ARRPreloadConfig(TIM3, ENABLE);//启动自动重装
TIM_Cmd(TIM3, ENABLE);//启动定时
}
//占空比 = TIMx_CCRx / TIMx_ARR
//moto_r右轮电机moto_l左轮电机. 数值 0-100
void Motor_PWMOut(u16 moto_l, u16 moto_r)
{
TIM_OCInitTypeDef TIM_OCInitSructure;
TIM_OCInitSructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitSructure.TIM_OutputState= TIM_OutputState_Enable;
//CH3 右电机
TIM_OCInitSructure.TIM_Pulse = moto_l; // 占空比= ccr/100
TIM_OC3Init(TIM3, &TIM_OCInitSructure); // 参数初始化
TIM_OC3PolarityConfig(TIM3, TIM_OCPreload_Enable); // 开始输出pwm
//CH4 左电机
TIM_OCInitSructure.TIM_Pulse = moto_r; // 占空比= ccr /100
TIM_OC4Init(TIM3, &TIM_OCInitSructure); // 参数初始化
TIM_OC4PolarityConfig(TIM3, TIM_OCPreload_Enable); // 开始输出pwm
TIM_ARRPreloadConfig(TIM3, ENABLE); // 启动自动重装
}
//***************************定时器1初始化 系统每10ms处理一次中断更新数据更新pwm等***************************//
void Timer6_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
// 计数是从0开始所以9999即是0~9999计数10000个
TIM_TimeBaseStructure.TIM_Period = 2999; //自动重新装载寄存器周期)
// STM32晶振是72Mhz每计算一个count的时间 = 72Mhz / (Prescaler + 1)
// 所以1us计算时间就是72Mhz/(71+1)=1Mhz, 1Khz = 1ms 1Mhz = 1us
// Tim6的周期实际是72Mhz/(TIM_Prescaler + 1) * (1 + TIM_Period)
// 100ms配置, 72Mhz / (719 + 1) * (9999 + 1) = 10us * 10000 = 100ms
// 5ms配置72Mhz / (71 + 1) * (4999 + 1) = 1us * 5000 = 5ms
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 时钟分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 对外部时钟进行采样的时钟分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //高级定时器1是用定时器功能配置这个才可以是正常的计数频率一开始的72mhz 值得注意的地方
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure); // 参数初始化
TIM_ClearFlag(TIM6, TIM_FLAG_Update);
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
NVIC_InitStructure.NVIC_IRQChannel=TIM6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM6, ENABLE);//启动定时器
}
//***************************定时器2初始化 ,使用编码器功能***************************//
//左电机编码器计数
//PA0----接 编码器A相 或者电机驱动的B2B标识
//PA1----接 编码器B相 或者电机驱动的B2A标识
void Encoder_Init_TIM2(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器4的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PB端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOB
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器
TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
//Reset counter
TIM_SetCounter(TIM2,0);
TIM_Cmd(TIM2, ENABLE);
}
//***************************定时器4初始化 ,使用编码器功能***************************//
//右电机编码器计数
//PB6----接 编码器B相 或者电机驱动的B1A标识
//PB7----接 编码器A相 或者电机驱动的B1B标识
void Encoder_Init_TIM4(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能定时器4的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器
TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上计数
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM4, &TIM_ICInitStructure);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);//清除TIM的更新标志位
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
//Reset counter
TIM_SetCounter(TIM4,0);
TIM_Cmd(TIM4, ENABLE);
}
/**************************************************************************
函数功能:单位时间读取编码器计数
入口参数:定时器
返回 值:速度值
**************************************************************************/
int Read_Encoder(u8 TIMX)
{
int Encoder_TIM;
switch(TIMX)
{
case 2:
Encoder_TIM = (short)TIM2 -> CNT;
TIM2 -> CNT = 30000;
break;
case 3:
Encoder_TIM = (short)TIM3 -> CNT;
TIM3 -> CNT = 30000;
break;
case 4:
Encoder_TIM = (short)TIM4 -> CNT;
TIM4 -> CNT = 30000;
break;
default:
Encoder_TIM = 0;
}
return Encoder_TIM;
}
/**************************************************************************
函数功能TIM4中断服务函数
入口参数:无
返回 值:无
**************************************************************************/
void TIM4_IRQHandler(void)
{
if(TIM4->SR&0X0001)//溢出中断
{
}
TIM4->SR&=~(1<<0);//清除中断标志位
}
/**************************************************************************
函数功能TIM2中断服务函数
入口参数:无
返回 值:无
**************************************************************************/
void TIM2_IRQHandler(void)
{
if(TIM2->SR&0X0001)//溢出中断
{
}
TIM2->SR&=~(1<<0);//清除中断标志位
}