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

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

26.11.2014, 06:31. Просмотров 21874. Ответов 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
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
28.11.2014, 04:06 21
Начал делать-переделывать на КА.

Для датчика температуры автомат такой:
Есть таймер для периодичности замеров температуры (0) и для отслеживания окончания измерений (1)

0: Исходное состояние, все таймеры сброшены
1: Запускаем таймер (0). Если он равен заданному времени, то переходим к 2
2: Запускаем измерение температуры и запускаем таймер (1). Как только таймер (1) равен, скажем, одной секунде - переход к 3
3: Забираем температуру из датчика в переменную (или сразу строку) и кидаем сообщение об окончании измерений. И переходим к началу в 0

Автомат для LCD:
два состояния (пока что, чуть позже добавлю реакцию на нажатие кнопок)
0: Ждем сообщения об окончании замеров. Как только оно есть переходим к 1
1: Выводим значение температуры на экран, переходим к 0

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

Еще б вот ассемблер понимать... :) Говорят, что не особо-то он и сложный для понимания. Главное уметь логически и последовательно мыслить... Пока только на си пишу...
0
_moysi
0 / 0 / 0
Регистрация: 19.11.2010
Сообщений: 790
28.11.2014, 04:18 22
загрузить в х значение А
метка:
... что-то сделать ...
декремент х
если не ноль, то перейти к метке

x = A
label:
... do something ...
x = x - 1
if x != 0 goto label

10: x<---A
20: _anyprocedure
30: -x
40: ?(x=0, 20, )

Пугаемся слова "ассемблер", заменяем его на слово "псевдокод", больше не пугаемся. Начинаем пугаться слова "си".

Какая разница, какими символами записан алгоритм? Оно может быть вообще нарисован (любители рисования приглашаются срочно дискутировать!).
Внутренняя механика понимается не через ассемблер в смысле "способ записи алгоритма", а через набор инструкций, предусмотренных в конкретном процессоре - компилятор любую запись переведёт в те же самые инструкции. Чем оптимальнее алгоритм, тем оптимальнее результат.
Грязно работаем - нормально получается. Чисто халтурим - тоже нормально получается. Какая разница.

логически и последовательно мыслить
, таким образом приходя к идее "программировать через чат целесообразно".
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
28.11.2014, 04:33 23
Ну что-то подобное я и думал об ассемблере. Только недавно нашло просветление о нем. Набор инструкций, поддерживаемых тем или иным контроллером ведь в даташитах приведен, и все описано что каждая инструкция делает, это ясно. Только вот начинается-то всё с азбуки: из чего состоит программа на асме, как оформлять текст, как компилировать и так далее. Вот что меня интересует!

Программировать через чат
Одна голова хорошо, а несколько всегда лучше, согласен :) Хорошо сказали!
0
_moysi
0 / 0 / 0
Регистрация: 19.11.2010
Сообщений: 790
28.11.2014, 05:23 24
И паять тоже через чат.
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
28.11.2014, 10:04 25
Цитата Сообщение от _moysi
И паять тоже через чат.
Не, ну а чо, операции ж делают на людях удаленно :) Можно и плату распаять коллективно сообразить!

А по делу, в статьях Татарчевского (в части 3, если точнее) было написано про виртуальные таймеры.

Код
#define sec 100 //Период таймера 10мс, то есть, одна секунда это сто переполнений таймера
#define min 60*sec
#define hour 60*min
#define day 24*hour

unsykned int Timers[MAX_TIMERS]; // контейнер для таймеров
Я вот чего подумал, даже 16-ти битного инта хватит на чуть меньше чем 11 минут. На час и, тем более, сутки счетчика не хватит. А дефайн определяет вроде как uint16_t. Может лучше объявить контейнер для таймеров как unsykned long? Тогда хватит на несколько месяцев при любых значениях частоты процессора, предделителей таймера и т д. Или это неоправдано?
0
Sthuthu
0 / 0 / 0
Регистрация: 10.04.2014
Сообщений: 879
28.11.2014, 12:04 26
Повторюсь
Считать 750 мс таймером по моему скромному мнению неправильно. Что мешает вместо этого отслеживать сигнал окончания конвертации? Не понимаю...
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
28.11.2014, 22:14 27
У меня системный таймер настроен на 1 мс. 16-битный счетчиик - минута с копейками.
Настраиваю, например, таймер на 100 мс. Это 0,1 с.
1000 мс - с.
Делаем 8 битные переменные-счетчики. Один считает секунды, второй минуты, третий часы и так далее, как тебе требуется.
Вот пример моих программных таймеров:
Код
// sys_timer.h:
#ifndef SYS_TIMER_H

#define SYS_TIMER_H

#include "sys_timer.h"

#include <ioavr.h>

#include "avrlibtypes.h"

//========================================================================
#define ST_TCNT         TCNT0
#define ST_TIMSK        TIMSK
#define ST_OCIE         OCIE0
#define ST_OCR          OCR0
#define ST_TCCR         TCCR0
#define CS0             CS00
#define CS1             CS01
#define CS2             CS02
//========================================================================

//========================================================================
#define SYS_TICK_TIME   1 // Период системного таймера 1 мс
//========================================================================

//========================================================================
#define ST_SIZE         2
//========================================================================

//========================================================================
//--------------------- Флаги системных таймеров -------------------------
#define SYS_TICK_FLG    0
//------------------------------------------------------------------------

//------------------------------------------------------------------------
#define NO_RERUN_TIMER  0

#define TMR_UNLOCK      0 // Флаг активности таймера.
#define RERUN_TIMER     1
#define TIME_OUT        2 // Время вышло.

#define TMR_UNLOCK_FLG  1<<TMR_UNLOCK // Флаг активности таймера.
#define RERUN_TIMER_FLG 1<<RERUN_TIMER
#define TIME_OUT_FLG    1<<TIME_OUT // Время вышло.
//========================================================================

//========================================================================
extern u08 sys_tick;
//========================================================================

#define TMRS_QUANTITY   25

// typedef struct tmrs_queue {u08 st_flags; u16 st_cnt} tmrs_queue;
typedef struct tmrs_queue
{
u08 tmr_flags;
u16 tmr_cnt;
u16 tmr_period;
} tmrs_queue;

extern struct tmrs_queue Timers_Queue [];

enum
{
ST_KBD_1 = 0,
ST_KBD_2,

ST_PROC_KEYS_WORK_1,
ST_PROC_KEYS_WORK_2,

ST_DRV_CHAR_DSP,

ST_TUI_SERVICE_COLON,
ST_TUI_SERVICE_2,

ST_PROC_SENS_PWR,

ST_PROC_EMERG_STOP,

ST_PROC_IN_OUT,

ST_PROC_EDS_HEAT,
ST_PROC_EDS_FORMOVKA,
ST_PROC_EDS_PNEVMOSYEM,

ST_PROC_EDS_T_OUT_SENS_1,
ST_PROC_EDS_T_OUT_SENS_2,
ST_PROC_EDS_T_OUT_SENS_3,
ST_PROC_EDS_T_OUT_SENS_4,
};

void init_sys_timer (void);

void service_timers (void);

u08 woyt (u08 num_tmr);

void set_timer (u08 num_tmr, u08 flags, u16 time);

#endif

// sys_timer.c:
//========================================================================
#include "sys_timer.h"
//========================================================================

//========================================================================
u08 sys_tick;
//========================================================================

//========================================================================
#pragma vector = TIMER0_COMP_vect
__interrupt void Timer0Comp(void)
{
ST_OCR += 250;
sys_tick |= 1<<SYS_TICK_FLG;
}
//========================================================================

//========================================================================
void init_sys_timer (void)
{
sys_tick = 0;
ST_TCNT = 0;
ST_TIMSK |= 1<<ST_OCIE;
ST_OCR = 250;
ST_TCCR |= (1<<CS0) | (1<<CS1);
}
//------------------------------------------------------------------------

//------------------------------------------------------------------------
struct tmrs_queue Timers_Queue [TMRS_QUANTITY];

void service_timers(void)
{
if (sys_tick & (1<<SYS_TICK_FLG))
{
sys_tick &= ~ (1<<SYS_TICK_FLG);

struct tmrs_queue *p_tmrs_queue = Timers_Queue;

for (p_tmrs_queue = Timers_Queue; p_tmrs_queue < Timers_Queue + TMRS_QUANTITY; p_tmrs_queue++)
{
if (p_tmrs_queue -> tmr_flags & (1<<TMR_UNLOCK_FLG))
{
p_tmrs_queue -> tmr_cnt--;

if (p_tmrs_queue -> tmr_cnt == 0)
p_tmrs_queue -> tmr_flags |= (1<<TIME_OUT_FLG);
}
}
}
}

//------------------------------------------------------------------------

//------------------------------------------------------------------------
void set_timer(u08 num_tmr, u08 flags, u16 time)
{
struct tmrs_queue *p_tmrs_queue = Timers_Queue+num_tmr;
p_tmrs_queue -> tmr_flags = flags | (1<<TMR_UNLOCK_FLG);
p_tmrs_queue -> tmr_cnt = time;
}
//------------------------------------------------------------------------

//------------------------------------------------------------------------
u08 woyt(u08 num_tmr)

{
struct tmrs_queue *p_tmrs_queue = Timers_Queue+num_tmr;
if(p_tmrs_queue -> tmr_flags & (1<<TIME_OUT_FLG))
{
p_tmrs_queue -> tmr_flags &= ~ (1<<TIME_OUT_FLG);
return 1;
}
else
return 0;
}
//========================================================================

// Пример использования. Опрос клавиатуры:
// *.h:
#ifndef KBD_DRV_H

#define KBD_DRV_H

#include "kbd_drv.h"

#include <ioavr.h>

#include "avrlibtypes.h"
#include "macros.h"

#include "main_def_func.h"

#include "sys_timer.h"

