打印

STM32F103RBT6: ADC + DMA + TIM

[复制链接]
5568|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Tenant_2013|  楼主 | 2013-4-22 22:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 Tenant_2013 于 2013-4-22 22:42 编辑

这是一个测试程序,完成后将在毕业设计的组内共享,各人添加、修改,完善成自己的程序,所以3路采样只用了2路。恭请各位大神帮忙看看问题。

型号:STM32F103RBT6;功能:ADC采样3路信号,通过DMA送入Memory;经过main函数的计算,再通过DMA送入TIM的CCR寄存器,产生2路PWM。

调整ADC输入,通过WatchWindow观察到ADC采样跟随变化,没有问题。

但DMA没有将TIM1_CCR1_Address (0x40012C34)和TIM1_CCR2_Address  (0x40012C38)更新,它们始终保持以初始占空比(75%、37.5%)输出PWM。

main.c如下:

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"


/* Private define ------------------------------------------------------------*/
/* Average Length */
#define N 10

/* Registers Address */
/* From "Memory Map" in "STM32F103x8 STM32F103xB Datasheet" & "TIM Registers" in "RM0008 Reference Manual";
        Registers Address = Sector Address + Offset Address */
/* ADC1: DR (Regular Data Register) Address */
#define ADC1_DR_Address                                ((uint32_t)0x4001244C)   /* 0x 4001 2400 + 0x 4C */
/* TIM1: CCR1, CCR2 (Conpare/Capture Register) Address */
#define TIM1_CCR1_Address                        ((uint32_t)0x40012C34)        /* 0x 4001 2C00 + 0x 34 */
#define TIM1_CCR2_Address                        ((uint32_t)0x40012C38)        /* 0x 4001 2C00 + 0x 38 */


/* Private variables ---------------------------------------------------------*/
uint16_t TimerPeriod;        /* PWM Period */
volatile uint16_t i, u, t;       /* Current, Voltage, Temperature */

/* Define Buffers */
uint16_t ADC_ConvertedValueTab[4*N];
uint16_t TIM1_CH1_PulseWidth;
uint16_t TIM1_CH2_PulseWidth;


/* Private function prototypes -----------------------------------------------*/
/* Clock Function */
void RCC_Configuration(void);
/* Peripheral Functions */
void GPIO_Configuration(void);
void DMA_Configuration(void);
void ADC_Configuration(void);
void TIM_Configuration(void);
/* Average Function */
uint16_t Average(char c);


/* Private functions ---------------------------------------------------------*/
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
        */
        
  /*
        C/C++ / Define:                                        USE_STDPERIPH_DRIVER,STM32F10X_MD
        startup_stm32f10x_md.s:        SystemInit()
        system_stm32f10x.c:                        #define SYSCLK_FREQ_72MHz  72000000
                                                                                                           
        PLLMUL:                PLLCLK = 8MHz * 9 = 72 MHz
        SW:                       SYSCLK = PLLCLK         = 72 MHz
        AHB Prescaler:        HCLK         = SYSCLK = 72 MHz
        APB2 Prescaler:      PCLK2 = HCLK/1 = 72 MHz
        APB1 Prescaler:      PCLK1 = HCLK/2 = 36 MHz
                                                                                                        }
        */     

  /* System Clocks Configuration */
  RCC_Configuration();

  /* GPIO Configuration */
  GPIO_Configuration();

  /* DMA Configuration */
  DMA_Configuration();

  /* ADC configuration */
  ADC_Configuration();

  /* TIM Configuration */
  TIM_Configuration();

  while (1)
  {
    i = Average('i');                               /* Current Sampling*/
                u = Average('u');                /* Voltage Sampling */
                t = Average('t');                 /* Temperature Sampling */
               
                TIM1_CH1_PulseWidth = i;
                TIM1_CH2_PulseWidth = t;
  }
}


void RCC_Configuration(void)
{
/* Set ADC Prescaler, ADCCLK = PCLK2/6 = 12 MHz */
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
        
/* Enable DMA1 clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        
/* Enable ADC1, ADC2, TIM1, GPIOA and GPIOC clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
}


void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;                                          /* Define GPIO_InitStructure */

  /* GPIOA Configuration */
  /* PA.08 (AF,PP) - TIM1_CH1; PA.09 (AF,PP) - TIM1_CH2 */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;         /* Select GPIO Pins */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;               /* Alternate Function & Push-Pull*/
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;            /* GPIO Speed = 50MHz */
  GPIO_Init(GPIOA, &GPIO_InitStructure);                                     /* Configure GPIOA */
        
  /* GPIOC Configuration */
  /* PC.02 (AIN) - ADC_12; PC.03 (AIN) - ADC_13; PC.04 (AIN) - ADC_14 */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;                /* Select GPIO Pins */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                                                /* Analog Input */
  GPIO_Init(GPIOC, &GPIO_InitStructure);                                                                 /* Configure GPIOC */
}


