Интерфейс пользователя. Библиотека знакосинтезирующих индикаторов
Электроника
“
Как создать библиотеки функций для знакосинтезирующего индикатора? Обычно для большинства периферийных модулей, которые подключаются к микроконтроллеру, разработчики создают большую часть функционала. Он оформляется в виде пакета файлов, который мы можем использовать для работы
Глоссарий
Для успешного освоения материала рекомендуем вам изучить следующие понятия:
Знакосинтезирующий индикатор
индикатор, в котором информация, предназначенная для зрительного восприятия, отображается с помощью одного или совокупности дискретных элементов. К знакосинтезирующим относятся, например, все сегментные индикаторы, в том числе семисегментные, и матричные индикаторы
Периферийное устройство
(англ. peripheral) — аппаратура, которая позволяет вводить информацию в компьютер или выводить ее из него. Периферийные устройства являются не обязательными для работы системы и могут быть отключены от компьютера
Видеолекция
Конспект
Задача
- Создать специализированную функцию для вывода строки на индикатор в определенную позицию
- Оформить все функции в виде библиотеки функций
- Использовать эту библиотеку для создания примера вывода информации на индикатор
Алгоритм
Важно
Строка — это набор символов, заканчивающийся байтом со значением 0
1. В функцию передаются указатель на строку и номер строки на индикаторе (row) и номер колонки (column)
2. Внутрь функции вписываем установку курсора на позицию row и column
3. Устраиваем перебор всего массива символов (строки), пока не найдем значение ноль
4. Все значащие байты, исключая ноль, передаем в индикатор с кодом транзакции 1
3. Устраиваем перебор всего массива символов (строки), пока не найдем значение ноль
4. Все значащие байты, исключая ноль, передаем в индикатор с кодом транзакции 1
Работа на компьютере
1. Копируем уже созданный проект (например из другого урока) и переименовываем
2. Запускаем проект и переходим в main.c
3. Добавляем функцию, выводящую строку на экран
4. Используем функцию SetCursorLCD для установки курсора на нужную позицию
5. В цикле перебираем все элементы массива
2. Запускаем проект и переходим в main.c
3. Добавляем функцию, выводящую строку на экран
4. Используем функцию SetCursorLCD для установки курсора на нужную позицию
5. В цикле перебираем все элементы массива
Применение функции
1. Закомментируем предыдущий код
2. В функции main выводим две строки в 1-ю и 2-ю строчку экрана индикатора
3. Строки передаем как ограниченные двойными кавычками наборы символов
2. В функции main выводим две строки в 1-ю и 2-ю строчку экрана индикатора
3. Строки передаем как ограниченные двойными кавычками наборы символов
//инициализация дисплея LCD
InitLCD(ArrIntLCD);
/*
//включим курсор мограющий
DisplayOnOffLCD(1, 1, 1);
//вывод символов на экран
SendByte2LCD('A',1);
SendByte2LCD('B',1);
SendByte2LCD('C',1);
*/
print2LCD("Hello", 0, 5);
print2LCD("world", 1, 5);
while (1)
{
if(event_5s_flag==1)
{//наступило событие для тяжелой обработки - передачи в UAR
sprintf(str_out, "time event\r\n"); //строка послыки
Size_out = strlen(str_out); //размер строки
HAL_UART_Transmit(&huart2, str_out, Size_out, 10); //посылаем ответ в компьютер
event_5s_flag=0; //сбросим флаг - обработали событие
}
4. Скомпилируем проект и прошиваем устройство
5. Запускаем устройство. Выводятся соответствующие строки
5. Запускаем устройство. Выводятся соответствующие строки
Работа с библиотекой
1. Создаем файл исходного кода lcd.c
2. Создаем заголовочный файл с тем же именем, но с расширением h
3. В файл lcd.c копируем все функции, которые работают с индикатором
4. Из каждой функции копируем заголовок в lcd.h. Не забываем ставить знак ";"
5. Копируем массив шаблонных кодов инициализации lcd
2. Создаем заголовочный файл с тем же именем, но с расширением h
3. В файл lcd.c копируем все функции, которые работают с индикатором
4. Из каждой функции копируем заголовок в lcd.h. Не забываем ставить знак ";"
5. Копируем массив шаблонных кодов инициализации lcd
/*
* lcd.h
*
* Created on: 13 нояб. 2019 г.
* Author: Electronics_5
*/
#ifndef INC_LCD_H_
#define INC_LCD_H_
#include "stm32l4xx_hal.h"
void SendByte2LCD(uint8_t byte, uint8_t data_command);
void InitLCD(uint8_t *ArrIntLCD);
void ClearLCD(void);
void ReturnHomeLCD(void);
void EntryModeSetLCD(uint8_t I_D, uint8_t Shift);
void DisplayOnOffLCD(uint8_t D, uint8_t C, uint8_t B);
void CursorDisplayShiftLCD(uint8_t S_C, uint8_t R_L);
void FunctionSetLCD(uint8_t DL, uint8_t N, uint8_t F);
void SetDDRAMAddressLCD(uint8_t Address);
void SetCursorLCD(uint8_t row, uint8_t column);
void print2LCD(char * str, uint8_t row, uint8_t column);
//массив шаблонных кодов команд для инииализации LCD
uint8_t ArrIntLCD[]={0x33, 0x32, 0x08, 0x28, 0x06, 0x01, 0x0C};
#endif /* INC_LCD_H_ */
6. В блоке main поставим в заголовочный файл lcd.h, чтобы функции были доступны для работы в main
7. Компилируем
7. Компилируем
Возможные ошибки
1. Неизвестный uint8_t. Это один из типов, определение которых содержится в библиотеке HAL
Исправление: скопируем из main.h подключение заголовочного файла, связанного с микроконтроллером, и поставим его в lcd.h и icd.c
2. DB4_Pin. Это означает, что наша библиотека не видит определения линий для индикатора
2. DB4_Pin. Это означает, что наша библиотека не видит определения линий для индикатора
Исправление: посмотрим, где определены порты. Они определены в заголовочном файле stm32l476xx.h. Подключаем этот заголовочный файл в нашу библиотеку
3. Требование имен выводов, которые мы сами обозначили в конфигураторе
3. Требование имен выводов, которые мы сами обозначили в конфигураторе
Исправление: эти файлы находятся в main.h, поэтому подключаем в lcd.c заголовочный файл main.h
Важно
После компиляции lcd.c и lcd.h можно отдавать другим разработчикам. Им нужно будет только поменять имена портов и выводов и, возможно, заголовочных файлов для конкретного микроконтроллера
Алгоритм для вывода счетчика секунд
1. Добавляем событие раз в 1 секунду
//событие "раз в 1 сек"
#define HTIM1_EVENT_1s 1000
volatile int32_t htim1_event_1s_count = HTIM1_EVENT_1s; //счетчик тиков таймера для полуения события раз в 1 с
volatile uint8_t event_1s_flag = 0; //флаг события - изначально событие не установленно
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM1)
{//прерывание из таймера TIM1 - настроен на обновление раз в 1 мс
2. Добавляем обработку этого события, обработчик прерывания
//генерируем событие на 1 секунд
htim1_event_1s_count--; //уменьшаем счетчик для события
if(htim1_event_1s_count==0)
{//счетчик достиг конуа - генерим событие
htim1_event_1s_count = HTIM1_EVENT_1s; //установим счетчик в изначальное состояние
event_1s_flag = 1; //установим флаг события
}
3. Настраиваем обработчик в главном цикле программы
4. Добавляем счетчик секунд. Это глобальная переменная длинного типа uint32_t sec_counter. Первоначальное значение после загрузки равно 0
5. В обработчике событий раз в секунду увеличиваем счетчик на 1
6. Ставим ограничение счета, чтобы он обнулялся при достижении максимума
7. Формируем строку вывода счетчика на экран индикатора:
4. Добавляем счетчик секунд. Это глобальная переменная длинного типа uint32_t sec_counter. Первоначальное значение после загрузки равно 0
5. В обработчике событий раз в секунду увеличиваем счетчик на 1
6. Ставим ограничение счета, чтобы он обнулялся при достижении максимума
7. Формируем строку вывода счетчика на экран индикатора:
- формируем массив символов
- вызываем функцию sprintf и передаем ей строчку
- в спецификаторе строки укажем, в каком виде хотим вывести строку
- вызываем функцию из библиотеки
while (1)
{
if(event_5s_flag==1)
{//наступило событие для тяжелой обработки - передачи в UAR
sprintf(str_out, "time event\r\n"); //строка послыки
Size_out = strlen(str_out); //размер строки
HAL_UART_Transmit(&huart2, str_out, Size_out, 10); //посылаем ответ в компьютер
event_5s_flag=0; //сбросим флаг - обработали событие
}
if(event_1s_flag==1)
{//наступило событие "раз в 1 сек"
sec_counter++ ; //считаем секунды
if(sec_counter>9999)
sec_counter=0; //превысили передел - счет сначала
/*
char str_sec[6];
sprintf(str_sec, "%04d", sec_counter);
print2LCD(str_sec, 1, 1);
*/
event_1s_flag=0; //сбросим флаг - обработали событие
}
Алгоритм для вывода счетчика секунд со сдвигом вправо
1. Добавим новое событие раз в 250 с
2. В вызове обработчика вставляем это событие
3. Добавляем обработку этого события в главный цикл программы
4. Добавляем счетчик номера колонки как глобальную переменную. Движение строки будет осуществляться сменой номера колонки
5. Добавляем условие: если номер колонки выйдет за границы экрана, то необходимо обнулить колонку
6. Формируем строку
2. В вызове обработчика вставляем это событие
3. Добавляем обработку этого события в главный цикл программы
4. Добавляем счетчик номера колонки как глобальную переменную. Движение строки будет осуществляться сменой номера колонки
5. Добавляем условие: если номер колонки выйдет за границы экрана, то необходимо обнулить колонку
6. Формируем строку
if(event_1s_flag==1)
{//наступило событие "раз в 1 сек"
sec_counter++ ; //считаем секунды
if(sec_counter>9999)
sec_counter=0; //превысили передел - счет сначала
/*
char str_sec[6];
sprintf(str_sec, "%04d", sec_counter);
print2LCD(str_sec, 1, 1);
*/
event_1s_flag=0; //сбросим флаг - обработали событие
}
if(event_250ms_flag==1)
{//наступило событие "раз в 250 мс"
char str_sec[15];
sprintf(str_sec, "sec count=%04d", sec_counter);
if(column>0)
print2LCD(" ", 1, column-1);//запись пробела очистки в колонку перед выводом новой строки
print2LCD(str_sec, 1, column);//вывод новой строки
column++;//увеличиваем номер колонки
if(column>16)
column=0; //зацикливаем номер колонки
event_250ms_flag=0; //сбросим флаг - обработали событие
}
/*
if ( HAL_UART_Receive(&huart2, pData, Size, 10) == HAL_OK) // ждем пока не примем из UART Size-количество символов (один) блокирующий режим !!!!!
{// приняли байт
str_in[idx++]=pData[0]; //копируем вновь принятый символ в новое место входного буфера
if(idx==SIZE_INPUT-1) //если превысили размер входного буфера - то начнем с его начала
idx=0;
7. Сохраняем, компилируем, прошиваем
“
Теперь мы научились выводить «бегущую строку» на экран индикатора и составлять свою библиотеку функций. Попробуйте проделать основные моменты самостоятельно.
Интерактивное задание
Тест
Для закрепления полученных знаний
пройдите тест
пройдите тест
Стартуем! |
Для чего используют функцию SetCursorLCD ?
Дальше |
Проверить |
Узнать результат |
Что означает ошибка «неизвестный uint8_t»?
Дальше |
Проверить |
Узнать результат |
Что означает row в функции?
Дальше |
Проверить |
Узнать результат |
Какое первоначальное значение присваивается глобальной переменной uint32_t sec_counter?
Дальше |
Проверить |
Узнать результат |
К сожалению, вы ответили неправильно
Прочитайте лекцию и посмотрите видео еще раз
Пройти еще раз |
Неплохо!
Но можно лучше. Прочитайте лекцию и посмотрите видео еще раз
Пройти еще раз |
Отлично!
Вы отлично справились. Теперь можете ознакомиться с другими компетенциями
Пройти еще раз |