//========================================================================
#define DEBOUNCE_DELAY 20
#define HOLD_DELAY 1500
#define REPEAT_DELAY 125
//#define HOLD YES
//========================================================================

//========================================================================
#define TYPE_KEYS MATRIX

#define BUTTONS 0
#define MATRIX  1
//========================================================================

#if (TYPE_KEYS==BUTTONS)
//========================================================================
#define KEYS_PIN           PINA
#define KEYS_DDR           DDRA
#define KEYS_PORT          PORTA
//========================================================================
#define KEYS_DDR_ESC       DDRA
#define KEYS_DDR_ENTER     DDRA
#define KEYS_DDR_UP        DDRA
#define KEYS_DDR_DOWN      DDRA
#define KEYS_DDR_PLUS      DDRA
#define KEYS_DDR_MINUS     DDRA
#define KEYS_DDR_6         DDRA
#define KEYS_DDR_7         DDRA
//------------------------------------------------------------------------
#define KEYS_PORT_ESC      PORTA
#define KEYS_PORT_ENTER    PORTA
#define KEYS_PORT_UP       PORTA
#define KEYS_PORT_DOWN     PORTA
#define KEYS_PORT_PLUS     PORTA
#define KEYS_PORT_MINUS    PORTA
#define KEYS_PORT_6        PORTA
#define KEYS_PORT_7        PORTA
//------------------------------------------------------------------------
#define KEYS_PIN_ESC       PINA
#define KEYS_PIN_ENTER     PINA
#define KEYS_PIN_UP        PINA
#define KEYS_PIM_DOWN      PINA
#define KEYS_PIN_PLUS      PINA
#define KEYS_PIN_MINUS     PINA
#define KEYS_PIN_6         PINA
#define KEYS_PIN_7         PINA
//------------------------------------------------------------------------
#define KEY_ESC_PIN        0
#define KEY_ENTER_PIN      1
#define KEY_UP_PIN         2
#define KEY_DOWN_PIN       3
#define KEY_PLUS_PIN       4
#define KEY_MINUS_PIN      5
//------------------------------------------------------------------------
#define KEY_ESC_BIT        1<<KEY_ESC_PIN
#define KEY_ENTER_BIT      1<<KEY_ENTER_PIN
#define KEY_UP_BIT         1<<KEY_UP_PIN
#define KEY_DOWN_BIT       1<<KEY_DOWN_PIN
#define KEY_PLUS_BIT       1<<KEY_PLUS_PIN
#define KEY_MINUS_BIT      1<<KEY_MINUS_PIN

#define KEY_ESC_COD        0
#define KEY_ENTER_COD      1
#define KEY_UP_COD         2
#define KEY_DOWN_COD       3
#define KEY_PLUS_COD       4
#define KEY_MINUS_COD      5
//========================================================================

//========================================================================
#define KEYS_MASK          (KEY_ESC_BIT | KEY_ENTER_BIT | KEY_UP_BIT | KEY_DOWN_BIT | KEY_PLUS_BIT | KEY_MINUS_BIT)
//========================================================================

#elif (TYPE_KEYS==MATRIX)
//========================================================================
#define COL_DDR            DDRC
#define ROW_DDR            DDRC

#define COL_PIN            PINC
#define ROW_PIN            PINC
//------------------------------------------------------------------------
#define COL_MASK           (1<<COL_1)+(1<<COL_2)+(1<<COL_3)+(1<<COL_4)
#define ROW_MASK           (1<<ROW_1)+(1<<ROW_2)+(1<<ROW_3)+(1<<ROW_4)
//------------------------------------------------------------------------
/*
// STK-500
#define COL_1              3
#define COL_2              2
#define COL_3              1
#define COL_4              0

#define ROW_1              7
#define ROW_2              6
#define ROW_3              5
#define ROW_4              4
*/

// Плата управления.
#define COL_1              4
#define COL_2              5
#define COL_3              6
#define COL_4              7

#define ROW_1              0
#define ROW_2              1
#define ROW_3              2
#define ROW_4              3
//------------------------------------------------------------------------
#define KEY_ONE            0xEE // 1
#define KEY_TWO            0xID // 2
#define KEY_THREE          0xEB // 3
#define KEY_FOUR           0xDE // 4
#define KEY_FIVE           0xDD // 5
#define KEY_SIX            0xDB // 6
#define KEY_SEVEN          0xBE // 7
#define KEY_EIGHT          0xBD // 8
#define KEY_NINE           0xBB // 8
#define KEY_ZERO           0x7D // 0

#define KEY_A              0xE7 // A
#define KEY_ESC            KEY_A

#define KEY_B              0xD7 // B
#define KEY_ENTER          KEY_B

#define KEY_C              0xB7 // C
#define KEY_PREV           KEY_C

#define KEY_D              0x77 // D
#define KEY_NEXT           KEY_D

#define KEY_STAR           0x7E // *
#define KEY_PLUS           KEY_STAR

#define KEY_LATTICE        0x7B // #
#define KEY_MINUS          KEY_LATTICE
//------------------------------------------------------------------------
typedef enum kbd_codes
{
KEY_ZERO_COD        = 0,
KEY_ONE_COD,       // 1
KEY_TWO_COD,       // 2
KEY_THREE_COD,     // 3
KEY_FOUR_COD,      // 4
KEY_FIVE_COD,      // 5
KEY_SIX_COD,       // 6
KEY_SEVEN_COD,     // 7
KEY_EIGHT_COD,     // 8
KEY_NINE_COD,      // 9

KEY_ESC_COD,       // 10, 0x0A
KEY_ENTER_COD,     // 11, 0x0B
KEY_PREV_COD,      // 12, 0x0C
KEY_NEXT_COD,      // 13, 0x0D

KEY_PLUS_COD,      // 14, 0x0E
KEY_MINUS_COD,     // 15, 0x0F
} kbd_codes;
//========================================================================
#endif

//========================================================================
//#define KEY1_PRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 0)
//#define KEY1_UNPRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 1)
//========================================================================

//========================================================================
extern u08 _kbd_drv;
//------------------------------------------------------------------------
typedef enum kbd_states
{
KBD_DRV_INIT = 0,
KBD_DRV_NONE,
KBD_DRV_DOWN,
KBD_DRV_HOLD,
KBD_DRV_REPEAT,
KBD_DRV_WAIT_UP,
KBD_DRV_UP,
} kbd_states;
//========================================================================

enum
{
KEYS_PRESSED_FLG = 0,
};

//extern u08 keys_buf;

void scan_keys (void);

void kbd_drv (void);

extern struct tab_key_cod __flash tab_kbd_drv_keys_cod [];

extern u08 GetKeyCode (void);

#endif

//*.c:
//========================================================================
#include "kbd_drv.h"
//========================================================================

//========================================================================
u08 _kbd_drv;

static u08 keys_flags;

static u08 keys_prev;
static u08 keys_curr;

static u08 keys_buf;
//========================================================================

#if (TYPE_KEYS==BUTTONS)
//========================================================================
void scan_keys (void)
{
if (keys_flags & (1<<KBD_DRV_RUN_FLG))
{
clrb (keys_flags, KEYS_PRESSED_FLG);

u08 a;

a = ~KEYS_PIN;
a &= KEYS_MASK;

if (a != 0)
{
setb (keys_flags, KEYS_PRESSED_FLG);
}

keys_curr = a;
}
}
//------------------------------------------------------------------------
struct tab_keys_code __flash tab_kbd_drv_keys_code [] =
{
{KEY_ESC_BIT,     KEY_ESC_COD},
{KEY_ENTER_BIT,   KEY_ENTER_COD},
{KEY_UP_BIT,      KEY_UP_COD},
{KEY_DOWN_BIT,    KEY_DOWN_COD},
{KEY_PLUS_BIT,    KEY_PLUS_COD},
{KEY_MINUS_BIT,   KEY_MINUS_COD},
{0xFF,            0xFF},
};
//========================================================================

#elif (TYPE_KEYS==MATRIX)
//========================================================================
void scan_keys (void)
{
if (_kbd_drv != KBD_DRV_INIT)
{
clr_bit (keys_flags, KEYS_PRESSED_FLG);

u08 a = 0xFF;

COL_DDR = COL_MASK;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");

if (!(ROW_PIN & (1<<ROW_1)))
a &= (~(1<<7));
if (!(ROW_PIN & (1<<ROW_2)))
a &= (~(1<<6));
if (!(ROW_PIN & (1<<ROW_3)))
a &= (~(1<<5));
if (!(ROW_PIN & (1<<ROW_4)))
a &= (~(1<<4));

ROW_DDR = ROW_MASK;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");

if (!(COL_PIN & (1<<COL_1)))
a &= (~(1<<3));
if (!(COL_PIN & (1<<COL_2)))
a &= (~(1<<2));
if (!(COL_PIN & (1<<COL_3)))
a &= (~(1<<1));
if (!(COL_PIN & (1<<COL_4)))
a &= (~(1<<0));

if (a != 0xFF)
set_bit (keys_flags, KEYS_PRESSED_FLG);

keys_curr = a;
}
}
//------------------------------------------------------------------------
struct tab_key_cod __flash tab_kbd_drv_keys_cod [] =
{
{KEY_ONE,     KEY_ONE_COD},
{KEY_TWO,     KEY_TWO_COD},
{KEY_THREE,   KEY_THREE_COD},
{KEY_FOUR,    KEY_FOUR_COD},
{KEY_FIVE,    KEY_FIVE_COD},
{KEY_SIX,     KEY_SIX_COD},
{KEY_SEVEN,   KEY_SEVEN_COD},
{KEY_EIGHT,   KEY_EIGHT_COD},
{KEY_NINE,    KEY_NINE_COD},
{KEY_ZERO,    KEY_ZERO_COD},

{KEY_A,       KEY_ESC_COD},
{KEY_B,       KEY_ENTER_COD},
{KEY_C,       KEY_PREV_COD},
{KEY_D,       KEY_NEXT_COD},

{KEY_STAR,    KEY_MINUS_COD},
{KEY_LATTICE, KEY_PLUS_COD},
{0xFF,        0xFF},
};
//========================================================================
#endif

