Работаем с АЦП stm32f4 discovery - мерим температуру

В отладочной плате STM32F4 discovery микроконтроллер оснащенный 12битным АЦП со встроенным датчиком температуры и напряжения.
В этой статье займёмся датчиком температуры, заодно рассмотрим принципы работы с АЦП в stm32 spl (стандартной периферийной библиотеке).
Напишем приложение, которое зажигает 4 диода в зависимости от уровня получаемого с АЦП1.

Необходимые инклуды:

#include <stm32f4xx.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_adc.h>

Инициализируем диоды:

void leds_init() {
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

      GPIO_InitTypeDef gpio;
      GPIO_StructInit(&gpio);
      gpio.GPIO_OType = GPIO_OType_PP;
      gpio.GPIO_Mode = GPIO_Mode_OUT;
      gpio.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

      GPIO_Init(GPIOD, &gpio);
}

Теперь настроим ADC1 (он же АЦП1) :

void adc_init() {
       ADC_InitTypeDef ADC_InitStructure;
       ADC_StructInit(&ADC_InitStructure);

       ADC_CommonInitTypeDef adc_init;
       ADC_CommonStructInit(&adc_init);
       /* разрешаем тактирование AЦП1 */
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
       /* сбрасываем настройки АЦП */
       ADC_DeInit();

       /* АЦП1 и АЦП2 работают независимо */
       adc_init.ADC_Mode = ADC_Mode_Independent;
       adc_init.ADC_Prescaler = ADC_Prescaler_Div2;
       /* выключаем scan conversion */
       ADC_InitStructure.ADC_ScanConvMode = DISABLE;
       /* Не делать длительные преобразования */
       ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

       /* Начинать преобразование программно, а не по срабатыванию триггера */
       ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
       /* 12 битное преобразование. результат в 12 младших разрядах результата */
       ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

       /* инициализация */
       ADC_CommonInit(&adc_init);

       ADC_Init(ADC1, &ADC_InitStructure);
       /* Включаем АЦП1 */
       ADC_Cmd(ADC1, ENABLE);
}

Функция для считывания данных с АЦП:

u16 readADC1(u8 channel){
   ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_3Cycles);
   // начинаем работу
   ADC_SoftwareStartConv(ADC1);
   // ждём пока преобразуется напряжение в код
   while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
   // возвращаем результат
   return ADC_GetConversionValue(ADC1);
}

Эта функция принимает в качестве параметра номер канала АЦП. Для использования встроенного датчика температуры необходимо использовать 16 канал.
Задержка:

void Delay(unsigned int Val){
   for( ; Val != 0; Val--)
      __NOP();
}

Теперь функция main :

int main(){
     leds_init();  // инициализируем диоды
     adc_init();  // ацп

     ADC_TempSensorVrefintCmd(ENABLE);  // разрешаем преобразование
     do {
         unsigned int Temperature = readADC1(16);  /// читаем данные с датчика АЦП1
         GPIO_ResetBits(GPIOD,GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);  // сбрасываем состояние диодов
         if (Temperature > 50) {  /// если больше 20 зажигаем первый диод
             GPIO_SetBits(GPIOD, GPIO_Pin_12);
         }
         if (Temperature > 55) { // если больше 30 - второй. и т.д.
             GPIO_SetBits(GPIOD, GPIO_Pin_13);
         }
         if (Temperature > 60) {
             GPIO_SetBits(GPIOD, GPIO_Pin_14);
         }
         if (Temperature > 70) {
             GPIO_SetBits(GPIOD, GPIO_Pin_15);
         }
         Delay(5000000);  // задержка
   }while (1);
}

Встроенный датчик врядли поможет вам получить истинные значения температуры. Он предназначен для отслеживания её изменений.
Приведенная программа зажигает 3 диода при ~25 за окном. 2 после засовывания в холодильник.

Скачать проект.

Просмотров:   24182

Комментарии

чт, 11/22/2012 - 14:11

Все как у вас, но температура все время 1045 - 1048... в чем причина не пойму

пт, 07/24/2015 - 05:03
Comrad

Temp *= 3300;
Temp /= 0xfff; //Reading in mV
Temp /= 1000.0; //Reading in Volts
Temp -= 0.760; // Subtract the reference voltage at 25°C
Temp /= .0025; // Divide by slope 2.5mV
Temp += 25.0; // Add the 25°C
страница 414 даташита

чт, 11/22/2012 - 14:11

Внутренний сенсор температуры предназначен для измерения изменения температуры!

чт, 11/22/2012 - 14:11

все отлично меряет - курите DS

 

пт, 12/28/2012 - 12:48
genezis

Я прогнал прогу, у меня она не работает в цикле. Проводит измерения за один цикл и по-видимому виснет.

Как заставить ее проводить измерения в цикле постоянно?

чт, 01/03/2013 - 19:55

На каком именно моменте виснет?

чт, 01/10/2013 - 20:46
Гость

Наверно там же где и у меня, на считывании температуры. Не может завершиться преобразование напряжения в код.

пт, 02/08/2013 - 16:02
roma1141

Виснет вот на этой части:
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
а точнее: stm32f4xx_adc.c

FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_GET_FLAG(ADC_FLAG));

/* Check the status of the specified ADC flag */
if ((ADCx->SR & ADC_FLAG) != (uint8_t)RESET)
{
/* ADC_FLAG is set */
bitstatus = SET;
}
else
{
/* ADC_FLAG is reset */
bitstatus = RESET;
}
/* Return the ADC_FLAG status */
return bitstatus;
}

только вот не пойму в чем причина?

пт, 02/08/2013 - 17:37
SVS

В ИАР работает, а в КЕЙЛ виснет на считывании температуры (причем и другой АЦП при запуске измерения).

ср, 10/30/2013 - 23:08
fse

Не проходит инициализация бита выравнивания. Автор пропустил ADC_StructInit(&ADC_InitStructure) в начале инита. Туда же ткните ADC_CommonStructInit(&adc_init).

чт, 10/31/2013 - 10:54

Спасибо, добавил в код.

ср, 01/29/2014 - 11:12
Антон

А у меня в uVision4 появляется ошибка error: #268: declaration may not appear after executable statement in block, указывающая на строчку ADC_CommonInitTypeDef adc_init;

Добавить комментарий

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.
CAPTCHA
Введи эти символы. Ато роботы одолели!