AVR УРОК 37. Модуль LCD 16×2. МЕНЮ. Часть 1



    Урок 37

 

Часть 1

 

Модуль LCD 16×2 .МЕНЮ

 

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

Сегодня мы постараемся, используя опыт прошлых занятий, как-то это всё структурировать и, всё-таки, сочинить какую-нибудь навигацию или меню. А там посмотрим, что получится.

Во-первых создадим новый проект. Создадим мы его так же, как и на прошлых занятиях, назвав его LCDBUTTONMENU и выбрав контроллер Atmega8A.

Из предыдущего проекта LCDBUTTONMODE мы скопируем файлы adc.c, adc.h, button.c, button.h, lcd.c, lcd.h и main.h, а также файл протеуса, переименовав его, соответственно в  LCDBUTTONMENU.pdsprj.

Также как и на прошлом занятии, мы удалим полностью всё содержимое файла main.c и вставим в него содержимое одноимённого файла из прошлого урока.

Соберём проект и запустим файл протеуса. Поправим в свойствах путь к файлу с прошивкой

001

Проверим работоспособность прошивки в протеусе, запустив проект. если всё работает, то переходим к проекту и начинаем писать код.

А прошивать мы теперь контроллер будем опять ни из avrdude напрямую, а через меню Atmel Studio. Для этого мы также, как и раньше мы делали в 6 студии, добавим новый пункт меню и пропишем определенную строку. Чтобы добавить новый пункт меню студии, мы идём в меню в пункт «Сервис -> Новые инструменты»

 

image000

 

Попадаем в следующий диалог, в котором мы дадим нашему меню название, через обзор показываем путь к прошивальной программе avrdude, именно к командному файлу, а не к тому который запускает GUI, а в следующей строке прописываем вот такую вот команду (можете скопировать отсюда, но, конечно, без кавычек)

«-c usbasp -p m8 -B12 -U flash:w:$(ProjectDir)Debug\$(TargetName).hex:a»

 

image001

 

Теперь у нас появилось новый пункт меню в «сервисе» с нашим названием, через который мы и будем впоследствии прошивать контроллер

 

image003

 

В файле button.c добавим глобальную переменную

 

static unsigned char button_cnt[5]={0};

unsigned int tim_cnt;//счетчик тиков таймера

 

Добавим также счёт этого счётчика в обработчик прерывания от таймера TIMER0_OVF_vect

 

Read_Button_State(Button_Select);

tim_cnt++;

if(tim_cnt>=1000) tim_cnt=0;

 

Создадим и добавим в проект файлы menu.c и menu.h. Подключим файл menu.h в файл main.h

#include «button.h»

#include «menu.h»

Также добавим подключение этого файла в файл menu.c и добавим туда две переменные

#include «menu.h»

//————————————————————

extern unsigned int tim_cnt;//счетчик тиков таймера

static unsigned char i=0;

 

 

В этом же файле добавим функцию

 

static unsigned char i=0;

//——————————————————

void MenuProcess(void)

{

_delay_ms(50);

}

//——————————————————

 

Добавим прототип этой функции в файле menu.c

 

#define MENU_H_

//————————————————————

void MenuProcess(void);

//————————————————————

 

Удалим задержку из бесконечного цикла главной функции main(), остальной код в теле данного цикла пока закомментируем, т.к. пригодится. Тажже вызовем в бесконечном цикле нушу только что написанную функцию

 

while(1)

{

MenuProcess();

// setpos(0,1);

 

Удалим объявление переменной в main()

 

unsigned char i=0;

 

Массив str1 перенесем и немного исправим в файл menu.c, а в источнике удалим

 

static unsigned char i=0;

char str1[6][11]=

{

«MM_1 \0»,

«MM_2 \0»,

«MM_3 \0»,

«MM_4 \0»,

«MM_5 \0»,

«EXIT \0»

};

 

В файле menu.h добавим подключение файла main.h и две структуры для запоминания состояния нашей программы (типа в каком меню мы находимся)

 

#define MENU_H_

//————————————————————

#include «main.h»

//————————————————————

typedef enum {

  MENU_STATE_IDLE = 0,

  MENU_STATE_WAIT,

  MENU_STATE_MAIN,

}MENU_StateTypeDef;

typedef enum {

  MAIN_MENU_STATE_IDLE = 0,

  MAIN_MENU_STATE_WAIT,

  MAIN_MENU_STATE_MM1,

  MAIN_MENU_STATE_MM2,

  MAIN_MENU_STATE_MM3,

  MAIN_MENU_STATE_MM4,

  MAIN_MENU_STATE_MM5,

  MAIN_MENU_STATE_EXIT,

  MAIN_MENU_STATE_MM1_WAIT,

  MAIN_MENU_STATE_MM2_WAIT,

  MAIN_MENU_STATE_MM3_WAIT,

  MAIN_MENU_STATE_MM4_WAIT,

  MAIN_MENU_STATE_MM5_WAIT,

  MAIN_MENU_STATE_EXIT_WAIT

}MAIN_MENU_StateTypeDef;

//————————————————————

 

Добавим ещё две инициализированных переменных в файл menu.c

 

  «EXIT \0»

};