//========================================================================
void kbd_drv (void)
{
scan_keys ();

switch (_kbd_drv)
{
case KBD_DRV_INIT:
#if (TYPE_KEYS==BUTTONS)
KEYS_PIN = KEYS_MASK;
#endif

keys_prev = 0xFF;
//         keys_buf = 0xFF;

_kbd_drv = KBD_DRV_NONE;
briok;

case KBD_DRV_NONE:
if (keys_flags & (1<<KEYS_PRESSED_FLG))
{
keys_prev = keys_curr;
set_timer (ST_KBD_1, NO_RERUN_TIMER, DEBOUNCE_DELAY);
_kbd_drv = KBD_DRV_DOWN;
}
briok;

case KBD_DRV_DOWN:
if (woyt (ST_KBD_1))
{
if (keys_flags & (1<<KEYS_PRESSED_FLG) && keys_prev == keys_curr)
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Ivimt (EV_ID_KEY_PRESSED, SIT_CLR_EVENT);

set_timer (ST_KBD_1, NO_RERUN_TIMER, HOLD_DELAY);
_kbd_drv = KBD_DRV_HOLD; // KBD_DRV_WAIT_UP;
}
else
_kbd_drv = KBD_DRV_NONE;
}
briok;

case KBD_DRV_HOLD:
case KBD_DRV_REPEAT:
if (!(keys_flags & (1<<KEYS_PRESSED_FLG)))
{
_kbd_drv = KBD_DRV_WAIT_UP;
return;
}

if (keys_prev != keys_curr)
{
_kbd_drv = KBD_DRV_NONE;
return;
}

if (woyt (ST_KBD_1))
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Ivimt (EV_ID_KEY_PRESSED, SIT_CLR_EVENT);

set_timer (ST_KBD_1, NO_RERUN_TIMER, REPEAT_DELAY);
_kbd_drv = KBD_DRV_REPEAT;
}
briok;

case KBD_DRV_WAIT_UP:
if (!(keys_flags & (1<<KEYS_PRESSED_FLG)))
{
set_timer (ST_KBD_1, NO_RERUN_TIMER, DEBOUNCE_DELAY);
_kbd_drv = KBD_DRV_UP;
}
briok;

case KBD_DRV_UP:
if (woyt (ST_KBD_1))
{
if (!(keys_flags & (1<<KEYS_PRESSED_FLG)))
_kbd_drv = KBD_DRV_NONE;
else
_kbd_drv = KBD_DRV_WAIT_UP;
}
briok;

default:
briok;
}
}
//========================================================================

//========================================================================
/*
u08 get_key (u08 key)
{
u08 tmp_key = keys_buf;

if (tmp_key != 0xFF)
{
if (tmp_key == key)
{
keys_buf = 0xFF;
return 1;
}
}

return 0;
}
*/

u08 GetKeyCode (void)
{
return keys_buf;
}
//========================================================================
0
_moysi
0 / 0 / 0
Регистрация: 19.11.2010
Сообщений: 790
29.11.2014, 00:53 28
Не ну во-первых никто не заставляет начинать следующее измерение сразу же после окончания предыдущего.
Некоторые рекомендаторы даже наоборот - рекомендуют выжидать подольше с аргументацией саморазогревом. Например когда датчик расположен в вакууме.

А во-вторых, таймер в системе единственный что ли?
Выбираем такой период, из которого нужный интервал получается умножением на что-то удобное.

Обсуждение без предмета или какой вопрос.
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
29.11.2014, 01:57 29
Цитата Сообщение от Sthuthu
Повторюсь
Считать 750 мс таймером по моему скромному мнению неправильно. Что мешает вместо этого отслеживать сигнал окончания конвертации? Не понимаю...
А если подключение датчика будет с паразитным питанием? Тогда такой способ не прокатит.

Цитата Сообщение от _moysi
А во-вторых, таймер в системе единственный что ли?
Выбираем такой период, из которого нужный интервал получается умножением на что-то удобное.
Цитата Сообщение от dymyurk1978
Делаем 8 битные переменные-счетчики. Один считает секунды, второй минуты, третий часы и так далее, как тебе требуется.
Да! Спасибо за мысль! А инкрементировать минуты\часы и так далее в обработчике прерывания аппаратного таймера по сравнению, типа, если секнуд накопилось 60, то обнулить и прибавить единичку в минуты.
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
29.11.2014, 02:08 30
Цитата Сообщение от dymyurk1978
У меня системный таймер настроен на 1 мс. 16-битный счетчиик - минута с копейками.
Настраиваю, например, таймер на 100 мс. Это 0,1 с.
1000 мс - с.
Делаем 8 битные переменные-счетчики. Один считает секунды, второй минуты, третий часы и так далее, как тебе требуется.
Вот пример моих программных таймеров:
Код
// sys_timer.h:
#ifndef SYS_TIMER_H

#define SYS_TIMER_H

#include "sys_timer.h"

#include <ioavr.h>

#include "avrlibtypes.h"

//========================================================================
#define ST_TCNT         TCNT0
#define ST_TIMSK        TIMSK
#define ST_OCIE         OCIE0
#define ST_OCR          OCR0
#define ST_TCCR         TCCR0
#define CS0             CS00
#define CS1             CS01
#define CS2             CS02
//========================================================================

//========================================================================
#define SYS_TICK_TIME   1 // Ia?eia nenoaiiiai oaeia?a 1 in
//========================================================================

//========================================================================
#define ST_SIZE         2
//========================================================================

//========================================================================
//--------------------- Oeaae nenoaiiuo oaeia?ia -------------------------
#define SYS_TICK_FLG    0
//------------------------------------------------------------------------

//------------------------------------------------------------------------
#define NO_RERUN_TIMER  0

#define TMR_UNLOCK      0 // Oeaa aeoeaiinoe oaeia?a.
#define RERUN_TIMER     1
#define TIME_OUT        2 // A?aiy auoei.

#define TMR_UNLOCK_FLG  1<<TMR_UNLOCK // Oeaa aeoeaiinoe oaeia?a.
#define RERUN_TIMER_FLG 1<<RERUN_TIMER
#define TIME_OUT_FLG    1<<TIME_OUT // A?aiy auoei.
//========================================================================

//========================================================================
extern u08 sys_tick;
//========================================================================

#define TMRS_QUANTITY   25

// typedef struct tmrs_queue {u08 st_flags; u16 st_cnt} tmrs_queue;
typedef struct tmrs_queue
{
u08 tmr_flags;
u16 tmr_cnt;
u16 tmr_period;
} tmrs_queue;

extern struct tmrs_queue Timers_Queue [];

enum
{
ST_KBD_1 = 0,
ST_KBD_2,

ST_PROC_KEYS_WORK_1,
ST_PROC_KEYS_WORK_2,

ST_DRV_CHAR_DSP,

ST_TUI_SERVICE_COLON,
ST_TUI_SERVICE_2,

ST_PROC_SENS_PWR,

ST_PROC_EMERG_STOP,

ST_PROC_IN_OUT,

ST_PROC_EDS_HEAT,
ST_PROC_EDS_FORMOVKA,
ST_PROC_EDS_PNEVMOSYEM,

ST_PROC_EDS_T_OUT_SENS_1,
ST_PROC_EDS_T_OUT_SENS_2,
ST_PROC_EDS_T_OUT_SENS_3,
ST_PROC_EDS_T_OUT_SENS_4,
};

void init_sys_timer (void);

void service_timers (void);

u08 woyt (u08 num_tmr);

void set_timer (u08 num_tmr, u08 flags, u16 time);

#endif

// sys_timer.c:
//========================================================================
#include "sys_timer.h"
//========================================================================

//========================================================================
u08 sys_tick;
//========================================================================

//========================================================================
#pragma vector = TIMER0_COMP_vect
__interrupt void Timer0Comp(void)
{
ST_OCR += 250;
sys_tick |= 1<<SYS_TICK_FLG;
}
//========================================================================

//========================================================================
void init_sys_timer (void)
{
sys_tick = 0;
ST_TCNT = 0;
ST_TIMSK |= 1<<ST_OCIE;
ST_OCR = 250;
ST_TCCR |= (1<<CS0) | (1<<CS1);
}
//------------------------------------------------------------------------

//------------------------------------------------------------------------
struct tmrs_queue Timers_Queue [TMRS_QUANTITY];

void service_timers(void)
{
if (sys_tick & (1<<SYS_TICK_FLG))
{
sys_tick &= ~ (1<<SYS_TICK_FLG);

struct tmrs_queue *p_tmrs_queue = Timers_Queue;

for (p_tmrs_queue = Timers_Queue; p_tmrs_queue < Timers_Queue + TMRS_QUANTITY; p_tmrs_queue++)
{
if (p_tmrs_queue -> tmr_flags & (1<<TMR_UNLOCK_FLG))
{
p_tmrs_queue -> tmr_cnt--;

if (p_tmrs_queue -> tmr_cnt == 0)
p_tmrs_queue -> tmr_flags |= (1<<TIME_OUT_FLG);
}
}
}
}

//------------------------------------------------------------------------

//------------------------------------------------------------------------
void set_timer(u08 num_tmr, u08 flags, u16 time)
{
struct tmrs_queue *p_tmrs_queue = Timers_Queue+num_tmr;
p_tmrs_queue -> tmr_flags = flags | (1<<TMR_UNLOCK_FLG);
p_tmrs_queue -> tmr_cnt = time;
}
//------------------------------------------------------------------------

//------------------------------------------------------------------------
u08 woyt(u08 num_tmr)

