Показ дописів із міткою LPCOMP. Показати всі дописи
Показ дописів із міткою LPCOMP. Показати всі дописи

суботу, 7 травня 2022 р.

MTB: PSoC4 CY8CKIT-149 дослідимо аналогові блоки ADC та LPCOMP за допомоги PDL

 Передмова

Продовжимо знайомство з мікроконтролерами Cypress, а нині це Infineon, та засобом розробки ModusToolBoxIDE. В цій статті пропоную розібратись, як працювати з аналоговими блоками, такими як ADC та LPCOMP. Програмувати будемо в засобі розробки MTB_IDE, та драйверами PDL. В попередній статті "Встановлення ModusToolBox та перший проект на CY8CKIT-149 PSoC® 4100S Plus Prototyping Kit" розглянули як встановити MTB_IDE, та створили перший проект. Використовувати будемо все той же ж  KIT Prototyping CY8CKIT-149 PSoC4, але все що буде в цій статті, буде підходити до всіх девайсів які підтримуються MTB та драйверами PDL.

Створення проекту

Запускаємо ModuToolBoxIDE, та створюємо новий проект як на малюнку, на швидкій панелі тиснемо 1:

Створення нового проекту

Далі потрібно обрати мікроконтролер або плату розробника, в цьому випадку це KIT Prototyping CY8CKIT-149 PSoC4, у вас це може бути інший чип. Головне, щоб він підтримувався та мав на борту ADC та LPCOMP:

Вибір цілі

  1. Обираємо серію МК - PSoC4
  2. Обираємо плату з цієї серії
  3. Можна переглянути документацію по цій платі
  4. Тиснемо "Next"
Створювач проектів "Project Creator" запропонує обрати шаблон проекту з прикладом до якоїсь периферії, або пустий проект. Обираємо пустий. Нам потрібно з нуля розібратись зі всіма налаштуваннями і ньюансами.
Обираємо шаблон для проекту
  1. Обираєом шаблон пустого проекту
  2. Називаємо свій проект за смаком і своїми вподобаннями
Після того, як проект створено і він з'явився в "Project explorer", пропоную розгорнути дерево проекту і відкрити головний файл "main.c":
Відкриваємо файл main.c
Залишилось всього трішки - дописати демо-код. Чим і займемось. Але перед тим відкриємо зі швидкої панелі "device-configurator", та налаштуємо периферію, як слід, для наших потреб.
Панель швидкого доступу
  1. Побудувати проект
  2. Очистити проект
  3. Прошити МК і перейти в режим відладки
  4. Залити прошивку і запустити її
  5. Відкрити утіліту "Library Manager" 
  6. Відкрити утіліту "Device Configurator"
Саме зараз нас цікавить "Device Configurator". Запусимо його і оберемо ADC:
Обираємо ADC
  1. Периферія
  2. Аналогова периферія
  3. Програмований аналог PASS
  4. 12-bit SAR ADC
Далі перейдемо до налаштувань самого ADC:
Налаштування ADC частина 1

Налаштування ADC частина 2
  1. Оберемо опірну напругу для порівняння, таку як 3.3 Вольта
  2. Поки обиремо 2 канали, далі можливо додамо ще каналів
  3. Джерело тактування оберемо один з вільних дільників
  4. Назначемо вільний та доступний пін для 0 канала
  5. Назначемо вільний та доступний пін для 1 канала
Тиснемо "CTRL + S" та зберігаємо файл налаштувань. Ще можна переглянути що за код згенерувався для налаштування ADC і двох каналів:
Попередній перегляд коду налаштувань
  1. Перейдемо до вкладки "Code Preview"
  2. Переглянемо, сам код, який генерується в проект
Зберемо такий макет для дослідження, та напишемо демо-код:
Схема макету для дослідження ADC

Демо-код ADC

Перед тим як писати демо-код, додамо бібліотеку retarget до проекту за допомоги "Library manager", для того щоб друкувати повідомлення серіал термінал по UART:

