Jump to content

    

STM32, ADC и DMA

Господа, настроил я в STM32F103C8 2 регулярных канала ADC и пустил данные через DMA

В результате от одного и того же источника напряжения получаю разные, сильно отличающиеся значения.

Где ошибка?

#define ADC1_DR_Address    ((uint32_t)0x4001244C)    //ADC1µÄÊý¾Ý¼Ä´æÆ÷µØÖ·

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
vu16 ADCConvertedValue[2];

uint8_t AsciiBuff[5];
/* Private function prototypes -----------------------------------------------*/
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;

......................

void adc_Init()
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // ʹÄÜ MDA ÖØÒª£¡£¡£¡
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);// ʹÄÜ ADC1 ÖØÒª£¡£¡£¡

    /*DMA1 channel1 configuration ----------------------------------------------*/
      DMA_DeInit(DMA1_Channel1);               //½«DMAµÄͨµÀ1¼Ä´æÆ÷ÖØÉèΪȱʡֵ
      DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;      //¶¨ÒåDMAÍâÉè»ùµØַΪADC1
      DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue; //¶¨ÒåDMAÄÚ´æ»ùµØÖ·
      DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;      //ÍâÉè×÷ΪÊý¾Ý´«ÊäµÄÀ´Ô´
      DMA_InitStructure.DMA_BufferSize = 2;      //¶¨ÒåÖ¸¶¨DMAͨµÀµÄDMA»º´æµÄ´óС
      DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //ÍâÉèµØÖ·¼Ä´æÆ÷²»±ä
      DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;        //ÄÚ´æµØÖ·¼Ä´æÆ÷²»±ä
      DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;    //Êý¾Ý¿í¶ÈΪ16λ
      DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;    //Êý¾Ý¿í¶ÈΪ16λ
      DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;      //¹¤×÷ÔÚÑ­»·»º´æģʽ
      DMA_InitStructure.DMA_Priority = DMA_Priority_High;    //DMAͨµÀ1ÓµÓиßÓÅÏȼ¶
      DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;    //DMAͨµÀ1ûÓÐÉèÖÃΪÄÚ´æµ½ÄÚ´æ´«Êä
      DMA_Init(DMA1_Channel1, &DMA_InitStructure);     
  
      /* Enable DMA1 channel1 */
      DMA_Cmd(DMA1_Channel1, ENABLE);             
     
      /* ADC1 configuration ------------------------------------------------------*/
      ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;     //¶ÀÁ¢¹¤×÷ģʽ
      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(ADC1, &ADC_InitStructure);

      /* ADC1 regular channel_8,configuration */ 
      ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5); //ת»»Ê±¼äΪ17.1US
        ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_55Cycles5); //ת»»Ê±¼äΪ17.1US

      /* Enable ADC1 DMA */
      ADC_DMACmd(ADC1, ENABLE);
  
      /* Enable ADC1 */
      ADC_Cmd(ADC1, ENABLE);

      /* Enable ADC1 reset calibaration register */   
      ADC_ResetCalibration(ADC1);

      /* Check the end of ADC1 reset calibration register */
      while(ADC_GetResetCalibrationStatus(ADC1));

      /* Start ADC1 calibaration */
      ADC_StartCalibration(ADC1);

      /* Check the end of ADC1 calibration */
      while(ADC_GetCalibrationStatus(ADC1));
     
      /* Start ADC1 Software Conversion */ 
      ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

А дальше добавляю ADCConvertedValue в окно watch отладчика и мониторю. В результате разные данные на канала 8 и 9. Добавлю - в случае нулевого напряжение - данные правильные.

ГДе косяк?

И еще вопрос - код не мой, но везде, где я натыкался на подобный код, - DMA_MemoryBaseAddr 32 битный, а переменная ADCConvertedValue - 16-ти битная. Почему так?

Edited by Salamander

Share this post


Link to post
Share on other sites

Так может проблема не в коде а в наводках на канал ADC и потому ваши показания прыгают. Попробуйте перемычку на vref+ Показания стабилизируются? На нуле у вас все стабильно как я понимаю.

 

16ти битная переменная потому что результат 12ти битного АЦП нет смысла хранить в 32бит переменной. А base addr наверно от того что DMA работает только с выровненными данными. DMA ориентирован на работу с большими массивами данных оптом, поэтому никого не волнует что вы теряете место впустую - лес рубят, щепки летят:)

Share this post


Link to post
Share on other sites
И еще вопрос - код не мой, но везде, где я натыкался на подобный код, - DMA_MemoryBaseAddr 32 битный, а переменная ADCConvertedValue - 16-ти битная. Почему так?

потому что DMA_MemoryBaseAddr это абсолютный адрес в памяти(а память в STM32 может адресовать до 4Гб, отсюда 32 разряда), а ADCConvertedValue - это переменная которая располагается по этому адресу и содержит максимум 12-тиразрядное значение .

Share this post


Link to post
Share on other sites

Попробуйте настроить DMA так, чтобы он опрашивал не в циклическом режиме и посмотрите на результаты, т.е. Время от времени его запускайте его таймером например и если все в порядке значит, скорей всего АЦП не успевает выдавать верные результаты.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this