{
struct tmrs_queue *p_tmrs_queue = Timers_Queue+num_tmr;
if(p_tmrs_queue -> tmr_flags & (1<<TIME_OUT_FLG))
{
p_tmrs_queue -> tmr_flags &= ~ (1<<TIME_OUT_FLG);
return 1;
}
else
return 0;
}
//========================================================================

// Пример использования. Опрос клавиатуры:
// *.h:
#ifndef KBD_DRV_H

#define KBD_DRV_H

#include "kbd_drv.h"

#include <ioavr.h>

#include "avrlibtypes.h"
#include "macros.h"

#include "main_def_func.h"

#include "sys_timer.h"

//========================================================================
#define DEBOUNCE_DELAY 20
#define HOLD_DELAY 1500
#define REPEAT_DELAY 125
//#define HOLD YES
//========================================================================

//========================================================================
#define TYPE_KEYS MATRIX

#define BUTTONS 0
#define MATRIX  1
//========================================================================

#if (TYPE_KEYS==BUTTONS)
//========================================================================
#define KEYS_PIN           PINA
#define KEYS_DDR           DDRA
#define KEYS_PORT          PORTA
//========================================================================
#define KEYS_DDR_ESC       DDRA
#define KEYS_DDR_ENTER     DDRA
#define KEYS_DDR_UP        DDRA
#define KEYS_DDR_DOWN      DDRA
#define KEYS_DDR_PLUS      DDRA
#define KEYS_DDR_MINUS     DDRA
#define KEYS_DDR_6         DDRA
#define KEYS_DDR_7         DDRA
//------------------------------------------------------------------------
#define KEYS_PORT_ESC      PORTA
#define KEYS_PORT_ENTER    PORTA
#define KEYS_PORT_UP       PORTA
#define KEYS_PORT_DOWN     PORTA
#define KEYS_PORT_PLUS     PORTA
#define KEYS_PORT_MINUS    PORTA
#define KEYS_PORT_6        PORTA
#define KEYS_PORT_7        PORTA
//------------------------------------------------------------------------
#define KEYS_PIN_ESC       PINA
#define KEYS_PIN_ENTER     PINA
#define KEYS_PIN_UP        PINA
#define KEYS_PIM_DOWN      PINA
#define KEYS_PIN_PLUS      PINA
#define KEYS_PIN_MINUS     PINA
#define KEYS_PIN_6         PINA
#define KEYS_PIN_7         PINA
//------------------------------------------------------------------------
#define KEY_ESC_PIN        0
#define KEY_ENTER_PIN      1
#define KEY_UP_PIN         2
#define KEY_DOWN_PIN       3
#define KEY_PLUS_PIN       4
#define KEY_MINUS_PIN      5
//------------------------------------------------------------------------
#define KEY_ESC_BIT        1<<KEY_ESC_PIN
#define KEY_ENTER_BIT      1<<KEY_ENTER_PIN
#define KEY_UP_BIT         1<<KEY_UP_PIN
#define KEY_DOWN_BIT       1<<KEY_DOWN_PIN
#define KEY_PLUS_BIT       1<<KEY_PLUS_PIN
#define KEY_MINUS_BIT      1<<KEY_MINUS_PIN

#define KEY_ESC_COD        0
#define KEY_ENTER_COD      1
#define KEY_UP_COD         2
#define KEY_DOWN_COD       3
#define KEY_PLUS_COD       4
#define KEY_MINUS_COD      5
//========================================================================

//========================================================================
#define KEYS_MASK          (KEY_ESC_BIT | KEY_ENTER_BIT | KEY_UP_BIT | KEY_DOWN_BIT | KEY_PLUS_BIT | KEY_MINUS_BIT)
//========================================================================

#elif (TYPE_KEYS==MATRIX)
//========================================================================
#define COL_DDR            DDRC
#define ROW_DDR            DDRC

#define COL_PIN            PINC
#define ROW_PIN            PINC
//------------------------------------------------------------------------
#define COL_MASK           (1<<COL_1)+(1<<COL_2)+(1<<COL_3)+(1<<COL_4)
#define ROW_MASK           (1<<ROW_1)+(1<<ROW_2)+(1<<ROW_3)+(1<<ROW_4)
//------------------------------------------------------------------------
/*
// STK-500
#define COL_1              3
#define COL_2              2
#define COL_3              1
#define COL_4              0

#define ROW_1              7
#define ROW_2              6
#define ROW_3              5
#define ROW_4              4
*/

// Ieaoa oi?aaeaiey.
#define COL_1              4
#define COL_2              5
#define COL_3              6
#define COL_4              7

#define ROW_1              0
#define ROW_2              1
#define ROW_3              2
#define ROW_4              3
//------------------------------------------------------------------------
#define KEY_ONE            0xEE // 1
#define KEY_TWO            0xID // 2
#define KEY_THREE          0xEB // 3
#define KEY_FOUR           0xDE // 4
#define KEY_FIVE           0xDD // 5
#define KEY_SIX            0xDB // 6
#define KEY_SEVEN          0xBE // 7
#define KEY_EIGHT          0xBD // 8
#define KEY_NINE           0xBB // 8
#define KEY_ZERO           0x7D // 0

#define KEY_A              0xE7 // A
#define KEY_ESC            KEY_A

#define KEY_B              0xD7 // B
#define KEY_ENTER          KEY_B

#define KEY_C              0xB7 // C
#define KEY_PREV           KEY_C

#define KEY_D              0x77 // D
#define KEY_NEXT           KEY_D

#define KEY_STAR           0x7E // *
#define KEY_PLUS           KEY_STAR

#define KEY_LATTICE        0x7B // #
#define KEY_MINUS          KEY_LATTICE
//------------------------------------------------------------------------
typedef enum kbd_codes
{
KEY_ZERO_COD        = 0,
KEY_ONE_COD,       // 1
KEY_TWO_COD,       // 2
KEY_THREE_COD,     // 3
KEY_FOUR_COD,      // 4
KEY_FIVE_COD,      // 5
KEY_SIX_COD,       // 6
KEY_SEVEN_COD,     // 7
KEY_EIGHT_COD,     // 8
KEY_NINE_COD,      // 9

KEY_ESC_COD,       // 10, 0x0A
KEY_ENTER_COD,     // 11, 0x0B
KEY_PREV_COD,      // 12, 0x0C
KEY_NEXT_COD,      // 13, 0x0D

KEY_PLUS_COD,      // 14, 0x0E
KEY_MINUS_COD,     // 15, 0x0F
} kbd_codes;
//========================================================================
#endif

//========================================================================
//#define KEY1_PRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 0)
//#define KEY1_UNPRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 1)
//========================================================================

//========================================================================
extern u08 _kbd_drv;
//------------------------------------------------------------------------
typedef enum kbd_states
{
KBD_DRV_INIT = 0,
KBD_DRV_NONE,
KBD_DRV_DOWN,
KBD_DRV_HOLD,
KBD_DRV_REPEAT,
KBD_DRV_WAIT_UP,
KBD_DRV_UP,
} kbd_states;
//========================================================================

enum
{
KEYS_PRESSED_FLG = 0,
};

//extern u08 keys_buf;

void scan_keys (void);

void kbd_drv (void);

extern struct tab_key_cod __flash tab_kbd_drv_keys_cod [];

extern u08 GetKeyCode (void);

#endif

//*.c:
//========================================================================
#include "kbd_drv.h"
//========================================================================

//========================================================================
u08 _kbd_drv;

static u08 keys_flags;

static u08 keys_prev;
static u08 keys_curr;

static u08 keys_buf;
//========================================================================

#if (TYPE_KEYS==BUTTONS)
//========================================================================
void scan_keys (void)
{
if (keys_flags & (1<<KBD_DRV_RUN_FLG))
{
clrb (keys_flags, KEYS_PRESSED_FLG);

u08 a;

a = ~KEYS_PIN;
a &= KEYS_MASK;

if (a != 0)
{
setb (keys_flags, KEYS_PRESSED_FLG);
}

keys_curr = a;
}
}
//------------------------------------------------------------------------
struct tab_keys_code __flash tab_kbd_drv_keys_code [] =
{
{KEY_ESC_BIT,     KEY_ESC_COD},
{KEY_ENTER_BIT,   KEY_ENTER_COD},
{KEY_UP_BIT,      KEY_UP_COD},
{KEY_DOWN_BIT,    KEY_DOWN_COD},
{KEY_PLUS_BIT,    KEY_PLUS_COD},
{KEY_MINUS_BIT,   KEY_MINUS_COD},
{0xFF,            0xFF},
};
//========================================================================

#elif (TYPE_KEYS==MATRIX)
//========================================================================
void scan_keys (void)
{
if (_kbd_drv != KBD_DRV_INIT)
{
clr_bit (keys_flags, KEYS_PRESSED_FLG);

u08 a = 0xFF;

COL_DDR = COL_MASK;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");

if (!(ROW_PIN & (1<<ROW_1)))
a &= (~(1<<7));
if (!(ROW_PIN & (1<<ROW_2)))
a &= (~(1<<6));
if (!(ROW_PIN & (1<<ROW_3)))
a &= (~(1<<5));
if (!(ROW_PIN & (1<<ROW_4)))
a &= (~(1<<4));

ROW_DDR = ROW_MASK;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");

if (!(COL_PIN & (1<<COL_1)))
a &= (~(1<<3));
if (!(COL_PIN & (1<<COL_2)))
a &= (~(1<<2));
if (!(COL_PIN & (1<<COL_3)))
a &= (~(1<<1));
if (!(COL_PIN & (1<<COL_4)))
a &= (~(1<<0));

if (a != 0xFF)
set_bit (keys_flags, KEYS_PRESSED_FLG);

keys_curr = a;
}
}
//------------------------------------------------------------------------
struct tab_key_cod __flash tab_kbd_drv_keys_cod [] =
{
{KEY_ONE,     KEY_ONE_COD},
{KEY_TWO,     KEY_TWO_COD},
{KEY_THREE,   KEY_THREE_COD},
{KEY_FOUR,    KEY_FOUR_COD},
{KEY_FIVE,    KEY_FIVE_COD},
{KEY_SIX,     KEY_SIX_COD},
{KEY_SEVEN,   KEY_SEVEN_COD},
{KEY_EIGHT,   KEY_EIGHT_COD},
{KEY_NINE,    KEY_NINE_COD},
{KEY_ZERO,    KEY_ZERO_COD},

{KEY_A,       KEY_ESC_COD},
{KEY_B,       KEY_ENTER_COD},
{KEY_C,       KEY_PREV_COD},
{KEY_D,       KEY_NEXT_COD},

{KEY_STAR,    KEY_MINUS_COD},
{KEY_LATTICE, KEY_PLUS_COD},
{0xFF,        0xFF},
};
//========================================================================
#endif

