zoukankan      html  css  js  c++  java
  • 定时器同步+触发三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注入通道):

    程序验证正常。

  • 相关阅读:
    log4net
    配置文件序列化到文件中
    log日志
    Quartz任务管理
    tuple
    mvc视图中使用JavaScriptSerializer
    windows服务安装
    23种设计模式之普通工厂模式代码实例
    23种设计模式之单例模式代码实例
    putty文件传输
  • 原文地址:https://www.cnblogs.com/isAndyWu/p/9593630.html
Copyright © 2011-2022 走看看