為了熟悉定時器定時器和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注入通道):
程序驗證正常。