一.程序编写思路
1.1串口接收数据方法选择
经查阅资料本次想采用以下两种方法之一来配置串口接收部分:1.定时器判断超时、2.串口空闲中断
1.11定时器判断超时接收
入选原因是modbus rtu协议中,主机在接收从机数据后,在3.5个字节时间后认为数据包接收完毕。那在这种情况下,一般的做法是设置一个定时器,在每接收到一个字节时清零定时器重新计数,直到定时器超过3.5个字节时间后触发中断即默认数据包接收完毕。此方法对于硬件配置比较低,也属于通常做法,方便后面移植到其他单片机。
1.12串口空闲中断判断超时接收
入选原因是STM32单片机拥有这个功能,可以自动判断串口是否接受完一帧数据。与定时器判断超时相比较能节省一个定时器,并在程序上简单一些
1.13最终结论
本次还是决定使用定时器判断超时,主要是为了后面方便移植到其他单片机。
1.2串口接收数据方法实现
选择好串口接收数据的方法后,开始配置STM32的串口和定时器,因为开发板采用的是串口1连接的RS485,所以程序需要配置串口1。选用通用定时器1做串口接收超时判断。
二.程序实现串口超时接收判断一帧数据
2.1配置串口1为9600、8、n、1
void uart1_init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //端口配置,A8为485换向引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOA,GPIO_Pin_8); //PA.8 输出高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9,USART1_TX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10,USART1_RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
RS485_RE=0; //485默认接收
}
2.2配置串口1中断
/**************************************************************************
*函数名称:void USART1_IRQHandler(void)
*函数功能:串口1中断函数
*输入参数:无
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
uart1_rx_buf[uart1_rx_count] = USART_ReceiveData(USART1); //接收到的数据填入uart1_rx_buf
uart1_rx_count++; //串口1接受计数加1
uart1_rx_timer_count=0; //每次接收到数据,串口1接收计数都重新开始计时
uart1_rx_timer_count_flag=1; //串口1是否开始进入超时计算标志位置1
}
}
2.3配置定时器1为1ms进入一次中断
/*********************************************
定时器 CH1 CH2 CH3 CH4
timer1 PA8 PA9 PA10 PA11 做串口超时及喂狗计时
timer2 PA0 PA1 PA2 PA3 √
timer3 PA6 PA7 PB0 PB1 √
timer4 PB6 PB7 PB8 PB9 √
**********************************************/
/**************************************************************************
*函数名称:void TIM1_Int_Init(u16 arr,u16 psc)
*函数功能:定时器1初始化
*输入参数:arr:定时器累积到此数值进入中断,psc:设置定时器每次加一个数的间隔时间
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM1_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //时钟使能
//定时器TIM1初始化
TIM_TimeBaseStructure.TIM_Period = arr-1; //设置
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能指定的TIM1中断,允许更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; //TIM1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
2.4配置定时器1中断
/**************************************************************************
*函数名称:void TIM1_UP_IRQHandler(void)
*函数功能:定时器1中断程序,每1ms进入一次中断,负责串口1超时接收判断、看门狗喂狗计数、LED指示灯计数
*输入参数:无
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM1_UP_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) //检查TIM1更新中断发生与否
{
TIM_ClearITPendingBit(TIM1, TIM_IT_Update); //清除TIM1更新中断标志
feed_watchdog_count++; //喂狗计时加1
if(uart1_rx_timer_count_flag==1) //如果串口接收到数据,会将计数清零,标志位置1,定时器开始超时计时
{
uart1_rx_timer_count++;
if(uart1_rx_timer_count>5) //设置5ms超时接收完成判断
{
uart1_rx_timer_count=0;
uart1_timeout_flag=1; //串口1超时接收完成标志位置1,主循环检测到则开始分析串口1数据
}
}
if(feed_watchdog_count>800) //看门狗计时判断
{
feed_watchdog_count_flag=1; //喂狗标志位置1,主循环检测到则开始喂狗
}
}
}
2.41验证
2.5设置16路PWM初始化
#include "pwm.h"
#include "modbusrtu.h"
/*********************************************
定时器 CH1 CH2 CH3 CH4
timer1 PA8 PA9 PA10 PA11 做串口超时及喂狗计时
timer2 PA0 PA1 PA2 PA3 √
timer3 PA6 PA7 PB0 PB1 √
timer4 PB6 PB7 PB8 PB9 √
**********************************************/
/**************************************************************************
*函数名称:void TIM2_PWM_CH1_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器2通道1初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM2_PWM_CH1_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIO外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //TIM2_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//始终不分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM2, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM2 OC1
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR1上的预装载寄存器
TIM_SetCompare1(TIM2,duty_ratio); //设置占空比
TIM_Cmd(TIM2, ENABLE); //使能TIM2
TIM2->CCER&=0xFFFE; //关闭第1路PWM使能
}
/**************************************************************************
*函数名称:void TIM2_PWM_CH2_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器2通道2初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM2_PWM_CH2_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM2_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM2, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM2 OC2
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR2上的预装载寄存器
TIM_SetCompare2(TIM2,duty_ratio);
TIM_Cmd(TIM2, ENABLE); //使能TIM2
TIM2->CCER&=0xFFEF; //关闭第2路PWM使能
}
/**************************************************************************
*函数名称:void TIM2_PWM_CH3_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器2通道3初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM2_PWM_CH3_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //TIM2_CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC3Init(TIM2, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM2 OC3
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM3在CCR3上的预装载寄存器
TIM_SetCompare3(TIM2,duty_ratio);
TIM_Cmd(TIM2, ENABLE); //使能TIM2
TIM2->CCER&=0xFEFF; //关闭第3路PWM使能
}
/**************************************************************************
*函数名称:void TIM3_PWM_CH4_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器2通道4初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM2_PWM_CH4_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //TIM2_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC4Init(TIM2, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM2 OC4
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR4上的预装载寄存器
TIM_SetCompare4(TIM2,duty_ratio);
TIM_Cmd(TIM2, ENABLE); //使能TIM2
TIM2->CCER&=0xEFFF; //关闭第4路PWM使能
}
/**************************************************************************
*函数名称:void TIM3_PWM_CH1_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器3通道1初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.03.28
**************************************************************************/
void TIM3_PWM_CH1_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM3_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC1
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR1上的预装载寄存器
TIM_SetCompare1(TIM3,duty_ratio);
TIM_Cmd(TIM3, ENABLE); //使能TIM3
TIM3->CCER&=0xFFFE; //关闭第5路PWM使能
}
/**************************************************************************
*函数名称:void TIM3_PWM_CH2_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器3通道2初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM3_PWM_CH2_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //TIM3_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器
TIM_SetCompare2(TIM3,duty_ratio);
TIM_Cmd(TIM3, ENABLE); //使能TIM3
TIM3->CCER&=0xFFEF; //关闭第6路PWM使能
}
/**************************************************************************
*函数名称:void TIM3_PWM_CH3_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器3通道3初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM3_PWM_CH3_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能GPIOB外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //TIM3_CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC3Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC3
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器
TIM_SetCompare3(TIM3,duty_ratio);
TIM_Cmd(TIM3, ENABLE); //使能TIM3
TIM3->CCER&=0xFEFF; //关闭第7路PWM使能
}
/**************************************************************************
*函数名称:void TIM3_PWM_CH4_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器3通道4初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM3_PWM_CH4_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOA外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM3_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC4Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC4
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR4上的预装载寄存器
TIM_SetCompare4(TIM3,duty_ratio);
TIM_Cmd(TIM3, ENABLE); //使能TIM2
TIM3->CCER&=0xEFFF; //关闭第8路PWM使能
}
/**************************************************************************
*函数名称:void TIM4_PWM_CH1_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器4通道1初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM4_PWM_CH1_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM4_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM4, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM4 OC1
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); //使能TIM4在CCR1上的预装载寄存器
TIM_SetCompare1(TIM4,duty_ratio);
TIM_Cmd(TIM4, ENABLE); //使能TIM4
TIM4->CCER&=0xFFFE; //关闭第9路PWM使能
}
/**************************************************************************
*函数名称:void TIM4_PWM_CH2_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器4通道2初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM4_PWM_CH2_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器4时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //TIM4_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM4, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM4 OC2
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable); //使能TIM4在CCR2上的预装载寄存器
TIM_SetCompare2(TIM4,duty_ratio);
TIM_Cmd(TIM4, ENABLE); //使能TIM4
TIM4->CCER&=0xFFEF; //关闭第10路PWM使能
}
/**************************************************************************
*函数名称:void TIM4_PWM_CH3_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器2通道1初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM4_PWM_CH3_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器4时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM4_CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC3Init(TIM4, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM4 OC3
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); //使能TIM4在CCR3上的预装载寄存器
TIM_SetCompare3(TIM4,duty_ratio);
TIM_Cmd(TIM4, ENABLE); //使能TIM4
TIM4->CCER&=0xFEFF; //关闭第11路PWM使能
}
/**************************************************************************
*函数名称:void TIM4_PWM_CH4_Init(u16 fre,u16 duty_ratio)
*函数功能:定时器4通道4初始化
*输入参数:fre:频率,duty_ratio:占空比(0-100)
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void TIM4_PWM_CH4_Init(u16 fre,u16 duty_ratio)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
fre=10000/fre;
duty_ratio=(fre*duty_ratio)/100;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器4时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB外设
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TIM4_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
TIM_TimeBaseStructure.TIM_Period = fre-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到多少us进入中断
TIM_TimeBaseStructure.TIM_Prescaler =71; //设置用来作为TIMx时钟频率除数的预分频值 ,1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC4Init(TIM4, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM4 OC4
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); //使能TIM4在CCR4上的预装载寄存器
TIM_SetCompare4(TIM4,duty_ratio);
TIM_Cmd(TIM4, ENABLE); //使能TIM4
TIM4->CCER&=0xEFFF; //关闭第12路PWM使能
}
/**************************************************************************
*函数名称:void All_Timer_Pwm_Init(void)
*函数功能:12路PWM初始化函数
*输入参数:无
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void All_Timer_Pwm_Init(void)
{
TIM2_PWM_CH1_Init((Pwm_Status[25]<<8)+Pwm_Status[26],(Pwm_Status[31]<<8)+Pwm_Status[32]);
TIM2_PWM_CH2_Init((Pwm_Status[25]<<8)+Pwm_Status[26],(Pwm_Status[33]<<8)+Pwm_Status[34]);
TIM2_PWM_CH3_Init((Pwm_Status[25]<<8)+Pwm_Status[26],(Pwm_Status[35]<<8)+Pwm_Status[36]);
TIM2_PWM_CH4_Init((Pwm_Status[25]<<8)+Pwm_Status[26],(Pwm_Status[37]<<8)+Pwm_Status[38]);
TIM3_PWM_CH1_Init((Pwm_Status[27]<<8)+Pwm_Status[28],(Pwm_Status[39]<<8)+Pwm_Status[40]);
TIM3_PWM_CH2_Init((Pwm_Status[27]<<8)+Pwm_Status[28],(Pwm_Status[41]<<8)+Pwm_Status[42]);
TIM3_PWM_CH3_Init((Pwm_Status[27]<<8)+Pwm_Status[28],(Pwm_Status[43]<<8)+Pwm_Status[44]);
TIM3_PWM_CH4_Init((Pwm_Status[27]<<8)+Pwm_Status[28],(Pwm_Status[45]<<8)+Pwm_Status[46]);
TIM4_PWM_CH1_Init((Pwm_Status[29]<<8)+Pwm_Status[30],(Pwm_Status[47]<<8)+Pwm_Status[48]);
TIM4_PWM_CH2_Init((Pwm_Status[29]<<8)+Pwm_Status[30],(Pwm_Status[49]<<8)+Pwm_Status[50]);
TIM4_PWM_CH3_Init((Pwm_Status[29]<<8)+Pwm_Status[30],(Pwm_Status[51]<<8)+Pwm_Status[52]);
TIM4_PWM_CH4_Init((Pwm_Status[29]<<8)+Pwm_Status[30],(Pwm_Status[53]<<8)+Pwm_Status[54]);
}