SMT32轻松输出带死区的4路PWM
带PWM宽度可调,死区时间可……
比较器输出改变死区时间,定时器的翻转周期改变PWM宽度。
1个通用定时器最多可以做到16路输出,不占用系统资源。
主要原理是使用翻转周期DMA通道改变端口输出状态,比较通道DMA关闭端口输出实现死区调节。
typedef struct
{uint32_t volatile Width[4]; //肪宽
uint32_t DeadZone; //死区
}Scan_Package;
Scan_Package PWM;
/*******************************
函数功能:定时器比较模式
********************************/
void TIM2_Compare (void)
{
// NVIC_InitTypeDef NVIC_InitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_Pulse = 17000; //翻转周期:1700个脉冲
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; //使能TIM2_CH3通道
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出为负逻辑
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Disable);
TIM_ForcedOC3Config(TIM2,TIM_ForcedAction_InActive);
// TIM_ITConfig(TIM2,TIM_IT_CC3,ENABLE); //比较中断
//
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
// /* Enable the TIMER15 Interrupt */
// NVIC_InitStructure.NVIC_IRQChannel= TIM15_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
// NVIC_Init(&NVIC_InitStructure);
}
/*******************************
函数功能:输出端口设置
********************************/
void Port_Out_init (GPIO_TypeDef* GPIOx,uint32_t GPIO_Pin_x)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOx , &GPIO_InitStructure);
}
void TIM2_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIMER_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
TIM_DeInit(TIM2);
TIMER_TimeBaseStructure.TIM_Prescaler= 0x05; //定时最大时间2.5ms
TIMER_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up;
TIMER_TimeBaseStructure.TIM_Period= 30000;
TIMER_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1;
TIMER_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM2,&TIMER_TimeBaseStructure);
Port_Out_init(GPIOA,GPIO_Pin_0);
Port_Out_init(GPIOA,GPIO_Pin_1);
Port_Out_init(GPIOA,GPIO_Pin_2);
Port_Out_init(GPIOA,GPIO_Pin_3);
/* Auto-reload preload enable */
TIM_ARRPreloadConfig(TIM2,ENABLE);
/* Clear the CH1 Interrupt flag an Enable the CH1 Interrupt Request */
TIM_ClearITPendingBit(TIM2,0xFFFF);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the TIMER2 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel= TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;//先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0; //从优先级0级
NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE);//允许更新中断和捕获中断
NVIC_DisableIRQ(TIM2_IRQn);
// TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE); //捕获中断
TIM_Cmd( TIM2, ENABLE );
}
/*******************************
函数功能:
********************************/
void DMA_DeInit_MITSUBISHI (void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel1); //TIM2_CC3
DMA_DeInit(DMA1_Channel2); //TIM2_UP
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOA->BSRR; //外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&PWM.Width[0]; //内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //dma传输方向单向 内存到外设
DMA_InitStructure.DMA_BufferSize = 4; //设置DMA在传输时缓冲区的长度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置DMA的外设递增模式,一个外设
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置DMA的内存递增模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //外设数据字长
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //内存数据字长
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //设置DMA的传输模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //设置DMA的优先级别
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //设置DMA的2个memory中的变量互相访问
DMA_Init(DMA1_Channel2,&DMA_InitStructure);
TIM_DMACmd(TIM2,TIM_DMA_Update,ENABLE);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOA->BSRR; //外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&PWM.DeadZone; //内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //dma传输方向单向 内存到外设
DMA_InitStructure.DMA_BufferSize = 1; //设置DMA在传输时缓冲区的长度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置DMA的外设递增模式,一个外设
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //设置DMA的内存递增模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //外设数据字长
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //内存数据字长
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //设置DMA的传输模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //设置DMA的优先级别
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //设置DMA的2个memory中的变量互相访问
DMA_Init(DMA1_Channel1,&DMA_InitStructure);
TIM_DMACmd(TIM2,TIM_DMA_CC3,ENABLE);
DMA_Cmd(DMA1_Channel1,ENABLE);
DMA_Cmd(DMA1_Channel2,ENABLE);
// DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE); //通道中断使能
// DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);
// DMA_ITConfig(DMA1_Channel3,DMA_IT_TC,ENABLE);
// DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
// NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);
// NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
// NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
void TIM2_APP_Config(void)
{
TIM2_Config();
DMA_DeInit_MITSUBISHI();
TIM2_Compare();
}