定時器同步+觸發三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注入通道):

程序驗證正常。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM