定时器同步+触发三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注入通道):

程序验证正常。

posted @ 2018-09-05 17:59  isAndyWu  阅读(1262)  评论(0编辑  收藏  举报