定时器同步+触发三ADC采样+输出6路PWM波
为了熟悉定时器定时器和ADC
用STM32F407DIS做了一个简单的工程:
通过高级定时器TIM1溢出更新时间作为触发输出信号(TRGO),触发TIM8开始计数;
同时TIM1的通道1、2、3以及分别的互补通道输出6路PWM波用于控制三相电机;
TIM1的通道4用于触发ADC1的注入通道;
TIM8的通道1用于触发三个ADC的的规则通道;
TIM8的通道2用于触发ADC2的注入通道;
最后采样结果通过DMA传输到数组内保存起来;
为此,绘制了程序框图:
由框图来看工程更加清晰,更便于理解;
接下来配置工程,实现该任务:
首先配置定时器:
1 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 2 TIM_OCInitTypeDef TIM_OCInitStructure;3 TIM_BDTRInitTypeDef TIM_BDTRInitStructure; 4 GPIO_InitTypeDef GPIO_InitStructure;
开启时钟以及基础设置
1 // TIM1 clock enable 2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 3 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOE, ENABLE); 4 5 // Time Base configuration 6 TIM_TimeBaseStructure.TIM_Prescaler = 0; //时钟频率除数的预分频值 7 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 8 TIM_TimeBaseStructure.TIM_Period = 4200; //ARR 9 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分割 10 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; 11 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
通道设置
1 // Channel 1, 2 and 3 Configuration in PWM mode 2 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 3 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 4 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; 5 TIM_OCInitStructure.TIM_Pulse = TIM1->ARR / 2; //待装入捕获比较寄存器的值 5000 6 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出比较极性 高 7 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //互补输出极性 高 8 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; //空闲状态期间输出比较引脚状态 9 TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; 10 11 TIM_OC1Init(TIM1, &TIM_OCInitStructure); 12 TIM_OC2Init(TIM1, &TIM_OCInitStructure); 13 TIM_OC3Init(TIM1, &TIM_OCInitStructure); 14 TIM_OC4Init(TIM1, &TIM_OCInitStructure); 15 16 TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); 17 TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); 18 TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); 19 TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
死区设置
1 TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; 2 TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; 3 TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF; 4 TIM_BDTRInitStructure.TIM_DeadTime = 60; // 60个周期时间 5 TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable; 6 TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; 7 TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable; 8 9 TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
输出六路PWM波通道映射
1 /* GPIOA Configuration: TIM1 CH1 (PA8) 、 TIM1 CH1N (PA7) 、TIM1 CH3 (PA10) */ 2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_7 | GPIO_Pin_10 ; 3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 4 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 5 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 6 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; 7 GPIO_Init(GPIOA, &GPIO_InitStructure); 8 9 /* GPIOB Configuration: TIM1 CH2N (PB14) and TIM1 CH3N (PB15) */ 10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15; 11 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 12 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 13 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 14 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; 15 GPIO_Init(GPIOB, &GPIO_InitStructure); 16 17 /* GPIOB Configuration: TIM1 CH2 (PE11) and TIM1 CH3 (PE13) */ 18 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_11 | GPIO_Pin_14; 19 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 20 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 21 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 22 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; 23 GPIO_Init(GPIOE, &GPIO_InitStructure); 24 25 /* Connect TIM1 pins to AF */ 26 GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1); 27 GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM1); 28 GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_TIM1); 29 GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_TIM1); 30 GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_TIM1); 31 GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_TIM1); 32 GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_TIM1);
选择主从模式,TIM1为主选择更新时间作为触发输出
1 TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update); //选择更新事件作为触发输出(TRGO) 2 TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
对相关配置进行使能
1 TIM_CCPreloadControl(TIM1, ENABLE); 2 TIM_ARRPreloadConfig(TIM1, ENABLE); 3 4 TIM_ClearFlag(TIM1,TIM_FLAG_Update); 5 6 TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); 7 TIM_ITConfig(TIM1, TIM_IT_CC4, ENABLE); 8 9 TIM_CCxCmd(TIM1, TIM_Channel_4, TIM_CCx_Enable); 10 11 TIM_Cmd(TIM1, ENABLE); 12 13 // Main Output Enable 14 TIM_CtrlPWMOutputs(TIM1, ENABLE); //设置TIM1 的PWM输出使能
定时器8同样的配置过程
1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); 2 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); 3 4 TIM_TimeBaseStructure.TIM_Prescaler = 0; 5 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 6 TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //65535 7 TIM_TimeBaseStructure.TIM_ClockDivision = 0; 8 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; 9 TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); 10 11 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 12 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 13 TIM_OCInitStructure.TIM_Pulse = 500; 14 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 15 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; 16 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; 17 TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; 18 TIM_OC1Init(TIM8, &TIM_OCInitStructure); 19 TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable); 20 TIM_OC2Init(TIM8, &TIM_OCInitStructure); 21 TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable); 22 23 TIM_ARRPreloadConfig(TIM8, ENABLE); 24 TIM_CCPreloadControl(TIM8, ENABLE); 25 26 // PWM outputs have to be enabled in order to trigger ADC on CCx 27 TIM_CtrlPWMOutputs(TIM8, ENABLE); 28 29 TIM_SelectInputTrigger(TIM8, TIM_TS_ITR0); //选择输入触发源 ITR0 30 TIM_SelectSlaveMode(TIM8, TIM_SlaveMode_Reset); //计数器从模式选择 所选的触发信号上升沿重新初始化 31 32 // TIM_ITRxExternalClockConfig(TIM8, TIM_TS_ITR0); //选择ITR0为触发源提供时钟 33 34 TIM_CCxCmd(TIM8, TIM_Channel_1, TIM_CCx_Enable); 35 TIM_CCxCmd(TIM8, TIM_Channel_2, TIM_CCx_Enable); 36 37 TIM_ITConfig(TIM8, TIM_IT_CC1, ENABLE); 38 TIM_ITConfig(TIM8, TIM_IT_CC2, ENABLE); 39 40 TIM_ClearFlag(TIM8,TIM_FLAG_Update); 41 TIM_GenerateEvent(TIM8, TIM_EventSource_Trigger); 42 43 TIM_Cmd(TIM8, ENABLE); 44 }
如此计算可知:
查阅手册可知:
TIM1为主,TIM8为从,内部是通过ITR0连接的,所以在上面的配置过程中,TIM8的触发源要配置为ITR0;
接下来配置ADC
ADC要配置为三重模式
不开启连续转换
ADC1选择外部触发,但ADC2/3必须配置为软件触发
1 ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult; //adc三重模式 2 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; 3 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; 4 ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 5 ADC_CommonInit(&ADC_CommonInitStructure); 6 7 // Channel-specific settings 8 ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //ADC分辨率双模式 12位精度 9 ADC_InitStructure.ADC_ScanConvMode = ENABLE; //扫描模式 10 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 11 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Falling; //选择外部触发方式 下降沿触发 12 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T8_CC1; //选择TIM8_CC1触发规则组开始转换的外部事件 13 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对齐 14 ADC_InitStructure.ADC_NbrOfConversion = 4; //指定使用规则通道组完成转换的次数 采样通道数 15 16 ADC_Init(ADC1, &ADC_InitStructure); 17 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //不使用外部触发 (多ADC模式中,外部事件触发必须仅触发主ADC,从ADC设置为软件触发) 18 ADC_InitStructure.ADC_ExternalTrigConv = 0; 19 ADC_Init(ADC2, &ADC_InitStructure); 20 ADC_Init(ADC3, &ADC_InitStructure); 21 22 // Enable DMA request after last transfer (Multi-ADC mode) 多ADC模式下 使能 源数据变化时开启DMA传输 23 ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); 24 25 // Injected channels for current measurement at end of cycle 26 ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T1_CC4); 27 ADC_ExternalTrigInjectedConvConfig(ADC2, ADC_ExternalTrigInjecConv_T8_CC2); 28 ADC_ExternalTrigInjectedConvEdgeConfig(ADC1, ADC_ExternalTrigInjecConvEdge_Falling); 29 ADC_ExternalTrigInjectedConvEdgeConfig(ADC2, ADC_ExternalTrigInjecConvEdge_Falling); 30 ADC_InjectedSequencerLengthConfig(ADC1, 2); //设置注入通道长度 1-4 31 ADC_InjectedSequencerLengthConfig(ADC2, 2); 32 33 ADC_Channels(); 34 35 // Interrupt 36 ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE); //使能ADC的JEOC中断源 注入转换中断屏蔽结束 37 38 // ADC_AutoInjectedConvCmd(ADC1, ENABLE); 39 // ADC_AutoInjectedConvCmd(ADC2, ENABLE); 40 41 ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T1_CC4); 42 ADC_ExternalTrigInjectedConvConfig(ADC2, ADC_ExternalTrigInjecConv_T8_CC2); 43 44 //Enable ADC_DMA 45 ADC_DMACmd(ADC1, ENABLE); 46 ADC_DMACmd(ADC2, ENABLE); 47 ADC_DMACmd(ADC3, ENABLE); 48 49 // Enable ADC1 50 ADC_Cmd(ADC1, ENABLE); 51 52 // Enable ADC2 53 ADC_Cmd(ADC2, ENABLE); 54 55 // Enable ADC3 56 ADC_Cmd(ADC3, ENABLE);
再配置一下ADC的通道
1 ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_15Cycles); //(15+12)/42 = 0.6429 us 总转换时间 2 ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 2, ADC_SampleTime_15Cycles); 3 ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, 3, ADC_SampleTime_15Cycles); 4 ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_15Cycles); 5 6 // ADC2 regular channels 7 ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_15Cycles); 8 ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 2, ADC_SampleTime_15Cycles); 9 ADC_RegularChannelConfig(ADC2, ADC_Channel_6, 3, ADC_SampleTime_15Cycles); 10 ADC_RegularChannelConfig(ADC2, ADC_Channel_5, 4, ADC_SampleTime_15Cycles); 11 12 // ADC3 regular channels 13 ADC_RegularChannelConfig(ADC3, ADC_Channel_2, 1, ADC_SampleTime_15Cycles); 14 ADC_RegularChannelConfig(ADC3, ADC_Channel_3, 2, ADC_SampleTime_15Cycles); 15 ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 3, ADC_SampleTime_15Cycles); 16 ADC_RegularChannelConfig(ADC3, ADC_Channel_3, 4, ADC_SampleTime_15Cycles); 17 18 // Injected channels 19 ADC_InjectedChannelConfig(ADC1, ADC_Channel_9, 1, ADC_SampleTime_15Cycles); 20 ADC_InjectedChannelConfig(ADC1, ADC_Channel_8, 2, ADC_SampleTime_15Cycles); 21 ADC_InjectedChannelConfig(ADC2, ADC_Channel_8, 1, ADC_SampleTime_15Cycles); 22 ADC_InjectedChannelConfig(ADC2, ADC_Channel_9, 2, ADC_SampleTime_15Cycles);
最后配置DMA
1 DMA_InitStructure.DMA_Channel = DMA_Channel_0; //通道0 2 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_Value; 3 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->CDR; 4 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 5 DMA_InitStructure.DMA_BufferSize = 12; //指定DMA通道的DMA缓存的大小 6 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 7 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 8 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度 9 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 10 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环缓存模式 11 DMA_InitStructure.DMA_Priority = DMA_Priority_High; 12 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //关闭FIFO模式 13 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; //FIFO阈值级别 14 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 15 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 16 DMA_Init(DMA2_Stream4, &DMA_InitStructure); 17 18 // DMA2_Stream0 enable 19 DMA_Cmd(DMA2_Stream4, ENABLE); 20 21 // Enable transfer complete interrupt 22 DMA_ITConfig(DMA2_Stream4, DMA_IT_TC, ENABLE);
如此,工程便配置完成了
通过示波器验证:
定时器1的通道1、2、3和他们的互补通道(6路PWM波):
TIM1通道4的波形(ADC1注入通道) 和 TIM8输出的波形(ADC规则通道、ADC2注入通道):
程序验证正常。