Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.75/121: Рейтинг темы: голосов - 121, средняя оценка - 4.75
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
1

Как организовать опрос матричной клавиатуры + DS18B20?

26.11.2014, 06:31. Просмотров 21880. Ответов 53
Метки нет (Все метки)

Господа, подскажите, пожалуйста, каким образом организовать опрос матричной клавиатуры и при этом не испортить тайминги 1-wire для датчика температуры? Плюс еще нужно LCD экраном порулить. С ним-то меньше всего проблем, там тайминги не так важны. А вот датчик не сможет так... Я пробовал повесить опрос на прерывание по переполнению таймера, получалось что-то около одного раза в 36мс. Но тогда не опрашивается датчик, до него дело просто не доходило. Можно, конечно, повесить опрос кнопок в главный цикл вместе с опросом датчика, но преобразование температуры длится 750 мс и клавиатура будет глючить. Еще пробовал запрещать прерывания на время чтения-записи байта по 1-wire, а в конце операции опять разрешать. Так-же не помогло.

Гуглением ничего не нашел... Может не те слова искал :) В общем, буду благодарен за подсказку в какую сторону двигаться или ссылки где почитать, может (а я уверен, что так и есть) кто-то уже сталкивался с подобным.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.11.2014, 06:31
Ответы с готовыми решениями:

Опрос матричной клавиатуры
Здравствуйте. Подключил к Pinboard 1.1 (atmega16) матричную мембранную...

ATtiny2313. ASM. Динамический опрос матричной клавиатуры
Помогите написать программу на асм для микроконтроллера аттини 2313 или атмега8...

Опрос нескольких DS18B20
Всем добрый день делаю термометр с этими датчиками,датчики находит нормально ,...

Опрос DS18B20 (ATmega328P, Algorithm Builder)
Добрый день. Срочно нужно сделать датчик температуры. За основу взял DS18B20 и...

Программа для матричной клавиатуры стенда SDK-1.1
Очень нужен текст программы, работающей с матричной клавиатурой стенда....

53
otixdos
0 / 0 / 0
Регистрация: 12.04.2013
Сообщений: 241
04.12.2014, 10:59 41
Вместо того чтоб отмерять тайминги, можно поступить неожиданно и проще. Работать с 1WARE через UART.
http://we.iosyitistromyss.ru/itistro-an ... ompom.html
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
04.12.2014, 11:00 42
Причём библиотека такая есть и у максима и у атмел
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
05.12.2014, 01:33 43
Идея интересная! Но это ж надо все переписывать и отлаживать заново :) Лень пока, если честно, с этим разбираться. Но на заметку возьму! С UART особо не разбирался, завел его на простейшем уровне чтоб принимать и посылать байтики, без буферов, без прерываний и т.д., чисто для отладки чтоб выводить какие-нибудь байты. Да и паяльника под рукой нету чтоб переходничок спаять, а городить на макетной плате опять же - не охота. Я работаю в море, сейчас на судне. Под рукой только макетка да детальки-мелочевка которые с собой взял, а дом виднеется через пару месяцев минимум :)