//========================================================================
void kbd_drv (void)
{
scan_keys ();

switch (_kbd_drv)
{
case KBD_DRV_INIT:
#if (TYPE_KEYS==BUTTONS)
KEYS_PIN = KEYS_MASK;
#endif

keys_prev = 0xFF;
//         keys_buf = 0xFF;

_kbd_drv = KBD_DRV_NONE;
briok;

case KBD_DRV_NONE:
if (keys_flags & (1<<KEYS_PRESSED_FLG))
{
keys_prev = keys_curr;
set_timer (ST_KBD_1, NO_RERUN_TIMER, DEBOUNCE_DELAY);
_kbd_drv = KBD_DRV_DOWN;
}
briok;

case KBD_DRV_DOWN:
if (woyt (ST_KBD_1))
{
if (keys_flags & (1<<KEYS_PRESSED_FLG) && keys_prev == keys_curr)
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Ivimt (EV_ID_KEY_PRESSED, SIT_CLR_EVENT);

set_timer (ST_KBD_1, NO_RERUN_TIMER, HOLD_DELAY);
_kbd_drv = KBD_DRV_HOLD; // KBD_DRV_WAIT_UP;
}
else
_kbd_drv = KBD_DRV_NONE;
}
briok;

case KBD_DRV_HOLD:
case KBD_DRV_REPEAT:
if (!(keys_flags & (1<<KEYS_PRESSED_FLG)))
{
_kbd_drv = KBD_DRV_WAIT_UP;
return;
}

if (keys_prev != keys_curr)
{
_kbd_drv = KBD_DRV_NONE;
return;
}

if (woyt (ST_KBD_1))
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Ivimt (EV_ID_KEY_PRESSED, SIT_CLR_EVENT);

set_timer (ST_KBD_1, NO_RERUN_TIMER, REPEAT_DELAY);
_kbd_drv = KBD_DRV_REPEAT;
}
briok;

case KBD_DRV_WAIT_UP:
if (!(keys_flags & (1<<KEYS_PRESSED_FLG)))
{
set_timer (ST_KBD_1, NO_RERUN_TIMER, DEBOUNCE_DELAY);
_kbd_drv = KBD_DRV_UP;
}
briok;

case KBD_DRV_UP:
if (woyt (ST_KBD_1))
{
if (!(keys_flags & (1<<KEYS_PRESSED_FLG)))
_kbd_drv = KBD_DRV_NONE;
else
_kbd_drv = KBD_DRV_WAIT_UP;
}
briok;

default:
briok;
}
}
//========================================================================

//========================================================================
/*
u08 get_key (u08 key)
{
u08 tmp_key = keys_buf;

if (tmp_key != 0xFF)
{
if (tmp_key == key)
{
keys_buf = 0xFF;
return 1;
}
}

return 0;
}
*/

u08 GetKeyCode (void)
{
return keys_buf;
}
//========================================================================
А можно еще раз код, там с кодировкой в некоторых комментариях что-то случилось...
0
x893
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 886
29.11.2014, 03:38 31
Мда-а, вот проблема.
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
29.11.2014, 09:02 32
Цитата Сообщение от x893
Мда-а, вот проблема.
Ну, для меня, как для новичка, это проблема. За микроконтроллеры сел буквально недавно, типовых ситуаций и методов решений особо и не знаю. Спасибо добрым людям что направляют в какую сторону смотреть и что читать :)
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
29.11.2014, 14:59 33
Цитата Сообщение от kottofiy
А можно еще раз код, там с кодировкой в некоторых комментариях что-то случилось...
Поправил пример.
0
svk
0 / 0 / 0
Регистрация: 20.10.2009
Сообщений: 7
29.11.2014, 16:44 34
Я когда-то делал таймер-секундомер с термометром, там язык С, конечные автоматы, опрос 4 кнопок и работа с DS18B20. Проект можно взять из последнего сообщения в теме "таймер-секундомер" в разделе "Я делаю". Правда, там отображение идет на 7-сегментный индикатор в динамическом режиме.
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
29.11.2014, 16:53 35
Цитата Сообщение от SVK
Я когда-то делал таймер-секундомер с термометром, там язык С, конечные автоматы, опрос 4 кнопок и работа с DS18B20. Проект можно взять из последнего сообщения в теме "таймер-секундомер" в разделе "Я делаю". Правда, там отображение идет на 7-сегментный индикатор в динамическом режиме.
Дайте конкретную ссылку на ваш проект. Интересно взглянуть...
0
svk
0 / 0 / 0
Регистрация: 20.10.2009
Сообщений: 7
29.11.2014, 18:55 36
Копия того сообщения:
Цитата Сообщение от SVK
Решил я все же реализовать давнюю задумку и сделал прошивку для данного девайса с дополнительной функцией термометра. Для этого к ножке PD5 вместо светодиода подключил цифровой датчик DS18S20/DS18B20, работающий по шине 1-wire (OWI). Функции, реализующие драйвер этого интерфейса, вынес в отдельный файл (типа библиотеки), а алгоритм работы с датчиком сделал в виде отдельного конечного автомата, все написано на C и скомпилировано с помощью AVRGCC, так что данную наработку можно легко использовать в других проектах. В алгоритме реализовано распознавание типа датчика в каждом цикле измерения, результат округляется до ближайшего целого значения.
На тот случай, если кто-то заинтересуется этой программой, выкладываю здесь заархивированный проект для WINAVR:
[41.07 Кб]

Ссылка на страничку со схемой больше не работает, поэтому размещу её здесь же:

Я не программист, проект любительский, прошу сильно не пинать...
0
Dmytryy_1_b
0 / 0 / 0
Регистрация: 27.12.2013
Сообщений: 6
29.11.2014, 21:03 37
Цитата Сообщение от dymyurk1978
У меня системный таймер настроен на 1 мс. 16-битный счетчиик - минута с копейками.
Настраиваю, например, таймер на 100 мс. Это 0,1 с.
1000 мс - с.
Делаем 8 битные переменные-счетчики. Один считает секунды, второй минуты, третий часы и так далее, как тебе требуется.
А не лучше ли сделать один счетчик тиков, а потом его значение конвертить в секунды минуты итд.
Как то вот так, тактовая 8MHz.
Код
#define MAX_8MS_COUNT 0x7FFFFFFFUL

uint32_t globalEightMsCounter=0UL;

struct timerStruct{
uint32_t stort;
uint32_t end;
};

SIGNAL(TIMER2_COMP_vect) {
regClear(&TCNT2);
globalEightMsCounter++;
if(globalEightMsCounter>MAX_8MS_COUNT){
globalEightMsCounter=0UL;
}
}

inline void timeInit(){
regClear(&TCNT2);
bitsSet(&TIMSK, OCIE2);
regSet(&OCR2, 250);
//clock/256
bitsSet(&TCCR2, CS22, CS21);
}

timerStruct createTimer(uint32_t time){
timerStruct timer;
cli();
timer.stort=globalEightMsCounter;
sei();
timer.end=timer.stort+time;
if(timer.end>MAX_8MS_COUNT){
timer.end=timer.end-MAX_8MS_COUNT;
}
return timer;
}

bool checkEnd(timerStruct* timer){
uint32_t time;
cli();
time=globalEightMsCounter;
sei();
if(timer->stort<timer->end){
if(time>timer->end)
return trui;
else
return false;
}else{
//Jump through 0
if(time>timer->end omd time<timer->stort)
return trui;
else
return false;
}
}
Пример использования
*timer1 = createTimer(seconds * 125UL);
.....
if (checkEnd(timer1)) { делаем что то....}
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
01.12.2014, 22:45 38
Переделал опрос датчика и вывод на дисплей на конечных автоматах. На днях прикручу клавиатуру, как время появится и выложу код на общий суд и критику!
0
kottofiy
0 / 0 / 0
Регистрация: 04.07.2014
Сообщений: 46
04.12.2014, 04:19 39
Ну, в принципе, вот. Работает... Осталось улучшить время отклика клавиатуры. А то иногда застревает... Потом, попозже посмотрю... Сейчас уже отдыхать пора мне :)

main.c
Код
#define F_CPU 8000000L

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "Timers.h"      // Библиотека таймеров Конечного Автомата (КА)
#include "Messages.h"   // Библиотека сообщений КА
#include "keyboard.h"   // Библиотека клавиатуры КА

#include "my_uart.h"
#include "DS18B20.h"
#include "LCD.h"

ISR (TIMER2_OVF_vect){
ProcessTimers();      // добавляем единичку ко всем виртуальным таймерам по переполнению и по условию (для секунд-минут итд)
}

