[mw_shl_code=c,true]/*********************************************************************************
*Copyright(C)
*FileName: PWM.c
*Author: 陶涛
*Version: v1.1
*Date: 2015/01/16
*Description: 本程序为stm32的高级计时器timer1生成PWM的API,rct6型号上测试过
*Version:
*Function List:
*History:
<Author> <Date> <Version> <Description>
taotao 2015/05/08 1.0 大部分函数改自原子大哥
taotao 2015/05/09 1.1 添加了SPWM的API,以定时器3作为中断,加载新的CCR,占空比值
*Others:
只有高级计时器可以输出互补波
TIM1模块是增强型的定时器模块,可以产生3组6路PWM,同时每组2路PWM为互补,并可以带有死区,可以用来驱动H桥。
硬件上的引脚连接:
PA8---TIM1_CH1 PB13---TIM1_CH1N
PA9---TIM1_CH2 PB14---TIM1_CH2N
PA10--TIM1_CH3 PB15---TIM1_CH3N
**********************************************************************************/
#include <

WM.h>
#include "GPIO.h " //测试用led灯
//主函数初始化中,需要做delay_init(72);和TIM1_PWM_Init(3600-1,0); //预分频数为0 PWM频率=72000/(3600-1+1)=20Khz 周期3600
//这几个占空比更改参数,需要配合TIM1_PWM_Init中的arr使用
u16 CCR1_Val=1800; //设置TIM1通道1输出占空比50%
u16 CCR2_Val=900; //设置TIM1通道1输出占空比25%
u16 CCR3_Val=450; //设置TIM1通道1输出占空比12.5%
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
//第一步:配置时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能定时器3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE); //使能GPIO和服用功能时钟
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //引脚重映射要开这个时钟
//第二步,配置gpio口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10; //PWM输出在PA8,9,10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; //PWM输出在PA7
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 = arr; //设置在自动重装载周期值,周期周期周期周期周期周期周期周期周期周期周期周期
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim,// 采样分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //重复寄存器,用于自动更新pwm占空比
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
//第四步pwm输出配置,TIM_OCInitStructure共七项配置
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2; //设置为pwm1输出模式
/*:PWM模式1-
在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;
在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),
否则为有效电平(OC1REF=1)。
PWM模式2-
在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;
在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。*/
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; //设置输出极性//输出极性和互补极性的有效电平为低
//Polarity_Low实际上是往极性控制位写1,所以会输出高电平
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //使能该通道输出//比较输出使能
//下面几个参数(除了pulse)是高级定时器才会用到,通用定时器不用配置
TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_Low; //设置互补端输出极性//输出极性和互补极性的有效电平为低
TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable; //使能互补端输出
TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Reset; //死区后输出状态
TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Set; //死区后互补端输出状态
//设置通道1捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_Pulse=CCR1_Val;
TIM_OC1Init(TIM1,&TIM_OCInitStructure); //设置通道1
//设置通道2捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_Pulse=CCR2_Val;
TIM_OC2Init(TIM1,&TIM_OCInitStructure);
//设置通道3捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_Pulse=CCR3_Val;
TIM_OC3Init(TIM1,&TIM_OCInitStructure);
//第五步,死区和刹车功能配置,高级定时器才有的,通用定时器不用配置TIM_BDTRInitStructure,共七项配置
TIM_BDTRInitStructure.TIM_OSSRState=TIM_OSSRState_Disable; //运行模式下输出选择//运行模式下“关闭状态”使能
TIM_BDTRInitStructure.TIM_OSSIState=TIM_OSSIState_Disable; //空闲模式下输出选择//关闭模式下“关闭状态”使能
TIM_BDTRInitStructure.TIM_LOCKLevel=TIM_LOCKLevel_OFF; //锁定设置
TIM_BDTRInitStructure.TIM_DeadTime=0xA0; //死区时间设置
TIM_BDTRInitStructure.TIM_Break=TIM_Break_Disable; //刹车功能不使能
TIM_BDTRInitStructure.TIM_BreakPolarity=TIM_BreakPolarity_High; //刹车输入极性 //刹车输入高电平有效
TIM_BDTRInitStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable; //自动输出使能
TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);
//第六步,使能端的打开
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIMx在CCR1上的预装载寄存器,这句的功能是让改变CCR之后马上有效 ,立刻改变占空比
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIMx在CCR2上的预装载寄存器
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIMx在CCR3上的预装载寄存器,这句的功能是让改变CCR之后马上有效 ,立刻改变占空比
TIM_ARRPreloadConfig(TIM1,ENABLE); //使能TIMx在ARR上的预装载寄存器?//立刻改变频率
TIM_Cmd(TIM1,ENABLE); //打开TIM1
//下面这句是高级定时器才有的,输出pwm必须打开
TIM_CtrlPWMOutputs(TIM1,ENABLE); //pwm输出使能,一定要记得打开
}
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
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(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
#define Sample_NUM 33 //采样点
unsigned int SinTab[Sample_NUM]={0x0400,0x04C2,0x057C,0x0629,0x06C2,0x0741,0x07A3,0x07E2,0x07FE,0x07F5,
0x07C7,0x0776,0x0705,0x0678,0x05D5,0x0520,0x0461,0x039F,0x02E0,0x022B,
0x0188,0x00FB,0x008A,0x0039,0x000B,0x0002,0x001E,0x005D,0x00BF,0x013E,
0x01D7,0x0284,0x033E};
unsigned char SinTab_i = 0;
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
{
unsigned int SinTab_j,SinTab_k;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{ TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIMx更新中断标志
SinTab_j=SinTab_i+Sample_NUM/3; //200/3 相差120°
SinTab_k=SinTab_i+Sample_NUM*2/3; //400/3 相差240°
SinTab_i++;
if(SinTab_i == Sample_NUM){SinTab_i = 0;}
if(SinTab_j >= Sample_NUM){SinTab_j = SinTab_j-Sample_NUM;}
if(SinTab_k >= Sample_NUM){SinTab_k = SinTab_k-Sample_NUM;}
TIM1->CCR1 = 7200-SinTab[SinTab_i]*2; //配合主函数的 TIM1_PWM_Init(7200-1,6-1); 使用
TIM1->CCR2 = 7200-SinTab[SinTab_j]*2;
TIM1->CCR3 = 7200-SinTab[SinTab_k]*2;
}
}
[/mw_shl_code]