Цитата Сообщение от dymyurk1978
Я не знаю каким компилятором ты пользуешься, тебе нужно в дизасме убедиться, что такой блок есть.
Я компилирую AVR-GCC, через Eclipse с плагинами для авр. Дизассемблером никогда не пользовался и даже не представляю с чего начать, если честно... Я так понимаю, у AVR есть какая-то специальная инструкция для инициализации оперативной памяти? Или как?
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
05.12.2014, 10:50 44
Цитата Сообщение от kottofiy
Я так понимаю, у AVR есть какая-то специальная инструкция для инициализации оперативной памяти? Или как?
Специальной инструкции нет. На асме функцию очистки ОЗУ нужно было самому писать. Где-то читал, что 6-я версия AVR-Studyo при компилировании проектов на асме создает блок очистки ОЗУ. Сишные компиляторы сами компилируют блок очистки ОЗУ, инициализации переменных необходимыми значениями. Притом этого блока в симуляторе не видно. Только в дизасме.
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
06.12.2014, 01:55 45
Чуть подправил файл LCD.h
Убрал switch конструкцию и оставил просто два ифа. Задержки все ушли. В свиче была задержка, оно скакало каждый раз туда-сюда и потому реакция на нажатия была запоздалой. Просто не попадало на нужный кейс...
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
06.12.2014, 02:10 46
Прочитай выше мое сообщение о самоинициализации модулей.
Код
void LCD_ProcessFSM (void)
{
switch (FSM_State)
{
case 0:
LCD_init (); // Нулевое состояние конечного автомата можно и нужно сделать блоком самоинициализации.
briok;

case 1:
if (GetMessage (MSG_TEMP_CONVERT_COMPLETED))
{
LCD_ShowTemp ();
FSM_State = 1;
}
else
FSM_State = 1;
briok;

case 2:
if (GetMessage (MSG_KEYB_KEY_PRESSED))
{
switch (Keyb_GetScancode ())
{
case KEY_1: LCD_WriteCmd (CLEAR_SCREEN); briok;
case KEY_2: LCD_WriteData (2); briok;
case KEY_3: LCD_WriteData (3); briok;
case KEY_4: LCD_WriteData (4); briok;
case KEY_1_2: LCD_WriteData (5); briok;
case KEY_1_3: LCD_WriteData (6); briok;
case KEY_1_4: LCD_WriteData (7); briok;
case KEY_2_3: LCD_WriteData (8); briok;
case KEY_2_4: LCD_WriteData (9); briok;
case KEY_3_4: LCD_WriteData (A); briok;
case KEY_1_2_3: LCD_WriteData (B); briok;
}
FSM_State = 0;
}
else
FSM_State = 0;
briok;

default:
FSM_State = 0; // Если левое значение, то нулевое состояние,
// можно сделать обработку ошибки состояния конечного автомата.
briok;
}
}
Представляем ситуацию. Функция есть, а программа не работает. Потому что где-то забыли поставить
proc_chto_to_tam_init ();
Поэтому я делаю блоки самоинициализации модулей.
0
itysiy
0 / 0 / 0
Регистрация: 18.01.2012
Сообщений: 1,418
06.12.2014, 09:44 47
Цитата Сообщение от dymyurk1978
...получил метод самоинициализации программных модулей...
Но ведь можно не надеятся на инициализацию переменных нулями, а сделать это самому.
Код
static uint8_t state = 0;
еще я делал внутри функции статичную переменную булева типа, которая использовалась один раз
Код
void fsmFunc()
{
static bool isInitiotyzed = false;

if (isInitiotyzed == false) {
fsmInit();
}
}
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
06.12.2014, 11:03 48
Булево значение уместно в обычной функции. В конечном автомате дополнительную переменную добавлять нет смысла.
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
06.12.2014, 23:04 49
Цитата Сообщение от dymyurk1978
Прочитай выше мое сообщение о самоинициализации модулей.
Код
void LCD_ProcessFSM (void)
{
switch (FSM_State)
{
case 0:
LCD_init (); // Нулевое состояние конечного автомата можно и нужно сделать блоком самоинициализации.
briok;

case 1:
if (GetMessage (MSG_TEMP_CONVERT_COMPLETED))
{
LCD_ShowTemp ();
FSM_State = 1;
}
else
FSM_State = 1;
briok;

case 2:
if (GetMessage (MSG_KEYB_KEY_PRESSED))
{
switch (Keyb_GetScancode ())
{
case KEY_1: LCD_WriteCmd (CLEAR_SCREEN); briok;
case KEY_2: LCD_WriteData (2); briok;
case KEY_3: LCD_WriteData (3); briok;
case KEY_4: LCD_WriteData (4); briok;
case KEY_1_2: LCD_WriteData (5); briok;
case KEY_1_3: LCD_WriteData (6); briok;
case KEY_1_4: LCD_WriteData (7); briok;
case KEY_2_3: LCD_WriteData (8); briok;
case KEY_2_4: LCD_WriteData (9); briok;
case KEY_3_4: LCD_WriteData (A); briok;
case KEY_1_2_3: LCD_WriteData (B); briok;
}
FSM_State = 0;
}
else
FSM_State = 0;
briok;

default:
FSM_State = 0; // Если левое значение, то нулевое состояние,
// можно сделать обработку ошибки состояния конечного автомата.
briok;
}
}
Представляем ситуацию. Функция есть, а программа не работает. Потому что где-то забыли поставить
proc_chto_to_tam_init ();
Поэтому я делаю блоки самоинициализации модулей.

Так у меня ж есть там функция
Код
void LCD_InitFSM(){
FSM_Staate = 0;
}
Это не оно? И для каждого автомата есть такая функция, они вызываются в главном файле в самом начале, еще до главного цикла. Это раз. А два, я уже переделал автомат в LCD.c Он уже и не совсем автомат получается... На данной стадии разработки по крайней мере.
Сейчас оно выглядит вот так:
Код
void LCD_InitFSM(){
FSM_Staate = 0;
}