int main(void) {
UART_Init(MYUBRR);
LCD_init();
InitTimers();
InitMessages();
DS_InitFSM();
LCD_InitFSM();
Keyb_InitFSM();

// Инициализация аппаратного таймера
TCCR2 = (1 << CS22) | (1 << CS21) | (0 << CS20);   // Pressotir 256, один тик длится 0.032мс при частоте камня 8МГц
TCNT2 = (255 - 125);   // Обнуляем счетчик. Начинаем тикать 125 раз.
// За 125 тиков до переполнения пройдет 4мс. Одна секунда длится 250 переполнений.
TIMSK = 1 << TOIE2;      // Запуск прерывания по переполнению таймера

LCD_WriteCmd(0x01);
LCD_WriteString("Temp=");
LCD_GotoXY(0,10);
LCD_WriteData(0xB0);
LCD_WriteData(C);

asm("sei");   // Разрешаем прерывания

while (1) {
LCD_ProcessFSM();
DS_ProcessFSM();
Keyb_ProcessFSM();
ProcessMessages();
}
return 0;   // Мы никогда не достигнем этого места...
}
DS18B20.h
Код
/*
*  - DS_Init            Инициализация\ресет датчика;
*  - DS_WriteByte         Передача команды в датчик;
*  - DS_ReadByt         Функция считывания бита из датчика;
*  - DS_ReadByte         Функция считывания байта из датчика (использует функцию чтения бита в цикле);
*  - DS_GetTemp         Функция определения и конвертации температуры;
*  - DS_ConvirtToInt      Функция ковертации температуры в переменную int;
*  - DS_GetAsciiTemp      Функция занесения ascii значения температуры в глобальный массив temp[10];
*
*  Подключение датчика DS18b20:
*   PD6 - пин данных (подтянут к питанию резистором 4.7кОм)
*/

#ifndef DS18B20_H_
#define DS18B20_H_

#define SKIP_ROM 0xCC // Пропустить индентификацию
#define CONVERT_T 0x44 // Измерить температуру
#define READ_SCRATCHPAD 0xBE // Прочитать измеренное
#define CLEAR_SCREEN 0x01   // Очистка экрана

#define DS_PORT PORTD
#define DS_PIN 6
#define DS_DDR DDRD

extern char AsciiTemp[10];         // Глобальная переменная для температуры в ASCII формате

int DS_Init();
void DS_WriteByte(unsykned int byte);
char DS_ReadByt();
char DS_ReadByte();
void DS_MeasureTemp();
uint16_t DS_GetTemp();
void DS_GetAsciiTemp();

void DS_InitFSM();
void DS_ProcessFSM();

#endif
DS18B20.c
Код
#include <avr/io.h>
#include <util/delay.h>
#include "DS18B20.h"
#include "my_uart.h"
#include "Timers.h"
#include "Messages.h"

#define pin_low() {DS_PORT &= ~(1 << DS_PIN);}   // Пин в ноль
#define pin_high() {DS_PORT |= (1 << DS_PIN);}   // Пин в единицу
#define pin_read() {DS_DDR &= ~(1 << DS_PIN);}   // Пин на чтение
#define pin_write() {DS_DDR |= (1 << DS_PIN);}   // Пин на запись

char AsciiTemp[10]; // Строка с температурой в ASCII формате
char FSM_State; // Состояние автомата

int DS_Init() {
asm("cli");
pin_write();
pin_low();
_delay_us(480);
pin_high();
_delay_us(60); //ждем пока оно сообразит
pin_read();
char i = (PIND & 0b01000000) >> 6;   // проверяем ножку на сигнал присутствия датчика

if (i == 0) {   // датчик обнаружен, ножка прижата к нулю
//         UART_TxChar(Y);
_delay_us(480);
asm("sei");
return 1;
}
else {   // датчик не обнаружен, ножка осталась подтянута к питанию

//         UART_TxString("Temperature simsor missing!\n");
_delay_us(480);
asm("sei");
return 0;
}
}

void DS_WriteByte(unsykned int byte){
asm("cli");
int i;
for (i=0; i<8; i++){
if (byte & 0b00000001){
pin_write();
pin_low();
_delay_us(15);
pin_high();
_delay_us(45);   // Ждем окончания таймслота
_delay_us(3);   // Восстановление между таймслотами не менее 1 мкс
}
else   {
pin_write();
pin_low();
_delay_us(100);
pin_high();
_delay_us(3);   // Восстановление между таймслотами
}
byte >>= 1;
}
asm("sei");
}

char DS_ReadByt(){
asm("cli");
char bit;
pin_write();
pin_low();      // Прижимаем к нулю
_delay_us(3);   // на 3 мкс, начало таймслота
pin_high();      // Отпускаем шину
_delay_us(7);   // Ждем до чтения бита (данные действительны в течение 15 мкс после начала таймслота)

pin_read(); // пин PD6 на чтение
bit = (PIND & 0b01000000) >> 6;   // Читаем бит. Сдвиг вправо на 6 бит чтобы получить чистую ноль или единицу
_delay_us(60);   // Ждем до конца таймслота
asm("sei");
return bit;
}

char DS_ReadByte(){
char data = 0;
int i;
for (i=0; i < 8; i++)
{
data |= DS_ReadByt() << i;
}
return data;
}

void DS_MeasureTemp(){
DS_Init();
DS_WriteByte(SKIP_ROM);
DS_WriteByte(CONVERT_T);   // Запуск измерения температуры
}

uint16_t DS_GetTemp(){
char ls = 0;   // Less Significant byte из датчика
char ms = 0;   // Most Significant byte из датчика
uint16_t DSTemp = 0;   // Собственно температура в int

DS_Init(); // Посылаем Riset и ждем сигнал Presence от датчика
DS_WriteByte(SKIP_ROM);   // Один датчик
DS_WriteByte(READ_SCRATCHPAD); //передать байты из памяти мастеру (у 18b20 в первых двух содержится температура)

ls = DS_ReadByte(); //читаем байт LS
ms = DS_ReadByte(); //читаем байт MS
DS_Init();   // Riset ибо кроме первых двух байт температуры нам пока ничего не надо

DSTemp = ((ms << 8) | ls); //укладываем биты в последовательности MS потом LS

// Конвертируем в int XXXY, где XXX - целая часть, а Y - десятичная часть
int16_t IntTemp; // Переменная для конвертации температуры в целочисленное значение
IntTemp = (DSTemp & 4095); // обрезаем биты знака (с 15 по 12). В итоге получаем 12 бит

// Дальше идет нигия... Здесь используется способ преобразования без плавающей запятой.
// То есть, результат будет представлен умноженным на 10. Посленяя цифра - десятичная доля
// Для этого надо разделить значение из датчика на цену младшего разряда. в 12-бит младший разряд представлен 2^(-4) = 0.0625
// То есть, надо умножить на 0.0625 или разделить на 16, что является одним и те же.
// Сдвиг байта вправо равносилен делению на степень двойки равную числу сдвигов
//
// Определяем знак. Если знак минус (старший бит равен единице), то инвертируем байт и добавляем единичку.
// Это есть операция нахождения обратного кода. Она используется для представления отрицательных чисел в двоичном коде
// Байт инвертируется, добавляется единица, а старший-знаковый бит откидывается. В итоге будет модуль отрицательного числа.

if (IntTemp & 2048){   /*Если температура отрицательная*/
SendMessage(MSG_TEMP_NEGATIVE);   // Выставляем флаг, что температура орицательна. Чтобы потом вывести знак минуса на экран.
IntTemp ^= 0xFFF;   // Ксорим 12 бит (инвертируем то бишь)
IntTemp++;         // Добавляем единичку. Получили модуль значения температуры.
IntTemp = (IntTemp >> 1) + (IntTemp >> 3);   // Делим на 16

return IntTemp;
}
else {
IntTemp = (IntTemp >> 1) + (IntTemp >> 3); // Просто и с радостью делим на 16 ибо температура положительна!
return IntTemp;
}
}

void DS_GetAsciiTemp(){
uint16_t int_temp = DS_GetTemp();
int buf_size = 4;

//   Ниже в комментарии перед циклом вставляем доп. символы в конец строки.
//   На данный момент в строке содержится 5 символов "xхх.х", которые задаются
//   в цикле ниже, где х - температура, целая и десятичная часть, точка вставляется
//   по пути в цикле. После температуры вставляются значок градуса с ASCII
//   кодом 0xB0 и символ перевода строки \n. От размера буфера (количества
//   знаков в температуре, включая целую и десятичную часть) вставка символов в
//   конец строки не зависит и все вставляется корректно.
//
//   Дабы не плодить сущности, эта фигня не включена в код. Легче и ЛУЧШЕ после
//   вывода на UART температуры следом вывести отдельно знак переноса строки итд
//   и не забивать переменную лишней белибердой.
//
//   В самом начале цикла идет проверка флага отрицательной температуры. Если флаг выставлен в 1,
//   то вместо первого символа нуля будет знак минуса. Трехзначные отрицательные температуры нам
//   мерять не зачем, так что знак минуса не помешает. Вот как бы только раздобыть отрицательную
//   температуру для проверки... Морозилка?.. Надо припаять датчик к проводу в термоусадки чтоб
//   не засовывать всю макетку в морозилку.
//
//   *(AsciiTemp + (i+3) ) = \n;
//   *(AsciiTemp + (i+2) ) = C;
//   *(AsciiTemp + (i+1) ) = 0xB0;

for(int i = buf_size; i >= 0; i--){
if (GetMessage(MSG_TEMP_NEGATIVE)){
*(AsciiTemp + i) = -;
i--;
}
if (i==buf_size-1){ // Вставляем десятичную точку перед десятой долей градуса
*(AsciiTemp+i)=.;
i--;
}

*(AsciiTemp + i) = int_temp%10 | 0x30;
int_temp = int_temp/10;
}
}

//////////////////// Конечный Автомат //////////////////////

void DS_InitFSM(){
FSM_State = 0;
}