Додаємо бібліотеку retarget
  1. Тиснемо вкладку "бібліотека"
  2. Обираємо периферію
  3. Та позначаємо необхідну бібліотеку
  4. Оновлюємо перелік бібліотек для проекту
В початковий код додаємо бібліотеку ""cy_retarget_io.h"":
#include "cy_pdl.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
В головну функцію main додаємо ініціалізацію бібліотеки retarget для друку повідомлень в термінал:
result = cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE);

if (result != CY_RSLT_SUCCESS)
{
	CY_ASSERT(0);
}
І на загал, код в файлі main.c буде виглядати таким чином:
#include "cy_pdl.h"
#include "cybsp.h"
#include "cy_retarget_io.h"

int main(void)
{
    cy_rslt_t result;
    uint16_t resADC[2];

    /* Initialize the device and board peripherals */
    result = cybsp_init() ;

    if (result != CY_RSLT_SUCCESS)
    {
        CY_ASSERT(0);
    }

    result = cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE);

    if (result != CY_RSLT_SUCCESS)
    {
		CY_ASSERT(0);
    }

    /* Enable global interrupts */
    __enable_irq();

    printf("\x1b[2J\x1b[;H");
    printf("*------------------------------*\r\n");
    printf("* Demo ADC and LPCOMP started! *\r\n");
    printf("*------------------------------*\r\n");

    result = Cy_SAR_Init(SAR0, &pass_0_sar_0_config);

    if (result != CY_RSLT_SUCCESS)
    {
	CY_ASSERT(0);
    }

    Cy_SAR_Enable(SAR0);

    for (;;)
    {
    	Cy_SAR_StartConvert(SAR0, CY_SAR_START_CONVERT_SINGLE_SHOT);
    	Cy_SAR_IsEndConversion(SAR0, CY_SAR_WAIT_FOR_RESULT);
    	resADC[0] = Cy_SAR_GetResult16(SAR0, 0);
    	resADC[1] = Cy_SAR_GetResult16(SAR0, 1);
    	printf("ADC Result Channel 0 = %d mV   \r\n", Cy_SAR_CountsTo_mVolts(SAR0, 0, resADC[0]));
    	printf("ADC Result Channel 1 = %d mV   \r\n", Cy_SAR_CountsTo_mVolts(SAR0, 1, resADC[1]));
    	printf("\x1b[1F");
    	printf("\x1b[1F");
    	Cy_SysLib_Delay(1000);
    }
}
Заливаємо, запускаємо, відкриваємо термінал і спостерігаємо щось подібне:
Результат
Крутимо потенциометри і спостерігаємо за результатом.

Відео посібник


Вмикаємо і налаштовуємо LPCOMP

LPCOMP (Low Power Comparator) - компаратор з низьким споживанням. Відкриємо знову "device configurator" та увімкнемо і налаштуємо один з компараторів:
Вмикаємо LPCOMP
Та налаштовуємо як на цьому скріншоті:
Налаштування LPCOMP

  1. Конфігуруємо вихід компаратора як "Direct" коли напруга на позитивному вході менша за ту, що на негативному вході, то на виході 0, і навпаки, коли на позитивному вході напруга перевищила поріг, що є на негативному вході, то на виході буде 1. 
  2. Живлення і швидкість порівняння обираємо "Normal power/Fast".
  3. Виникає переривання в обох випадках, як по фронту, так і по спаду.
  4. Обираємо шпильку для позитивного входу.
  5. Обираємо шпильку для негативного входу.
  6. Обираємо шпильку для виходу.
  7. Обиремо, саме той пін для виходу, де є під'єднаний світлодіод, щоб наочно бачити результат порівняння вхідних напруг. Так як світлодіод під'єднаний постійно до 3.3В, то світитиме, коли на виході буде 0, а як на виході компаратора з'явиться 1 то світлодіод згасне.
Вибір шпильки для виходу компаратора

Зберігаємо зміни "CTRL+S" додаємо з'єднання компаратора і дільників.

Схема під'єднання

