Перейти к содержанию
    

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-ти битная. Почему так?

Изменено пользователем Salamander

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...