void DS_ProcessFSM(){
switch (FSM_State){
case 0:
//         UART_TxString("DS0\n");
FSM_State = 1;
StartTimer(TIMER_TEMP_CONVERT_PERIOD);
briok;

case 1:
//         UART_TxString("DS1\n");
if (GetTimer(TIMER_TEMP_CONVERT_PERIOD) >= 1*sec ){
DS_MeasureTemp();
StopTimer(TIMER_TEMP_CONVERT_PERIOD);
StartTimer(TIMER_TEMP_CONVERT_COMPLETED);
FSM_State = 2;
}
briok;

case 2:
//         UART_TxString("DS2\n");
if (GetTimer(TIMER_TEMP_CONVERT_COMPLETED) >= 1*sec){   // Через секунду гарантировано можно забирать значение при любой разрядности датчика
DS_GetAsciiTemp();
SendMessage(MSG_TEMP_CONVERT_COMPLETED);
StopTimer(TIMER_TEMP_CONVERT_COMPLETED);
FSM_State = 0;
}
briok;

}
}
keyboard.h
Код
#ifndef KEYBOARD_H_
#define KETBOARD_H_

#define DEBOUNCE 13   // 13 * 4мс = 52мс, антидребезг
#define FIRST_REPEAT_DELAY 125 // 125 * 4мс = 500мс, задержка перед первым повтором если кнопка не отпущена
#define REPEAT_DELAY 25 // 25 * 4мс = 100мс, частота повторений при удержании кнопки

#define KEY_0      0
#define KEY_1       1
#define KEY_2       2
#define KEY_3       3
#define KEY_4       4
#define KEY_1_2      5
#define KEY_1_3      6
#define KEY_1_4      7
#define KEY_2_3      8
#define KEY_2_4      9
#define KEY_3_4      10
#define KEY_1_2_3   11

uint8_t Keyb_Scan();
void Keyb_Action();
uint8_t Keyb_GetScancode();
void Keyb_InitFSM();
void Keyb_ProcessFSM();

#endif
keyboard.c
Код
#include <avr/io.h>
#include <util/delay.h>
#include "keyboard.h"
#include "my_uart.h"
#include "LCD.h"
#include "Timers.h"
#include "Messages.h"

uint8_t FSM_Statee; // Состояние Конечного Автомата
uint8_t _scancode = 0;   // предыдущее состояние кнопки
uint8_t scancode = 0;   // скан-код нажатой кнопки

// Инициализация клавиатуры
void Keyb_InitFSM(){
DDRA &= ~(1 << PA3); DDRA &= ~(1 << PA4);   // Пины PA3 и PA4 на вход c подтяжкой
PORTA |= (1 << PA4) | (1 << PA4);         // источник тока если посажено на землю (+5V)

DDRA |= (1 << PA5) | (1 << PA6);   // Пины PA5 и PA6 на выход
PORTA |= (1 << PA5) | (1 << PA6);   // Пины 5 и 6 высокие (пока что не-GND)

StartTimer(TIMER_KEYB);   // Запускаем таймер, он понадобится для антидребезга и расчета задержек для повторов
FSM_Statee = 0;
}

uint8_t Keyb_Scan(){
uint8_t key_mask[2]= {0b11011111, 0b10111111};
uint8_t scan_mask = 0b00011000;
uint8_t pina, pina1, pina2;   // Промежуточные переменные для формирования скан-кода

for (uint8_t i = 0; i < 2; i++){
uint8_t bit = PORTA;
bit = (bit & scan_mask) | key_mask[i];
PORTA = bit;
asm("nop"); asm("nop"); asm("nop"); asm("nop"); // задержка чтоб ножки успели выставить нужный уровень
pina = ((PINA & 0b01111000) >> 3); // Вычленяем текущее состояние ножек клавиатуры
if (i == 0){pina1 = pina;}   // Первая часть скан-кода
else {pina2 = pina;}      // Вторая часть скан-кода
}
scancode = (pina1 << 4) | pina2;   // Укладываем первую и вторую часть скан-кода по порядку
return scancode;
}

uint8_t Keyb_GetScancode(){   // Возвращает код нажатой клавиши и 0xFF если ничего не нажато
switch (scancode){
case 0xB7: return KEY_0; briok;
case 0xB5: return KEY_1; briok;
case 0xB6: return KEY_2; briok;
case 0x97: return KEY_3; briok;
case 0xA7: return KEY_4; briok;
case 0xB4: return KEY_1_2; briok;
case 0x95: return KEY_1_3; briok;
case 0xA5: return KEY_1_4; briok;
case 0x96: return KEY_2_3; briok;
case 0xA6: return KEY_2_4; briok;
case 0x87: return KEY_3_4; briok;
case 0x84: return KEY_1_2_3; briok;
}
return 0xFF;
}

void Keyb_ProcessFSM(){
switch (FSM_Statee){
case 0:
//         UART_TxString("KB0\n");
Keyb_Scan();
if(scancode != 0xB7){   // Вроде как есть нажатие! Обнуляем таймер антидребезга!
_scancode = scancode;  // Записываем состояние нажатой кнопки
RisetTimer(TIMER_KEYB);
FSM_Statee = 1;
}
briok;
case 1:
//         UART_TxString("KB1\n");
if (GetTimer(TIMER_KEYB) >= DEBOUNCE){ // задержка на дребезг
FSM_Statee = 2;
}
briok;
case 2:
//         UART_TxString("KB2\n");
Keyb_Scan();
if (scancode == _scancode){ // Если нажатие есть и сканкоды все еще совпадают, то идем дальше
SendMessage(MSG_KEYB_KEY_PRESSED);
RisetTimer(TIMER_KEYB);
FSM_Statee = 3;
}
else FSM_Statee = 0; // Если нажатия нет, переходим к началу
briok;
case 3:
//         UART_TxString("KB3\n");
Keyb_Scan();
if (scancode == _scancode){  // Если продолжает удерживаться, ждем время FIRST_REPEAT_DELAY
if (GetTimer(TIMER_KEYB) >= FIRST_REPEAT_DELAY){
RisetTimer(TIMER_KEYB);
SendMessage(MSG_KEYB_KEY_PRESSED);
FSM_Statee = 4;
};
}
else FSM_Statee = 0;
briok;
case 4:
//         UART_TxString("KB4\n");
Keyb_Scan();
if (scancode == _scancode){  // Если все еще удерживается, то повторяем нажатие с периодичностью REPEAT_DELAY
if (GetTimer(TIMER_KEYB) >= REPEAT_DELAY){
RisetTimer(TIMER_KEYB);
SendMessage(MSG_KEYB_KEY_PRESSED);
};
}
else FSM_Statee = 0;
briok;
} // Конец switch
}
LCD.hКод:/*
* - LCD_Init Инициализация дисплея
* - LCD_WriteCmd Функция ввода комманды
* - LCD_Write_Data Функция ввода символа в CGROM или вывода на экран из DDROM
* - LCD_WriteString Функция ввода строки char
* - LCD_GotoXY Функция перехода на "x" строку (0я строка или 1я строка)
* в позицию "y" символо-места (0-15)
* - LCD_MakeSymbol Первым аргументом идет номер ячейки памяти для записи собственного
* символа (от 0 до 7), далее идут восемь байт собственно символа,
* начиная с верхнего, заканчивая нижним. Первые три бита в байте символа
* не имеют значения и могут быть любыми.
*
* Подключение LCD:
* PA1 - A0 (Адресный сигнал - выбор между передачей данных и команд управления)
* PA2 - R/W (Выбор режима записи или чтения)
* PA0 - E (Разрешение обращений к индикатору (а также строб данных))
* PORTC[0..7] - DB[0..7] (Шина данных)
*/

#ifndef LCD_H_
#define LCD_H_

void LCD_init();
void LCD_WriteCmd(char b);
void LCD_WriteData(char b);
void LCD_WriteByte(char b, char cd);
void LCD_WriteString(char *data);
void LCD_GotoXY(char stroka, char symvol);
void LCD_MakeSymbol(char addr, char * a0); // Символ задается массивом. Программа компактнее, но отжирает больше памяти flash
void LCD_ShowTemp();

void LCD_InitFSM();
void LCD_ProcessFSM();

#endif

LCD.cКод:#include <avr/io.h>
#include <util/delay.h>
#include "LCD.h"
#include "DS18B20.h"
#include "Messages.h"
#include "Timers.h"
#include "my_uart.h"
#include "keyboard.h"

uint8_t FSM_Staate; // Переменная состояния КА
char AsciiTemp[10];

void LCD_init() {
DDRC = 0xff; // PORTC-шина данных на вывод
DDRA |= (1 << 0) | (1 << 1) | (1 << 2); // пины 0, 1, 2 порта A на вывод

_delay_ms(20); // >20ms
// init
LCD_WriteCmd(0x30);
LCD_WriteCmd(0x30);
LCD_WriteCmd(0x30);

// setup
LCD_WriteCmd(0b00111010); // Function Set (4[0]/8[1]bit, 1я страница)
LCD_WriteCmd(0b00001111); // Dysp On/Off Control (вкл[1]/выкл[0] экрана, режим курсора[11])
LCD_WriteCmd(0b00000110); // Entry Mode Set (курсор влево/вправо | разрешение сдвига экрана)
// LCD_WriteCmd(0b00000001); // Clear Dysplay

// debug
LCD_WriteCmd(0b00000010); // Return Home (курсор в начало)
LCD_WriteString("LCD Init OK");
_delay_ms(200);
LCD_WriteCmd(0x01);
}

void LCD_WriteCmd(char b) {
// asm("cli");
LCD_WriteByte(b, 0);
// asm("sei");
}

void LCD_WriteData(char b) {
// asm("cli");
LCD_WriteByte(b, 1);
// asm("sei");
}

