(为免误导,特免责声明如下:本文所有内容,只是基于个人当前理解和实际做法,后面亦会有更正和修订,但任何版本都不免有个人能力有限、理解有误或者工作环境不同的状况,故文中内容仅供参考。任何人都可以借鉴或者直接使用代码片段,但对任何直接引用或者借鉴产生的技术问题等后果,作者不承担任何责任。)
采用Stm32单片机产生脉宽可调的4路PWM信号驱动桥式电路。PWM周期4us,4路中1、3两路是同步的,2.4两路也是同步的,1,3与2,4之间错开。pwm的脉宽是一组设定的值,不停轮换发送。
TIM_TimeBaseStructure.TIM_Period = 143; //定时器周期
TIM_TimeBaseStructure.TIM_Prescaler=0; //设置预分频:不预分频,即为72
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分频系数:不分频
TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_CenterAligned1;//中央对齐模式1
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: 通道2,4 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //配置为PWM模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 144;//TIM_3_CH24_CCR; //设置跳变值,当计数器计数到这个值时,电平发生跳变
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //当定时器计数值小于CCR1_Val时为高电平
TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //TIM3 PWM 通道2 PA7
TIM_OC4Init(TIM3, &TIM_OCInitStructure); //TIM3 PWM 通道4 PB1
/* PWM1 Mode configuration: 通道1,3*/
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置为PWM模式1
TIM_OCInitStructure.TIM_Pulse = 0;//TIM_34_CH2_CCR; //
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //TIM3 PWM 通道1 PA6
TIM_OC3Init(TIM3, &TIM_OCInitStructure); //TIM3 PWM 通道3 PB0
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//TIM3 PWM 通道1 设置
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//TIM3 PWM 通道2 设置
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);//TIM3 PWM 通道3 设置
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);//TIM3 PWM 通道4 设置
//设置高频参数
/*输入参数: uKHz 0-250:代表100-350 kHz
uPercentage 0-45:占空比 0-45%
参数不在范围内返回错误
*/
u8 PWM_T3_SetPara(u8 uKHz,u8 uPercentage)
{
u16 uFreq,uPeriod,uCCR1,uCCR2;
if((uKHz>250) || (uPercentage>45))return 1;
uFreq=uKHz+100; //将0-250映射到100-350KHz
uPeriod=36000/uFreq;
uCCR1=uPeriod*uPercentage/100;
uCCR2=uPeriod-uCCR1;
TIM3->CNT=uCCR1+1; //把计时器当前计数值放在中间,时钟还没启用,计数值不会变,所以四路PWM都没有输出
TIM3->ARR=uPeriod;
TIM3->CCR1=uCCR1;//
TIM3->CCR3=uCCR1;//
TIM3->CCR2=uCCR2;//
TIM3->CCR4=uCCR2;//
return 0;
}
//启动TIM3 的四路PWM
void ENPWM_TIM3(void)
{
TIM_Cmd(TIM4, ENABLE);
TIM_ClearITPendingBit( TIM4, TIM_IT_Update);
TIM_ITConfig( TIM4, TIM_IT_Update, ENABLE);
PWM_T3_SetPara(sysWorkPara[0],sysWorkPara[1]);//设置高频PWM参数
TIM_SelectOCxM(TIM3,TIM_Channel_1,TIM_OCMode_PWM1);
TIM_CCxCmd(TIM3,TIM_Channel_1,TIM_CCx_Enable);
TIM_SelectOCxM(TIM3,TIM_Channel_3,TIM_OCMode_PWM1);
TIM_CCxCmd(TIM3,TIM_Channel_3,TIM_CCx_Enable);
TIM_SelectOCxM(TIM3,TIM_Channel_2,TIM_OCMode_PWM2);
TIM_CCxCmd(TIM3,TIM_Channel_2,TIM_CCx_Enable);
TIM_SelectOCxM(TIM3,TIM_Channel_4,TIM_OCMode_PWM2);
TIM_CCxCmd(TIM3,TIM_Channel_4,TIM_CCx_Enable);
TIM_CtrlPWMOutputs( TIM3, ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
//停止TIM3的四路PWM
void DENPWM_TIM3(void)
{
TIM_Cmd( TIM3, DISABLE); // 关闭定时器3
TIM3->CNT=72;
TIM_SelectOCxM(TIM3,TIM_Channel_2,TIM_ForcedAction_InActive);
TIM_SelectOCxM(TIM3,TIM_Channel_4,TIM_ForcedAction_InActive);
TIM_SelectOCxM(TIM3,TIM_Channel_1,TIM_ForcedAction_InActive);
TIM_SelectOCxM(TIM3,TIM_Channel_3,TIM_ForcedAction_InActive);
}
u32 DMA_AddrofData[8]={0,(u32)DMA_Currency1_Data,(u32)DMA_Currency2_Data,(u32)DMA_Currency3_Data,(u32)DMA_Currency4_Data,(u32)DMA_Currency5_Data,(u32)DMA_Currency6_Data,(u32)DMA_Currency7_Data};
#define DMA_CHAN DMA1_Channel3 /*DMA 通道,根据激发条件*/
void DMA_PWM_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn; /*指定DMA通道DMA1_Channel3*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /*开中断*/
NVIC_Init(&NVIC_InitStructure);
}
void DMA_PWM_Start(void)
{
if(!DMA_DataNumbers)return;
else DMA_SetCurrDataCounter(DMA_CHAN,DMA_DataNumbers); /*再次重启需要重新设置数据量*/
DMA_Cmd(DMA_CHAN, ENABLE);/* DMA1 Channel3 enable */
TIM3->CNT=72; //把计时器当前计数值放在中间,时钟还没启用,计数值不会变,所以四路PWM都没有输出
TIM3->ARR=143;
TIM3->CCR1=28;//
TIM3->CCR3=28;//
TIM3->CCR2=116;//
TIM3->CCR4=116;//
TIM_SelectOCxM(TIM3,TIM_Channel_1,TIM_OCMode_PWM1);
TIM_CCxCmd(TIM3,TIM_Channel_1,TIM_CCx_Enable);
TIM_SelectOCxM(TIM3,TIM_Channel_3,TIM_OCMode_PWM1);
TIM_CCxCmd(TIM3,TIM_Channel_3,TIM_CCx_Enable);
TIM_SelectOCxM(TIM3,TIM_Channel_2,TIM_OCMode_PWM2);
TIM_CCxCmd(TIM3,TIM_Channel_2,TIM_CCx_Enable);
TIM_SelectOCxM(TIM3,TIM_Channel_4,TIM_OCMode_PWM2);
TIM_CCxCmd(TIM3,TIM_Channel_4,TIM_CCx_Enable);
TIM_Cmd(TIM3, ENABLE);
TIM_CtrlPWMOutputs( TIM3, ENABLE);
}
void DMA_PWM_SetWidth(u8 uWidId)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DataNumbers=DMA_DataNumofCurrency[uWidId];
DMA_DeInit(DMA_CHAN);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM3->DMAR); /*DMA外设地址,Burst 模式选择TIM3的DMAR*/
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DMA_AddrofData[uWidId]; //src
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //内存到外设
DMA_InitStructure.DMA_BufferSize = DMA_DataNumbers;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//传输完成结束,不做循环传输:DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA_CHAN, &DMA_InitStructure);
TIM_DMAConfig(TIM3, TIM_DMABase_CCR1,TIM_DMABurstLength_4Transfers);//设置burst 方式DMA,一次传4个外设地址,CCR1 CCR2 CCR3 ,CCR4
//
TIM_DMACmd(TIM3, TIM_DMA_CC4, ENABLE); //采用 CH4的比较事件作为DMA请求信号,所以DMA通道是channel3
DMA_ITConfig(DMA_CHAN, DMA_IT_TC, ENABLE); //开中断
}
/**
DMA 传输完成中断,
*/
void DMA1_Channel3_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC3))
{
TIM_Cmd( TIM3, DISABLE); // 关闭定时器3
TIM3->CNT=72;
TIM_SelectOCxM(TIM3,TIM_Channel_2,TIM_ForcedAction_InActive);
TIM_SelectOCxM(TIM3,TIM_Channel_4,TIM_ForcedAction_InActive);
TIM_SelectOCxM(TIM3,TIM_Channel_1,TIM_ForcedAction_InActive);
TIM_SelectOCxM(TIM3,TIM_Channel_3,TIM_ForcedAction_InActive);
DMA_Cmd(DMA_CHAN, DISABLE);/* DMA1 Channel3 关闭 */
DMA_ClearITPendingBit(DMA1_IT_TC3); //清除中断标志
}
}
——————————
需要500关注,拜托点个关注,谢谢