STM8L Компараторы: часть1 COMP1

Компараторы в микроконтроллерах серии STM8L рассмотрим на примере STM8L152C6T6, который установлен на плате STM8L-DISCOVERY.

Наш STM8L152C6T6 относится к классу medium. Для начала разберёмся с подключением первого компаратора COMP1. Для иллюстрации подключения компаратора из RM0031 возьмём рисунок из раздела Routing interface (RI) для medium:


Входной сигнал мы будем подавать на ножку PBO при помощи делителя напряжения.


На фото многооборотный потенциометр, но можно обойтись и обыкновенным. Дополнительный резистор R2 установлен, чтобы случайно не сжечь вход PB0, если он вдруг запрограммируется на выход. LCD индикатор аккуратно вынимаем и откладываем в сторону.


Компаратор COMP1 имеет один фиксированный пороговый уровень, V_ref = 1,202...1,242 Вольт. Это напряжение подается на инвертирующий вход компаратора. Точное значение V_ref конкретного камня измеряется на заводе при VDD = 3 V ±10 mV. Это значение можно прочитать по адресу 0x00 4910 и использовать в своей программе для повышения точности измерений. В IAR прочитать можно вот так:

//#include "iostm8l151c6.h"
#include <stdint.h>    // работа с uintx_t переменными
#include <stdio.h>    // работа с терминалом I/O

uint16_t D_ref_FACTORY;

void main( void )
{         
   D_ref_FACTORY = *((uint8_t*)0x4910); // читаем значение по адресу 0x4910 
   D_ref_FACTORY += 0x600;  // в старшем байте всегда 0x6‚ в младшем у меня 0x83 
   printf("D_ref_FACTORY = %d\n",D_ref_FACTORY); // опорное, замеренное на заводе
   
   //  3000mV           4095 единиц
   //  1,221V  D_ref_FACTORY единиц
    
   // получаем опорное в mV для конкретного камня
   D_ref_FACTORY = (uint32_t)D_ref_FACTORY * 3000 / 4095;
   printf("mV = %d\n",D_ref_FACTORY); 
   
   while(1);
} 

Заголовочник «iostm8l151c6.h» в этом примере не используется, мы обращаемся прямо по адресу в памяти. Файл примера READ_Vref.zip находится во вложении. Теперь мы знаем, что наш камень будет сравнивать входное напряжение со значением V_ref = 1,221 Вольт.

Примечание: Точно также по адресу 0x00 4911 можно считать калибровочное значение встроенного термодатчика TS_Factory_CONV_V90, замеренное на заводе при 90 град. Цельсия. В старшем байте там всегда будет 0x3.

Теперь давайте включим COMP1 и посмотрим, как он работает.
Делитель напряжения подключаем к входу PBO:

PB_DDR_bit.DDR0 = 0; // настраиваем PB0 на вход  
PB_CR1_bit.C10 = 0;  // подтягивающий резистор - отключен

Для наблюдения за работой компаратора будем использовать голубой светодиод, расположенный на плате DISCOVERY.

PC_DDR_bit.DDR7 = 1; //настраиваем C7 на выход ГОЛУБОЙ
PC_CR1_bit.C17 = 1; //переключаем его в режим push-pull

Включаем тактирование компараторов и подключаем Vrefint к инвертирующему входу COMP1:

CLK_PCKENR2_bit.PCKEN25 = 1;
COMP_CSR3_bit.VREFEN = 1;

Замыкаем ключ AS14
Замыкаем ключ AS6
Подключаем PB0 к неинвертирующему входу COMP1

RI_ASCR2_bit.AS14 = 1;
RI_ASCR1_bit.AS6 = 1;
RI_IOSR1_bit.CH19E = 1;

Входные ножки разделены на 8 групп. В каждой группе по 3 ножки. PB0 — 1 нога в группе — значит RI_IOSR1; группа №6, значит 6 бит — он называется CH19E. Так можно выбрать любую из 24 имеющихся ножек. Можно использовать одновременно АЦП и компаратор COMP1, только если они подключены к одной и той же линии (выделена жёлтым цветом).

Включаем триггер Шмидта.
Включаем детектор фронтов (включаем, даже если не нужны прерывания!)

COMP_CSR1_bit.STE = 1;
COMP_CSR1_bit.CMP1 = 3; // 0-COMP1 выключен; 1-по спаду; 2-по фронту; 3-по фронту и спаду;

В цикле будем отображать выход компаратора:

while (1)
{   
  PC_ODR_bit.ODR7 = COMP_CSR1_bit.CMP1OUT; //компаратор в “1” - светодиод горит
}

Файл примера COMP_1.zip находится во вложении. К выходу C7 помимо светодиода я подключил осциллограф. Пока входное напряжение меньше порога, на выходе компаратора «0» и светодиод не горит. Когда выше — на выходе компаратора «1» и светодиод горит. Если входное напряжение равно порогу, компаратор находится в неустойчивом состоянии и это видно на осциллографе. Уверенный «0» (1.220 V) отличается от уверенной «1» (1.222 V) на 2mV.



Сделаем пример, в котором будут использоваться прерывания COMP1.
Добавим обработчик прерывания:

#pragma vector = COMP_EF1_vector   // прерывания по срабатыванию COMP1
__interrupt void COMP_EF1(void)
{  
  PC_ODR_bit.ODR7 = COMP_CSR1_bit.CMP1OUT; //голубой светодиод отображает выход компаратора
  COMP_CSR1_bit.EF1 = 0;   // обнуляем бит выхода из прерывания
}

Теперь голубой светодиод отображает выход компаратора уже внутри прерывания.
Внутри обработчика необходимо вручную обнулять бит выхода из прерывания EF1. На этот вектор (20) прилетают прерывания не только от COMP1, но и от COMP2 и от АЦП.

Детектор фронтов и настраивается битом CMP1 в регистре COMP_CSR1.
COMP_CSR1_bit.CMP1 = 0; // COMP1 выключен
COMP_CSR1_bit.CMP1 = 1; // генерирует прерывание по спаду
COMP_CSR1_bit.CMP1 = 2; // генерирует прерывание по фронту
COMP_CSR1_bit.CMP1 = 3; // генерирует прерывание по спаду и фронту

В main разрешаем прерывания COMP1 и глобально разрешаем прерывания.

COMP_CSR1_bit.IE1 = 1;
asm("rim");

Пока входное напряжение меньше порога, на выходе компаратора «0» и светодиод не горит. Когда выше — на выходе компаратора «1» и светодиод горит. Файл примера COMP_1_INTERRUPTS.zip находится во вложении. В следующей части мы рассмотрим COMP2 и совместную работу компараторов в оконном режиме.
  • +6
  • 01 апреля 2019, 00:09
  • CreLis
  • 3
Файлы в топике: READ_Vref.zip, COMP_1.zip, COMP_1_INTERRUPTS.zip

Комментарии (0)

RSS свернуть / развернуть
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.