MENU_StateTypeDef menu_state = MENU_STATE_IDLE;

MAIN_MENU_StateTypeDef main_menu_state = MAIN_MENU_STATE_IDLE;

 

 

В файле menu.c в функцию MenuProcess добавим следующий код, отслеживающий текущее состояние программы

 

void MenuProcess(void)

{

switch (menu_state)

{

  case MENU_STATE_IDLE: //старт программы

  break;

  case MENU_STATE_WAIT: //ждем запуска главного меню

  break;

  case MENU_STATE_MAIN: //запуск главного меню

  break;

}

_delay_ms(50);

 

Добавим код в первый кейс

 

case MENU_STATE_IDLE: //старт программы

  menu_state = MENU_STATE_WAIT;

  clearlcd();

  setpos(0,0);

  str_lcd(«MENU»);

  setpos(0,1);

  str_lcd(«Press SELECT»);

  break;

 

Добавим код в следующий кейс

 

case MENU_STATE_WAIT: //ждем запуска главного меню

  if(button_state[Button_Select]&ST_UNPRESSURE)

  {

    SetButtonState(Button_Select,ST_LOCKED);

    ResetButtonState(Button_Select,ST_UNPRESSURE);

    SetButtonState(Button_Select,ST_PRESSURE);

    //обработка нажатия кнопки

    menu_state = MENU_STATE_MAIN;

  }

break;

 

Также уберём всё лишнее из главной функции. Останется только вот это

 

int main(void)

{

port_ini(); //инициализируем порты

LCD_ini(); //инициализируем дисплей

ADC_Init(); //инициализируем АЦП

Button_ini(); //инициализируем состояние кнопок

sei(); //включим глобальные прерывания

clearlcd(); //очистим дисплей

while(1)

 

Соберём проект и проверим в протеусе

 

002

 

 

Теперь начнём реализовывать работоспособность кнопок.

Для этого создадим ещё одну функцию с кейсами

 

//——————————————————

void MainMenuProcess(void)

{

  while (1)

  {

    switch (main_menu_state)

    {

    case MAIN_MENU_STATE_IDLE: //старт главного меню

      break;

    case MAIN_MENU_STATE_WAIT: //Ожидаем выбора меню

      break;

    case MAIN_MENU_STATE_MM1_WAIT: //ожидание выбора 1 пункта

      break;

    case MAIN_MENU_STATE_MM2_WAIT: //ожидание выбора 2 пункта

      break;

    case MAIN_MENU_STATE_MM3_WAIT: //ожидание выбора 3 пункта

      break;

    case MAIN_MENU_STATE_MM4_WAIT: //ожидание выбора 4 пункта

      break;

    case MAIN_MENU_STATE_MM5_WAIT: //ожидание выбора 5 пункта

      break;

    case MAIN_MENU_STATE_EXIT_WAIT: //ожидание выбора пункта EXIT

      break;

    case MAIN_MENU_STATE_MM1: //выбор пункта 1

      break;

    case MAIN_MENU_STATE_MM2: //выбор пункта 2

      break;

    case MAIN_MENU_STATE_MM3: //выбор пункта 3

      break;

    case MAIN_MENU_STATE_MM4: //выбор пункта 4

      break;

    case MAIN_MENU_STATE_MM5: //выбор пункта 5

      break;

    case MAIN_MENU_STATE_EXIT: //выбор пункта EXIT

      break;

    }

  }

}

//——————————————————

 

Добавим ей прототип в этом же файле сверху

 

#include «menu.h»

//————————————————————

void MainMenuProcess(void);

 

Вызовем данную функцию в предыдущей функции:

 

case MENU_STATE_MAIN://запуск главного меню

  main_menu_state=MAIN_MENU_STATE_IDLE;

  MainMenuProcess();

  break;

 

Заполним первый кейс в функции MainMenuProcess

 

case MAIN_MENU_STATE_IDLE: //старт главного меню

  setpos(0,0);

  for(i=0;i<3;i++)

  {

    str_lcd(str1[i]);

  }

  setpos(0,1);

  for(i=0;i<3;i++)

  {

    str_lcd(str1[i+3]);

  }

  _delay_ms(50);

  ResetButtonState(Button_Select,ST_LOCKED);

  main_menu_state = MAIN_MENU_STATE_WAIT;

  break;

 

Тепрь можно собрать код и проверить работоспособность кнопки Select в протеусе.

Всё работает.

Со следующими кейсами мы поработаем в следующей части урока.

 

 

Предыдущий урок Программирование МК AVR Следующая часть

 

 

Приобрести программатор USBASP USBISP с адаптером можно здесь USBASP USBISP 3.3 с адаптером

 

 

Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)

AVR Модуль LCD 16x2. МЕНЮ

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

AVR Модуль LCD 16x2. МЕНЮ

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*