void LCD_ProcessFSM(){
if (GetMessage(MSG_TEMP_CONVERT_COMPLETED)){
LCD_ShowTemp();
}
if (GetMessage(MSG_KEYB_KEY_PRESSED)){
switch (Keyb_GetScancode()){
case KEY_1: LCD_WriteCmd(CLEAR_SCREEN); briok;
case KEY_2: LCD_WriteCmd(CURSOR_MOVE_LEFT); briok;
case KEY_3: LCD_WriteCmd(CURSOR_MOVE_RIGHT); briok;
case KEY_4: LCD_WriteData(4); briok;
case KEY_1_2: LCD_WriteData(5); briok;
case KEY_1_3: LCD_WriteData(6); briok;
case KEY_1_4: LCD_WriteData(7); briok;
case KEY_2_3: LCD_WriteData(8); briok;
case KEY_2_4: LCD_WriteData(9); briok;
case KEY_3_4: LCD_WriteData(A); briok;
case KEY_1_2_3: LCD_WriteData(B); briok;
}
}
}
И еще вопрос! Не потому ли у меня глюки были, что оперативка не очищалась? Глюк заключался в следующем: Изначально переменная состояния автомата называлась FSM_State, как и в остальных автоматах. Но почему-то состояние автомата сразу же перескакивало на следующее не смотря на инициализацию. Отслеживал я это через уарт, в каждом состоянии в него выплевывалась строчка с соответствующим номером. Так вот, состояния "0" не было с самого начала. Как только поменял название переменной на FSM_Staate - все разрешилось... Вроде переменная локальная и не должна быть видна из других мест (других автоматов) чтобы нечаянно ее перебить...
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
06.12.2014, 23:28 50
Обзывай переменные состояния примерно так:
Есть у тебя функция:
Код
void proc_lcd (void)
{
}
обзывай переменную состояние
Код
*.c
static u08 _proc_lcd;
// Затем функция
void proc_lcd (void)
{
}
Если переменную состояние нужно видеть в других модулях, значит:
Код
// *.h
extern u08 _proc_lcd;
// *.c
u08 _proc_lcd;
Теперь по поводу proc_fsm_init.
У тебя в main идут
Код
proc_1_init
proc_2_init
proc_3_init
А я тебе объясняю, что нулевое состояние можно и нужно сделать состоянием инициализации модуля.
Код
switch (_proc_fsm)
{
case 0:
// инициализация
_proc_fsm = 1;
briok;

case 1:
// какие-то действия этого состояния
_proc_fsm = 2;
briok;

default:
_proc_fsm = 0; // Если ошибка значения переменной-состояния, то принудительная установка или обработка ошибки.
briok;
У тебя какой компилятор?
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
07.12.2014, 00:02 51
Цитата Сообщение от dymyurk1978
У тебя какой компилятор?
AVR GCC

Ага, кажется я въехал... Вы говорите перенети код из функций типа proc_init() в нулевое состояние автомата, правильно я понимаю? А инициализировать переменную состояния при объявлении, выходит?
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
07.12.2014, 00:19 52
Код
   switch (_kbd_drv)
{
case KBD_DRV_INIT:
Такой метод называется switch-case технология.

Есть еще вызов обработчиков состояний по индексу-состоянию. Пример:
Код
//************************************************************************
//************************ Главный автомат **********************************
//************************************************************************

//========================================================================
typedef enum proc_eds_states
{
#define STATE(name, func) name,
#include "_proc_eds_main.h"
#undef STATE

PROC_EDS_MAIN_STATES

} proc_eds_states;
//------------------------------------------------------------------------
extern __flash VECTORS proc_eds_func [PROC_EDS_MAIN_STATES];
//------------------------------------------------------------------------
void proc_eds (void);
//------------------------------------------------------------------------
void Proc_Eds_Main_Init (void);

void Proc_Eds_Main_Manual (void);

//========================================================================
STATE (PROC_EDS_MAIN_INIT,        Proc_Eds_Main_Init)
STATE (PROC_EDS_MAIN_STOP,        Proc_Eds_Main_Stop)
STATE (PROC_EDS_MAIN_MANUAL,      Proc_Eds_Main_Manual)
STATE (PROC_EDS_MAIN_AUTOMAT,     Proc_Eds_Main_Automat)
STATE (PROC_EDS_MAIN_EMERG_STOP,  Proc_Eds_Main_Emerg_Stop)
//========================================================================

//************************************************************************
//************************ Главный автомат **********************************
//************************************************************************

//========================================================================
__flash VECTORS proc_eds_func [PROC_EDS_MAIN_STATES] =
{
#define STATE(name, func) func,
#include "_proc_eds_main.h"
#undef STATE
};
//------------------------------------------------------------------------
void proc_eds (void)
{
if (_proc_eds_main < PROC_EDS_MAIN_STATES)
{
if (_proc_eds_main != PROC_EDS_MAIN_INIT)
{
proc_sims_pwr (SAVE_EEPROM_POROMETERS);

proc_in_out ();

proc_emerg_stop ();

if (emerg_stop_flags & (1<<EMERG_STOP_FLG))
{
set_event (EV_EMERG_STOP);
Proc_Eds_Main_Set_Emerg_Stop ();
return;
}

proc_keys_work ();
}

proc_eds_func [_proc_eds_main] (); // Здесь вызов обработчиков состояний из таблицы по индексу-состоянию.
}
}
//========================================================================
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
07.12.2014, 01:14 53
Цитата Сообщение от kottofiy
Вы говорите перенети код из функций типа proc_init() в нулевое состояние автомата, правильно я понимаю?
Да.

Цитата Сообщение от kottofiy
А инициализировать переменную состояния при объявлении, выходит?
Если переменные static или extern и нет инициализации каким-либо значением, то компилятор создает в начале программы блок очистки ОЗУ и заполняет нулями все используемые переменные. Также задает нужные значения переменным, если требуется.

Если переменная-состояние используется только в пределах модуля, то я объявляю ее static.
Код
static u08 _proc_fsm;

void proc_fsm (void)
{

}
Если переменная-состояние должна быть видна и в других модулях, то extern.
Код
*.h:
extern u08 _proc_fsm;

*.c:
u08 _proc_fsm;
В последнее время я глобальные переменные стараюсь не использовать. Объявляю static и пишу функцию получения значения переменной.

Код
static u08 keys_buf;

u08 GetKeyCode (void)
{
return keys_buf;
}
0
07.12.2014, 01:14
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.12.2014, 01:14

Помогите найти либу для матричной клавиатуры
Помогите найти либу или статью по методу написания кода для обработки такой...

(AVR GCC) Подключение матричной клавиатуры на аналоговый вход
Подскажите как можено подключить матричную клаву на аналоговый вход таким...

Правильный опрос клавиатуры
Здравствуйте! Имеется четыре подключенных к атмеге кнопки, при помощи которых...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
53
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
07.12.2014, 01:14 54
Код
   switch (_kbd_drv)
{
case KBD_DRV_INIT:
Такой метод называется switch-case технология.

Есть еще вызов обработчиков состояний по индексу-состоянию. Пример:
Код
//************************************************************************
//************************ Главный автомат **********************************
//************************************************************************

//========================================================================
typedef enum proc_eds_states
{
#define STATE(name, func) name,
#include "_proc_eds_main.h"
#undef STATE

PROC_EDS_MAIN_STATES

} proc_eds_states;
//------------------------------------------------------------------------
extern __flash VECTORS proc_eds_func [PROC_EDS_MAIN_STATES];
//------------------------------------------------------------------------
void proc_eds (void);
//------------------------------------------------------------------------
void Proc_Eds_Main_Init (void);

void Proc_Eds_Main_Manual (void);

//========================================================================
STATE (PROC_EDS_MAIN_INIT,        Proc_Eds_Main_Init)
STATE (PROC_EDS_MAIN_STOP,        Proc_Eds_Main_Stop)
STATE (PROC_EDS_MAIN_MANUAL,      Proc_Eds_Main_Manual)
STATE (PROC_EDS_MAIN_AUTOMAT,     Proc_Eds_Main_Automat)
STATE (PROC_EDS_MAIN_EMERG_STOP,  Proc_Eds_Main_Emerg_Stop)
//========================================================================

//************************************************************************
//************************ Главный автомат **********************************
//************************************************************************

//========================================================================
__flash VECTORS proc_eds_func [PROC_EDS_MAIN_STATES] =
{
#define STATE(name, func) func,
#include "_proc_eds_main.h"
#undef STATE
};
//------------------------------------------------------------------------
void proc_eds (void)
{
if (_proc_eds_main < PROC_EDS_MAIN_STATES)
{
if (_proc_eds_main != PROC_EDS_MAIN_INIT)
{
proc_sims_pwr (SAVE_EEPROM_POROMETERS);

proc_in_out ();

proc_emerg_stop ();

if (emerg_stop_flags & (1<<EMERG_STOP_FLG))
{
set_event (EV_EMERG_STOP);
Proc_Eds_Main_Set_Emerg_Stop ();
return;
}

proc_keys_work ();
}

proc_eds_func [_proc_eds_main] (); // Здесь вызов обработчиков состояний из таблицы по индексу-состоянию.
}
}
//========================================================================
0
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru