Найти в Дзене
DGO шпаргалка

Семисегментный индикатор на китайском CH32V003. Часть2. Таймер, а не задержка.

Привет! Это снова я. Поспрашивал я немного в этих ваших интернетах про предыдущую статью и, оказалось, нужно писать ещё... подробнее. Буду исправляться! И начну с самого начала. Ссылка на предыдущую статью Ссылка на следующую статью Сама плата выглядит примерно так: Надписи, в отличие, например, от Ардуино Нано обозначают не аналоговые или цифровые порты, а аббревиатуру от аббревиатуры GPIO PORT X PIN X. Таким образом надпись "D5" обозначает пин 5 на порте 4. И в среде разработки MounRiver Studio при настройке порта нужно сначала включить тактирование всего порта, а уже потом настраивать пин, как нам нужно. Самая большая сложность в отображении информации на семисегментных индикаторах в том, что под каждый из них нужно по семь выводов микроконтроллера. И чтобы сделать простенькие часы только под отображение времени нужно 28 выводов контроллера! Или нет? На самом деле все сложнее и интереснее! Есть такая "штука", как динамическая индикация. То есть мы можем отображат
Оглавление

Привет! Это снова я.

Поспрашивал я немного в этих ваших интернетах про предыдущую статью и, оказалось, нужно писать ещё... подробнее. Буду исправляться! И начну с самого начала.

Ссылка на предыдущую статью

Ссылка на следующую статью

Со схемы.

Схема
Схема

Сама плата выглядит примерно так:

Слева плата прототипирования, справа программатор для этих контроллеров WCH-LinkE-R0-1v3
Слева плата прототипирования, справа программатор для этих контроллеров WCH-LinkE-R0-1v3

Надписи, в отличие, например, от Ардуино Нано обозначают не аналоговые или цифровые порты, а аббревиатуру от аббревиатуры GPIO PORT X PIN X. Таким образом надпись "D5" обозначает пин 5 на порте 4. И в среде разработки MounRiver Studio при настройке порта нужно сначала включить тактирование всего порта, а уже потом настраивать пин, как нам нужно.

-3

Приближаясь к теме статьи.

Самая большая сложность в отображении информации на семисегментных индикаторах в том, что под каждый из них нужно по семь выводов микроконтроллера. И чтобы сделать простенькие часы только под отображение времени нужно 28 выводов контроллера! Или нет? На самом деле все сложнее и интереснее! Есть такая "штука", как динамическая индикация. То есть мы можем отображать информацию на каждом из сегментов по очереди. Используя подключение индикаторов параллельно. И в момент отображения цифры на индикаторе включать только его, подавая питание на общий вывод или притягивая его к земле, в зависимости от конструкции. Это как бежать вдоль забора от собаки на другой стороне. И мы ее видим и она нас. Весело! Но стоит только остановиться, как из всей собаки виден только злой глаз. Это явление называется инерционность зрения.

Чтобы избежать остановок и достичь скорости переключения индикаторов, необходимой для активации нужного эффекта без визуальных подергиваний нужно в первую очередь избавить программу от функуии DelayMs();, которая просто останавливает всю работу контроллера на время.

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

Картинка с официального сайта производителя на контроллер.
Картинка с официального сайта производителя на контроллер.

Как видно из структурной схемы микроконтроллера нам доступны два внутренних таймера:

1×16-bit general-purpose timer - GPTM*1 - TIM2

1×16-bit advanced-control timer - Advanced TM*1 -TIM1

С нашей задачей справится любой из таймеров. Выберем TIM1 и проинициализируем. Для этого создадим функцию TIM_init(); Располагаться она может как до, так и после функции инициализации портов в теле программы.

void TIM_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
// инициализация таймера
TIM_CounterModeConfig(TIM1, TIM_CounterMode_Up);// режим прямого счета
TIM_SetAutoreload(TIM1, 100);// настройка автоперезагрузки
TIM_PrescalerConfig(TIM1, 48000 - 1, TIM_PSCReloadMode_Immediate); //прескаллер
TIM_Cmd(TIM1, ENABLE); //разрешение работы таймера
}

Функция TIM_SetAutoreload(TIM_TypeDef *TIMx, uint16_t Autoreload) позволяет выбрать период в миллисекундах до перезагрузки выбранного таймера, а для того, чтобы миллисекунды длились как раз-таки миллисекунды нужно настроить прескаллер. Цифра 48000 Была взята из настройки "#define SYSCLK_FREQ_48MHz_HSE 48000000", которая находится в файле "system_ch32v00x.c" в той же папке, что и файл "main.c" и нужна для выбора источника тактирования микроконтроллера и частоты этого самого тактирования.

Далее включаем в функцию main() нашу инициализацию и можем пользоваться таймером вместо задержки выполнения всей программы. Существует несколько способов, как можно это сделать. Лучшим решением было бы использование прерывания, но пока что будем использовать условный оператор и сравнивать значение обнуляющегося каждый период счетчика таймера с любым возможным значением из этого счетчика и выполнять какое-то действие при каждом совпадении. Период мы можем поставить любой, а срабатывание условия должно выполняться, так что выберем за значение для сравнения - "0" - он есть в любом периоде.

Для получения значений счетчика MRS(MounRiver Studio) предлагает использовать функцию "uint16_t TIM_GetCounter(TIMx)" - возвращает целые числа формата uint16_t. Так и поступим.

Помигаем цифрой СЕМЬ на нашем индикаторе.

Обозначение порядка светодиодов
Обозначение порядка светодиодов

Для этого будем зажигать и гасить каждый период светодиоды A, B, C.

int main(void) //обновленный вид функции "main()"
{

u8 i = 0; // переменная для хранения состояния светодиодов
SystemCoreClockUpdate();
GPIO_INIT();
// инициализация портов
TIM_Init();
// инициализация таймера
while(1)
// бесконечный цикл
{
if(TIM_GetCounter(TIM1)==0){
// если значение счетчика равно нулю
if (i == 1) i=0; else i = 1;
// меняем значение переменной состояния таймера на противоположное
}
GPIO_WriteBit(GPIOD, LED1_A ,i);
// зажигаем(гасим) выбранный светодиод
GPIO_WriteBit(GPIOD, LED1_B ,i);
GPIO_WriteBit(GPIOD, LED1_C ,i);
}
}

Видео работы программы.
Видео работы программы.

Без рассеивателей, конечно, на цифру не очень похоже, но всему свое время.

Наша реализация имеет много недостатков, в том числе диоды мигают не стабильно. Работу над ошибками проведем в следующий раз.

Спасибо за внимание! Буду рад критике и комментариям.