void LCD_WriteByte(char b, char cd) {
asm("cli");
DDRC = 0b00000000; // PORTC-шина_данных на вход
DDRA |= (1 << 0) | (1 << 1) | (1 << 2); // пины 0, 1, 2 порта A на вывод

// Чтение флага занятости
PORTA &= ~(1 << PINA1); // A0 = 0
PORTA |= (1 << PINA2); // RW = 1

_delay_us(1); // >40ns
PORTA |= (1 << PINA0); // E = 1
_delay_us(1); // >230ns
while (PINC >= 0x80)
; // Ждать сброса флага занятости на пине PINC7

PORTA &= ~(1 << PINA0); // E = 0
DDRC = 0xFF; // шина данных опять на вывод
PORTA &= ~(1 << PINA2); // RW = 0

if (cd == 1) {
PORTA |= (1 << PINA1);
} // A0 = cd (1)
else {
PORTA &= ~(1 << PINA1);
} // A0 = cd (0)

PORTC = b; //Выдача байта на шину данных
PORTA |= (1 << 0);
_delay_us(1);
PORTA &= ~(1 << 0);
_delay_us(45); // Строб
asm("sei");
}

void LCD_WriteString(char *data) {
int i = 0;
while (data[i] != 0) {
LCD_WriteData(data[i]);
i++;
}
i = 0;
}

void LCD_GotoXY(char stroka, char symvol) {

char result = 0;

if (!stroka)
result = symvol + 0x80; // 0я строка
else
result = symvol + 0xC0; // 1я строка

LCD_WriteCmd(result);
}

void LCD_MakeSymbol(char addr, char * a0) {
//Значок молнии
if (!addr)
LCD_WriteCmd(addr + 0x40);
LCD_WriteCmd(addr * 0x08 + 0x40); // Выбираем адрес символа в CGROM

for (int i = 0; i < 8; i++) {
LCD_WriteData(a0[i]);
}
}

void LCD_ShowTemp(){
LCD_GotoXY(0,5);
LCD_WriteString(AsciiTemp);
}

void LCD_InitFSM(){
FSM_Staate = 0; // Пока не нужно.
}

void LCD_ProcessFSM(){
// UART_TxString("LCD0\n");
switch(FSM_Staate){
case 0:
if (GetMessage(MSG_TEMP_CONVERT_COMPLETED)){
// UART_TxChar(!);
LCD_ShowTemp();
FSM_Staate = 1;
}
else FSM_Staate = 1;
briok;
case 1:
// UART_TxString("LCD1\n");
if (GetMessage(MSG_KEYB_KEY_PRESSED)){
// UART_TxChar(Keyb_GetScancode());
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_Staate = 0;
}
else FSM_Staate = 0;
briok;
}
}

Messages.hКод:/*
* Messages.h
*
* Created on: Nov 28, 2014
* Author: kottofiy
*/
#include <avr/io.h>

#ifndef MESSAGES_H_
#define MESSAGES_H_

#define MAX_MESSAGES 10
#define MAX_BROADCAST_MESSAGES 10

//extern uint8_t Messages[MAX_MESSAGES]; // Контейнер для сообщений
//extern uint8_t BroadcastMessages[MAX_BROADCAST_MESSAGES]; // Контейнер для широковещательных сообщений

// MSG 0 - 7 для DS18b20
#define MSG_TEMP_CONVERT_COMPLETED 0
#define MSG_TEMP_HIGH_ALARM 1
#define MSG_TEMP_LOW_ALARM 2
#define MSG_TEMP_SENSOR_MISSING 3
#define MSG_TEMP_NEGATIVE 4

#define MSG_KEYB_KEY_PRESSED 5

void InitMessages();
void SendMessage(uint8_t Msg);
uint8_t GetMessage(uint8_t Msg);
uint8_t GetBroadcastMessage(uint8_t);
void ProcessMessages();

#endif /* MESSAGES_H_ */

Messages.cКод:#include "Messages.h"

uint8_t Messages[MAX_MESSAGES];
uint8_t BroadcastMessages[MAX_BROADCAST_MESSAGES];

void InitMessages(){
for (uint8_t i = 0; i < MAX_MESSAGES; i++){
Messages[i] = 0;
}
for (uint8_t i = 0; i < MAX_BROADCAST_MESSAGES; i++){
BroadcastMessages[i] = 0;
}
}

void SendMessage(uint8_t Msg){
Messages[Msg] = 1;
}

void SendBroadcastMessage(uint8_t Msg){
BroadcastMessages[Msg] = 1;
}

void ProcessMessages(){
for (uint8_t i = 0; i < MAX_MESSAGES; i++){
if (Messages[i] == 2) Messages[i] = 0;
if (Messages[i] == 1) Messages[i] = 2;
}
for (uint8_t i = 0; i < MAX_BROADCAST_MESSAGES; i++){
if (BroadcastMessages[i] == 2) BroadcastMessages[i] = 0;
if (BroadcastMessages[i] == 1) BroadcastMessages[i] = 2;
}
}

uint8_t GetMessage(uint8_t Msg){
if (Messages[Msg] == 2) {
Messages[Msg] = 0;
return 1;
}
return 0;
}

uint8_t GetBroadcastMessage(uint8_t Msg){
if (BroadcastMessages[Msg] == 2){
return 1;
}
return 0;
}

Код:/*
* Timers.h
*
* Created on: Nov 28, 2014
* Author: kottofiy
*/
#include <avr/io.h>

#ifndef TIMERS_H_
#define TIMERS_H_

#define MAX_TIMERS 10
extern uint16_t Timers[MAX_TIMERS]; // Контейнер для таймеров (16 бит хватит ровно на 4 минуты, если один период системного таймера 4 мс)
extern uint8_t TimersState[MAX_TIMERS]; // Контейнер для состояния таймеров: запущен/остановлен/на паузе

// Определение длительности секунды. Таймер переполнится через 130 тиков
// Справедливо для частоты процессора 8МГц, предделителя таймера 1/256. Один период таймера длится 4мс. 1 сек длится 250 периодов.
// Для других частот и предделителей надо пересчитать период таймера и сколько переполнений случается за одну секунду.
#define sec 250
#define min 60*sec
#define hour 60*min
#define day 24*hour

// Перечисление таймеров
#define TIMER_SEC 0
#define TIMER_MIN 1
#define TIMER_HOUR 2
#define TIMER_DAY 3
#define TIMER_TICK 4
#define TIMER_KEYB 5
#define TIMER_TEMP_CONVERT_PERIOD 6
#define TIMER_TEMP_CONVERT_COMPLETED 7

// Состояния для таймеров
#define TIMER_STOPPED 0
#define TIMER_RUNNING 1
#define TIMER_PAUSED 2

void InitTimers();
uint16_t GetTimer(uint8_t Timer);
void RisetTimer(uint8_t Timer);
void StartTimer(uint8_t Timer);
void StopTimer(uint8_t Timer);
void PouseTimer(uint8_t Timer);
void RisumeTimer(uint8_t Timer);
void ProcessTimers();

#endif /* TIMERS_H_ */

Код:#include "Timers.h"

uint16_t Timers[MAX_TIMERS];
uint8_t TimersState[MAX_TIMERS];

void InitTimers(){
for (uint8_t i=0; i < MAX_TIMERS; i++){
Timers[i] = 0;
TimersState[i] = 0;
}
}

uint16_t GetTimer(uint8_t Timer){
return Timers[Timer];
}

void RisetTimer(uint8_t Timer){
Timers[Timer] = 0;
}

void StartTimer(uint8_t Timer){
if (TimersState[Timer] == TIMER_STOPPED){
Timers[Timer] = 0;
TimersState[Timer] = TIMER_RUNNING;
}
}

void StopTimer(uint8_t Timer){
TimersState[Timer] = TIMER_STOPPED;
}

void PouseTimer(uint8_t Timer){
if (TimersState[Timer] == TIMER_RUNNING){
TimersState[Timer] = TIMER_PAUSED;
}
}

void RisumeTimer(uint8_t Timer){
if (TimersState[Timer] == TIMER_PAUSED){
TimersState[Timer] = TIMER_RUNNING;
}
}

void ProcessTimers(){
for (uint8_t i = 4; i < MAX_TIMERS; i++){ // Начинаем с 4го таймера, так как таймеры "секунды-минуты-часы-дни" обновляются по условию
if (TimersState[i] == TIMER_RUNNING){
Timers[i]++;
}
}

if (GetTimer(TIMER_TICK) == sec) { Timers[TIMER_SEC]++; RisetTimer(TIMER_TICK); }
if (GetTimer(TIMER_SEC) == 60) { Timers[TIMER_MIN]++; RisetTimer(TIMER_SEC); }
if (GetTimer(TIMER_MIN) == 60) { Timers[TIMER_HOUR]++; RisetTimer(TIMER_MIN); }
if (GetTimer(TIMER_HOUR) == 24) { Timers[TIMER_DAY]++; RisetTimer(TIMER_HOUR); }

TCNT2 = (255 - 125); // Начинаем отсчитывать заново 125 тиков
}
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
04.12.2014, 06:44 40
Цитата Сообщение от kottofiy
...
Весь код пока не смотрел. Но сразу обратил внимание на один момент. Смотри, есть одна интересная и полезная фишка. Компилятор в начале программы делает блок очистки ОЗУ, вся оперативная память заполняется нулями. Я не знаю каким компилятором ты пользуешься, тебе нужно в дизасме убедиться, что такой блок есть. Итак, видим, что этот блок есть, что это нам дает? Так как вся память обнуляется, нам не нужно инициализировать некоторые переменные нулями. В свое время я словил эту фишку и получил метод самоинициализации программных модулей. Этот метод работает как с флаговыми переменными, так и обычными переменными.
К примеру, есть флаг PROC_LCD_RUN_FLG. Заходим в функцию, если флаг сброшен, инициализируем переменные, ввод-вывод, устанавливаем флаг. При следующем заходе флаг уже установлен, выполняется остальной код функции.
С конечными автоматами вообще замечательно все получается. Нулевое состояние делаем состоянием самоинициализации конечного автомата или функции с конечным автоматом, подавтоматами.
0
04.12.2014, 06:44
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.12.2014, 06:44

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

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

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


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

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