STM32F030F4P6 VREFINT 5510 Keil

Опубликовано stm32 - Птн, 04/24/2020 - 11:59

STM32F030F4P6 VREFINT 5510 Keil

Всем привет!

В этой статье хочу остановиться на таком вопросе как измерение напряжения питания микроконтроллера STM32F030F4P6 при его работе от батареек. Это не всегда нужно, но если есть желание использовать устройство круглый год - лучше заранее быть готовым к тому, что батарейка сядет тогда когда вы этого не ждете. В микроконтроллерах STM (и не только) заложено такое измерение на аппаратном уровне. Это обычное измерение аналогового сигнала, но без использования дополнительных ножек микроконтроллера. Удобно. Не надо дополнительных элементов - программно подключился, измерил, отключился.

Дальше немного рассуждений ..

Мы решили использовать внутреннюю схему измерения напряжения - как контроль за источником питания микроконтроллера.   

Остановимся на батарейном питании схемы. Режим работы микроконтроллера должен подбираться так, чтобы максимально продлить срок жизни элемента питания.  Чтобы это реализовать, будет необходимо использовать один из трех режимов экономии потребления предусмотренных в микроконтроллерах и в том числе у STM32F030F4P6 , а именно:

1. Режим   -  SLEEP

2.Режим  - STOP

3.Режим  -   STANDBY

В этой статье я не буду останавливать на этих режимах, но зачем я про них пишу тогда? Вот зачем .. когда мы подключаемся для измерения внутреннего напряжения мы включаем Аналого-цифровой преобразователь (он же АЦП).  А это один из тех потребителей тока который может разрядить батарейку (батарейки) питания устройства и быть одной !!! из причин неправильных показателей измерения напряжения.  

Как пример ..

Вы решили использовать питание от батарейки типа  CR2032 и измеряете напряжение питания 1 раз в мин ... Что произойдет ... При подключении канала для измерения напряжения АЦП у STM32F030F4P6 будет потребление ~ 1.3 mА. Если учесть, что нормальным потребление для батарейки CR2032 является ток > 0,03 mA (при емкости CR2032 200-240 mA час )  то при токе 1.3 мА - будет реальное сокращение срока службы устройства от одного элемента...  и самое главное - при подключении в режим измерения будет просаживаться напряжения до минимально уровня заряда  - что в свою очередь приведет к возможно !!! не верному измерению внутреннего напряжения.

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

Вернемся к основной статье.

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

RM0360  Reference manual STM32F030x4/x6/x8/xC and STM32F070x6/xB advanced ARM®-based 32-bit MCUs

На странице 182 видим, что АЦП мы можем использовать в следующих режимах 

rt_1

1 канал для внутреннего измерения и будем использовать  - Vrefint.

Смотрим дальше .... 

rt_2

Vrefint - подключается к каналу ADC_IN17.

Смотри дальше как его посчитать ...

rt_3

 

rt_4

Где

rt_5

 

Попробуем прочитать для этого ...

Создадим проект как описано в  статье  STM32F030F4P6 Keil Первый проект  или STM32F030F4P6 LCD5510 Keil  

Добавим в него следующие следующие 2 файла 

adc.h

****************************************************************************************************************

#ifndef ADC_H
#define ADC_H

#include "stm32f0xx.h" 

void adc_init(void);


#endif
*****************************************************************************************************************

adc.c 

 *****************************************************************************************************************

#include "adc.h"


void adc_init(void) // Инициализация 
{

  ADC_InitTypeDef     ADC_user;                   // создаем структуру для настройки АЦП
  GPIO_InitTypeDef    GPIO_ADC_user;    // создаем структуру для настройки порта

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);   // Включаем тактирование АЦП
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  // Включаем тактирование порта
  GPIO_ADC_user.GPIO_Pin =  ADC_Channel_Vrefint  ;         // Выбираем порт ADC_IN17 он в Keil под названием -ADC_Channel_Vrefint
  GPIO_ADC_user.GPIO_Mode = GPIO_Mode_AN;
  GPIO_ADC_user.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOA, &GPIO_ADC_user);
  
   ADC_DeInit(ADC1);
   ADC_StructInit(&ADC_user);
  // Конфигурируем АЦП
  ADC_user.ADC_Resolution = ADC_Resolution_12b;               
  ADC_user.ADC_ContinuousConvMode = ENABLE; 
  ADC_user.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_user.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_user.ADC_ScanDirection = ADC_ScanDirection_Upward;
  ADC_Init(ADC1, &ADC_user); 
  
  ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint  , ADC_SampleTime_239_5Cycles);
  ADC_GetCalibrationFactor(ADC1);
  ADC_Cmd(ADC1, ENABLE);     
  ADC_VrefintCmd(ENABLE);
    
  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)); 
   ADC_StartOfConversion(ADC1);    
  
    
}

После создания файлов и подключения их к проекту 

main.c 

Дополняем следующим содержимым

 #include "adc.h"  // подключим созданные файлы

#define VREFINT_CAL_ADDR 0x1FFFF7BA  // адрес где храниться калибровочные данные

uint16_t acd_raw;
float      v_adc;
float     v_ref;
float     v_bat;

char str1[15];

uint16_t vrefint_cal_adr

int main(void)
{    

while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET){};  // если АЦП готов то запускаем считывание

acd_raw = ADC_GetConversionValue(ADC1);                                       // получаем код АЦП
             
vrefint_cal_adr = *((uint16_t*)VREFINT_CAL_ADDR);                 // Читаем калибровочные данные
              
v_ref = 3.3 * vrefint_cal_adr/4095;                                                     // Рассчитываем опорное 
                
v_bat = (4095*v_ref)/acd_raw;                                                           //На  основание рассчитанного опорного напряжения рассчитываем Vbat 
                
 sprintf(str1,"%.2f",v_bat);                                                                  // Форматируем строку для вывода .. в моем случае на LCD 5110                                                        

}

Вот и вся программа считывания.

Дальше выбираем куда будем выводить информацию.

На видео я вывожу данные на LCD510  при этом входное напряжение я регулирую преобразователем напряжения.

Видео файл

    

На выходе имеем очень не плохие результаты.  Данные уверенно считываются до напряжения 2.1 вольт.

Конечно, в примере отображается простая схема получения значения напряжения питания.  Но она позволяет запустить АЦП и начать работать в нужном направлении!!!  

Ура!! Все получилось!

Если есть вопросы или необходим исходник проекта  из статьи - пишите по адресу stm32@stm32res.ru или Website feedback

 

 

Яндекс.Метрика