Додамо дротів з дільників на вхід компаратора

Демо-код для компаратора

#include "cy_pdl.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
#include "stdbool.h"

volatile bool flagLPComp = false;
cy_stc_lpcomp_context_t lpcomp_0_context;

static void lpcomp_interrupt_handler(void);

int main(void)
{
    cy_rslt_t result;
    uint16_t resADC[2];


    cy_stc_sysint_t lpcomp_interrupt_config = {
    	.intrSrc = lpcomp_0_comp_0_IRQ,
	.intrPriority = 3
    };

    /* Initialize the device and board peripherals */
    result = cybsp_init() ;

    if (result != CY_RSLT_SUCCESS)
    {
        CY_ASSERT(0);
    }

    result = cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE);

    if (result != CY_RSLT_SUCCESS)
    {
	CY_ASSERT(0);
    }

    /* Enable global interrupts */
    __enable_irq();

    printf("\x1b[2J\x1b[;H");
    printf("*------------------------------*\r\n");
    printf("* Demo ADC and LPCOMP started! *\r\n");
    printf("*------------------------------*\r\n");

    result = Cy_SAR_Init(SAR0, &pass_0_sar_0_config);

    if (result != CY_RSLT_SUCCESS)
    {
	CY_ASSERT(0);
    }

    Cy_SAR_Enable(SAR0);

    Cy_LPComp_Init(LPCOMP, CY_LPCOMP_CHANNEL_0, &lpcomp_0_comp_0_config, &lpcomp_0_context);
    Cy_LPComp_Enable(LPCOMP, CY_LPCOMP_CHANNEL_0, &lpcomp_0_context);

    Cy_LPComp_SetInterruptMask(LPCOMP, CY_LPCOMP_CHANNEL0_INTR);
    Cy_SysInt_Init(&lpcomp_interrupt_config, &lpcomp_interrupt_handler);
    NVIC_ClearPendingIRQ(lpcomp_interrupt_config.intrSrc);
    NVIC_EnableIRQ(lpcomp_interrupt_config.intrSrc);

    for (;;)
    {
    	Cy_SAR_StartConvert(SAR0, CY_SAR_START_CONVERT_SINGLE_SHOT);
	Cy_SAR_IsEndConversion(SAR0, CY_SAR_WAIT_FOR_RESULT);
	resADC[0] = Cy_SAR_GetResult16(SAR0, 0);
	resADC[1] = Cy_SAR_GetResult16(SAR0, 1);
	printf("ADC Result Channel 0 (-input) = %d mV   \r\n", Cy_SAR_CountsTo_mVolts(SAR0, 0, resADC[0]));
	printf("ADC Result Channel 1 (+input) = %d mV   \r\n", Cy_SAR_CountsTo_mVolts(SAR0, 1, resADC[1]));
	if(flagLPComp)
	{
	    printf("Output PIN LPComp is HIGT\r\n");
	}
	else
	{
	    printf("Output PIN LPComp is LOW \r\n");
	}
	printf("\x1b[1F");
	printf("\x1b[1F");
	printf("\x1b[1F");
	Cy_SysLib_Delay(1000);
    }
}

static void lpcomp_interrupt_handler(void)
{
	if(CY_LPCOMP_CHANNEL0_INTR == Cy_LPComp_GetInterruptStatusMasked(LPCOMP))
	{
	    if(Cy_LPComp_GetCompare(LPCOMP, CY_LPCOMP_CHANNEL_0))
	    {
		flagLPComp = true;
	    }
	    else
	    {
		flagLPComp = false;
	    }
	    Cy_LPComp_ClearInterrupt(LPCOMP, CY_LPCOMP_CHANNEL0_INTR);
	    NVIC_ClearPendingIRQ(lpcomp_interrupt_IRQn);
	}
}
Крутимо потенциометром на позитивному вході компаратора, і спотерігаємо, що як напруга на позитивному вході перевищує напругу на негативному вході, то вихід компаратора встановлює високий рівень і навпаки.
Результат роботи

Відео посібник