void DMA_Configuration(void)
{
  DMA_InitTypeDef DMA_InitStructure;                              /* Define DMA_InitStructure */

        
/* DMA1 channel1 Configuration: DMA1_Channel1 - ADC1_Channel12 & ADC1_Channel13 --------*/
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;                               /* Peripheral Base Address */
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValueTab;                        /* Memory Base Address */
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                                             /* From Peripheral To Memory */
  DMA_InitStructure.DMA_BufferSize = N*2;                                                                                    /* Buffer Size: 2N */
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                                            /* Peripheral Increase: Disable */
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                                 /* Memory Increase: Enable */
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;                             /* Peripheral Data Size: 32 bits */
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;                                 /* Memory Data Size: 32 bits */
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                                                 /* Circular */
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                                                /* Priority: High */
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                                                    /* Memory To Memory: Disable */
  /* Initialize DMA1_Channel1 */
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  /* Enable DMA1_Channel1 */
  DMA_Cmd(DMA1_Channel1, ENABLE);

        
  /* DMA1 Channel2 Configuration: DMA1_Channel2 - TIM1_Channel1) */
  DMA_DeInit(DMA1_Channel2);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM1_CCR1_Address;                           /* Peripheral Base Address */
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&TIM1_CH1_PulseWidth;                        /* Memory Base Address */
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                                           /* From Memory To Peripheral */
  DMA_InitStructure.DMA_BufferSize = 1;                                                                                      /* Memory Buffer Size: 1 */
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                                          /* Peripheral Increase: Disable */
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                               /* Memory Increase: Disable */
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;                     /* Peripheral Data Size: 16 bits */
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                         /* Memory Data Size: 16 bits */
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                                               /* Circular */
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                                                /* Priority: High */
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                                                  /* Memory To Memory: Disable */
  /* Initialize DMA1_Channel2 */
  DMA_Init(DMA1_Channel2, &DMA_InitStructure);
  /* Enable DMA1_Channel2 */
  DMA_Cmd(DMA1_Channel2, ENABLE);


  /* DMA1 Channel3 Configuration: DMA1_Channel3 - TIM1_Channel2) */
  DMA_DeInit(DMA1_Channel3);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM1_CCR2_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&TIM1_CH2_PulseWidth;        
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize = 1;        
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;        
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  /* DMA1 Channel3 Initialization */
  DMA_Init(DMA1_Channel3, &DMA_InitStructure);
  /* DMA1 Channel3 enable */
  DMA_Cmd(DMA1_Channel3, ENABLE);
}


void ADC_Configuration(void)
{
  ADC_InitTypeDef ADC_InitStructure;

  /* ADC1 Configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;                                   /* ADC1 & ADC2: dual */
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;                                         /* Scan */
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                               /* Continuous */
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;     /* No External Trigger */
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                             /* Right Alignment */
  ADC_InitStructure.ADC_NbrOfChannel = 2;                                                     /* Number of Channels: 2 */
  ADC_Init(ADC1, &ADC_InitStructure);                                                             /* Configure ADC1 */
  /* ADC1 regular channels configuration; ADC1: ADC_CH12, Sequence: 1; Sample Time: 28.5 Cycles  */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_28Cycles5);
  /* ADC1 regular channels configuration; ADC1: ADC_CH13, Sequence: 2; Sample Time: 28.5 Cycles  */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 2, ADC_SampleTime_28Cycles5);
  /* Enable The DMA Function of ADC1 */
  ADC_DMACmd(ADC1, ENABLE);

  /* ADC2 Configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 2;
  ADC_Init(ADC2, &ADC_InitStructure);
  /* ADC2 regular channels configuration; ADC2: ADC_CH14, Sequence: 1; Sample Time: 28.5 Cycles */
  ADC_RegularChannelConfig(ADC2, ADC_Channel_14, 1, ADC_SampleTime_28Cycles5);
        /* ADC2 regular channels configuration; ADC2: ADC_CH14, Sequence: 2; Sample Time: 28.5 Cycles */
  ADC_RegularChannelConfig(ADC2, ADC_Channel_14, 2, ADC_SampleTime_28Cycles5);


        /* ADC1: Enable & Calibration */
  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  /* Enable ADC1 reset calibration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));
  /* Start ADC1 calibration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));


        /* ADC2: Enable & Calibration */
  /* Enable ADC2 */
  ADC_Cmd(ADC2, ENABLE);
  /* Enable ADC2 reset calibration register */   
  ADC_ResetCalibration(ADC2);
  /* Check the end of ADC2 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC2));
  /* Start ADC2 calibration */
  ADC_StartCalibration(ADC2);
  /* Check the end of ADC2 calibration */
  while(ADC_GetCalibrationStatus(ADC2));


  /* Start ADC1, ADC2 */
  /* Start ADC1 Software Conversion */
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
  /* Start ADC2 Software Conversion */
  ADC_SoftwareStartConvCmd(ADC2, ENABLE);
}


void TIM_Configuration(void)
{
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
   TIM_OCInitTypeDef  TIM_OCInitStructure;

  /* TIM1 Configuration ---------------------------------------------------
   Generate 2 PWM signals with 2 different duty cycles:
   TIM1CLK = SystemCoreClock, Prescaler = 0, TIM1 counter clock = SystemCoreClock
   - Prescaler = (TIM1CLK / TIM1 counter clock) - 1 = 0.

   SystemCoreClock is set to 72 MHz for Medium-density device.

   The TIM1 is running at 50 KHz:
   TIM1 Frequency = TIM1 counter clock / (ARR + 1) = 72 MHz / 1440 = 50 KHz

   The objective is to generate 2 PWM signal at 50 KHz:
     - TIM1_Period = (SystemCoreClock / 50000) - 1
   The channel 1 duty cycle is set to 75%
   The channel 2 duty cycle is set to 37.5%
   The Timer pulse is calculated as follows:
     - ChannelxPulse = DutyCycle * (TIM1_Period - 1) / 100
  ----------------------------------------------------------------------- */
        
  /* Compute ARR value (PWM Wave Pulse Width) to generate signal frequency at 50000 KHz */
  TimerPeriod = (SystemCoreClock / 50000 ) - 1;
  /* Initialize CCR1 value (Channel1 Pulse Width) at 75% duty cycle for channel 1 */
  TIM1_CH1_PulseWidth = (uint16_t) (((uint32_t) 75 * (TimerPeriod - 1)) / 100);
  /* Initialize CCR2 value (Channel2 Pulse Width) at 37.5% duty cycle for channel 2 */
  TIM1_CH2_PulseWidth = (uint16_t) (((uint32_t) 375 * (TimerPeriod - 1)) / 1000);

  /* Time Base configuration (Timer Counting Configuration) */
  TIM_TimeBaseStructure.TIM_Prescaler = 0;                                                /* Prescaler = 0 */
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        /* Count Up */
  TIM_TimeBaseStructure.TIM_Period = TimerPeriod;                                   /* ARR */
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;                                         /* Clock Division = 0 */
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;                                 /* UEV Configuration: Update st every Overflow */

  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);                                                        /* Configure TIM1 */

  /* Channel 1 and 2 Configuration in PWM mode (Channel Output Configuration) */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                                       /* PWM1 Mode (CNT < CCRx, High Level Output)*/
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;                           /* Positive Channel: Enable */
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;                      /* Negative Channel: Disable */
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;                                    /* Positive Channel Output: Low */
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;                                /* Negative Channel Output: High */
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;                              /* Positive Channel Idle Band: Reset */
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;                            /* Negative Channel Idle Band: Reset */

  TIM_OCInitStructure.TIM_Pulse = TIM1_CH1_PulseWidth;                /* Channel1 Pulse Width */
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);                                      /* Configure TIM1_CH1 */

  TIM_OCInitStructure.TIM_Pulse = TIM1_CH2_PulseWidth;                /* Channel2 Pulse Width */
  TIM_OC2Init(TIM1, &TIM_OCInitStructure);                                      /* Configure TIM1_CH2 */


  /* Enable TIM1 Update DMA Request */
  TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);

  /* Enable TIM1 Counter */
  TIM_Cmd(TIM1, ENABLE);

  /* Enable TIM1 Main Output */
  TIM_CtrlPWMOutputs(TIM1, ENABLE);
}


/* Average: remove max, min; calculate the average. */
uint16_t Average(char c)
{
  uint16_t j, max, min, sum, average, inc, num;
        __IO uint16_t *a = ADC_ConvertedValueTab;
        
        switch (c)
        {
        case 'i': num=N; inc=4; break;
        case 'u': num=N; inc=4; a+=2; break;
        case 't': num=N*2; inc=2; a+=1; break;
        }

  max = *a;
  min = *a;
  sum = 0;

  for(j = 0; j < num; a+= inc, j++)
  {
          if(*a > max) max = *a;
                if(*a < min) min = *a;
                sum+= *a;
  }
        average = (sum-max-min)/(num-2);

  return average;
}


/************************END OF FILE***********************/


先谢谢各路大神!
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

7

帖子

0

粉丝