Опрос кнопок микроконтроллером

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Аlex »

А причём тут "мегапроект" ? У Вас проблема с опросом кнопок, значит Вам сюда. Зачем темы плодить ?
ut1wpr
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Re: Помогите опросить кнопку

Сообщение ut1wpr »

Zhursat писал(а):А то в этой теме мне стыдно позориться со своим "мегапроектом".
Модератор тебе правильно сказал. Не стоит темы плодить. И стыдится не стоит. Ты же не колупаешь в носу, время от времени выпрашивая у форумчан пару строчек для себя. :) Ты учишь, читаешь, рисуешь, исследуешь, ошибаешься, исправляешься. Процесс идет, все в порядке. Для помощи таким и толчется здесь людь знающий и ведающий. :)
С уважением,
Виктор.
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Помогите опросить кнопку

Сообщение RGB »

Zhursat Используй функцию опроса кнопок в прерывании от таймера
в предоставленном на 4 странице уважаемым пользователем Аlex код опроса кнопок просто велеколепный
За что ему ещё раз отдельное спасибо!
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Помогите опросить кнопку

Сообщение vitalik_1984 »

Правильно как раз в динамической индикации уже используются прерывания таймера, вписываем в существующий код опрос кнопок и поехали!
Zhursat
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Вт янв 31, 2012 21:09:21
Откуда: Украина

Re: Помогите опросить кнопку

Сообщение Zhursat »

Тут вот какое дело.... Убрал я из программы все, и оставил только работу с кнопками, как советовали.
Вот код:
Спойлерwhile (1)
{
if (PINB.0==0)
{
delay_ms(50);
if (PINB.0==0)
{
if (set_temp<90) set_temp++;

};
};

if (PINB.1==0)
{
delay_ms(50);
if (PINB.1==0)
{
if (set_temp>40) set_temp--;
};
};
indication=set_temp;
recoding();
};
}


И что вы думаете? Нифига они не пашут. Жму на них жму - а на индикаторе "00"
Такое впечатление, что программа не знает, что это за переменная set_temp и что с ней нужно делать.
Напомню, она у меня обьявлена вот так eeprom int set_temp=50 тоесть по идее она должна храниться в ЕЕПРОМ и сохранять свое значение даже при выключении схемы (ну или если электричество вырубится). Или я как то неправильно ее инициализирую? Но КодВижн вроде не ругается..... Компилит красиво.
Аватара пользователя
U235
Встал на лапы
Сообщения: 135
Зарегистрирован: Вт фев 21, 2012 20:42:26
Откуда: Санкт-Петербург, Россия, Земля

Re: Помогите опросить кнопку

Сообщение U235 »

Zhursat писал(а):Такое впечатление, что программа не знает, что это за переменная set_temp и что с ней нужно делать.

С этой переменной в программе всё нормально, что бы убедиться в этом достаточно глянуть на ассемблерный листинг. А вот переменную indication функция main хранит в регистре, компилятор так оптимизирует программу. И поскольку выполнение функции никогда не завершается, в регистре все изменения и остаются. Что бы избежать такое, нужно объявить переменную как volatile.

Код: Выделить всё

volatile unsigned int indication;

Тем самым Вы сообщите, что переменная может "внезапно" измениться и к ней нельзя применять оптимизацию.
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Re: Помогите опросить кнопку

Сообщение Goodefine »

Вообще-то, CVAVR всегда было пофиг на volatile. Чтоб сказать где проблема нужно увидеть весь код, желательно полный проект, а не огрызок за которым скрывается невесть что..
И еще, почему кнопка на PB0 проверяется на уровень 0, на на PB1 - на уровень 1? Подтянуты по разному что ли?
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Zhursat
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Вт янв 31, 2012 21:09:21
Откуда: Украина

Re: Помогите опросить кнопку

Сообщение Zhursat »

Goodefine писал(а):Вообще-то, CVAVR всегда было пофиг на volatile. Чтоб сказать где проблема нужно увидеть весь код, желательно полный проект, а не огрызок за которым скрывается невесть что..
И еще, почему кнопка на PB0 проверяется на уровень 0, на на PB1 - на уровень 1? Подтянуты по разному что ли?


Извините, где вы увидели, что кнопки проверяются на разные уровни? Что PINB.0 что PINB.1 проверяются на 0. И подтянуты они одинаково.
А код полностью вот:
Спойлер/*****************************************************
Chip type : ATmega8
Program type : Application
AVR Core Clock frequency: 4,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/

#include <mega8.h>
#include <1wire.h>
#include <ds18b20.h>
#include <delay.h>
#include <stdio.h>

#define digit1 PORTC.1 //анод первой цифры
#define digit2 PORTC.2 //анод второй цифры

eeprom int set_temp=50; //переменная с опорной температурой

flash char digits[] = { //создаём массив с цифрами
0b11000000, //0
0b11111001, //1
0b10100100, //2
0b10110000, //3
0b10011001, //4
0b10010010, //5
0b10000010, //6
0b11111000, //7
0b10000000, //8
0b10010000, //9
0b10001001, //Буква Н
0b11111111 //пустота
};

//*******




char digit_out[2], cur_dig; //переменные для работы с LED
volatile unsigned int indication; //переменная для хранения чисел




void recoding(void) { //функция для перекодировки из hex в dec

if (indication<100) { //начинаем преобразование если число < 100 так как 2-х разрядный LED
digit_out[0]=indication/10; //Делим на 10 остаток в масив 1-разряд
digit_out[1]=indication%10; //Делим на 10 число в масив 2-разряд
} //*******
}




// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTD=0xFF; //чтобы предотвратить эффект “тени” на соседних индикаторах
switch (cur_dig){
case 0:{digit1=1; digit2=0; break;}; //подаём питание на разряд 2
case 1:{digit2=1; digit1=0; break;}; //подаём питание на разряд 1
}
PORTD=digits[digit_out[cur_dig]]; //выводим с каждым срабатыванием таймера число с мссива в порт В, но не для всех разрядов сразу

cur_dig++; //с каждым срабатыванием таймера, увеличиваем
//переменную cur_dig на 1
if(cur_dig==2) cur_dig=0; //если cur_dig = 2 обнуляем

}

// Declare your global variables here
unsigned char devices;

void main(void)
{
// Declare your local variables here

PORTB=0x03;
DDRB=0x0C;

PORTC=0x00;
DDRC=0x06;


PORTD=0x00;
DDRD=0x7F;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 62,500 kHz
TCCR0=0x03;
TCNT0=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;

// инициализация 1 Wire
devices=w1_init();

#asm("sei")

while (1)
{
if (PINB.0==0)
{
delay_ms(50);
if (PINB.0==0)
{
if (set_temp<99) set_temp++;

};
};

if (PINB.1==0)
{
delay_ms(50);
if (PINB.1==0)
{
if (set_temp>40) set_temp--;
};
};
indication=set_temp;
recoding();
};
}


Кстати, вот что вырулил: если в теле программы присвоить переменной set_temp какое нибудь значение - тогда все красиво работает (инкремент-декремент, индикация - все пашет). Но в таком случае после включения-выключения питания в этой переменной будет присвоеное значение, зачем тогда ЕЕПРОМ использовать. Все ведь задумывалось так, чтобы эти данные было "энергонезависимы".
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Re: Помогите опросить кнопку

Сообщение Goodefine »

И правда, чего то глаз замылился ))) Насчет присваивания - все логично, пока не присвоите, там мусор, точнее 0xFF, в пределы не попадает и не инкрементируется/декрементируется. Что касается повторной записи при включении, скорее всего, при компиляции создается файл инициализации еепром (*.eep) - начальными значениями, а в коде это не прописывается. Его нужно зашивать отдельно от прошивки один раз. Точнее не скажу, с кодевижном давно не работал, а когда работал то квалификаторами eeprom не пользовался - делал по другому..
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Zhursat
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Вт янв 31, 2012 21:09:21
Откуда: Украина

Re: Помогите опросить кнопку

Сообщение Zhursat »

Все таки победил я кнопки!!!! Для перестраховки сделал так:

Код: Выделить всё

if ((set_temp<40)||(set_temp>100)) {set_temp=40;};


Опрос сделал вот так

Код: Выделить всё

while (1)
      { 
        if (PINB.0==0)
        {
                delay_ms(50);
                if (PINB.0==0)
                {
                        if (set_temp<99) set_temp++;
                        delay_ms(2000);
                       
                };
        };
       
        if (PINB.1==0)
        {
                delay_ms(50);
                if (PINB.1==0)
                {
                        if (set_temp>40) set_temp--;
                        delay_ms(2000);
                };
        };
        if ((PINB.0==0) || (PINB.1==0)) {indication=set_temp;} else {indication=ds18b20_temperature(0);};
        recoding();
      };
}


Теперь протеус рисует и опорную температуру с задержкой на отображение 2 сек и если не нажаты кнопки в течении 2 сек - начинает показывать температуру текущую, которая "пришла" с термодатчика. Спасибо всем, кто не остался в стороне, все таки когда мозг в тупике - даже вроде бы незначительный совет может направить на путь истинный. Буду теперь заниматься силовой стороной автоматики: когда что включить, когда что выключить.
Кстати, попутно вопрос, правда не в тему: КТ315 транзистора хватит для управления релюшками РЭС 34, или нужно помощнее ставить???
Аватара пользователя
U235
Встал на лапы
Сообщения: 135
Зарегистрирован: Вт фев 21, 2012 20:42:26
Откуда: Санкт-Петербург, Россия, Земля

Re: Помогите опросить кнопку

Сообщение U235 »

Заработало - это хорошо. То что Вы назвали перестраховкой - это повышение надёжности программы.

Но работу с кнопками я бы посоветовал продолжить. В нынешнем варианте что бы изменить температуру на 10 градусов придётся потратить больше 20 секунд, а это не очень удобно.
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Re: Помогите опросить кнопку

Сообщение Goodefine »

Zhursat писал(а):Все таки победил я кнопки!!!! Для перестраховки сделал так:

Код: Выделить всё

if ((set_temp<40)||(set_temp>100)) {set_temp=40;};


В принципе, говоря победил, надо все таки уловить суть проблемы, и как с ней бороться. В первом вашем варианте тоже все было правильно, единственное что вы не сделали - это не записали в контроллер файл с именем проекта и расширением eep, находящийся в одной папке с hex-ом. Поскольку при инициализации еепром переменных, а именно

Код: Выделить всё

eeprom int set_temp=50; //переменная с опорной температурой

компилятор не прописывает это в хексе а просто создает вышеуказанный фал. Это сделано специально чтобы можно было инициализировать eeprom переменные без лишней головной боли. Если переменная меняется в коде программы, то понятное дело, в хексе это есть. Впрочем строка

Код: Выделить всё

if ((set_temp<40)||(set_temp>100)) {set_temp=40;};

тоже полезна - устанавливает дефолтные значения в случае чего. Но понимать инструментарий нужно...
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Zhursat
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Вт янв 31, 2012 21:09:21
Откуда: Украина

Re: Помогите опросить кнопку

Сообщение Zhursat »

Так а я о чем? Я обеими руками "За!".
Вот тут накидал немного "автоматики", и еще уменьшил задержки на индикацию опорной температуры. Неплохо помог мне в этом вот этот сайтик http://www.atmega8.ru/ Это ни в коем случае не реклама, действительно для начинающих, типа меня, самое то.
Вобщем, кто желает посмотреть и покритиковать - во вложении файлы проекта и конечно же протеус :)))
Вложения
_KOTEL_new.rar
(95.29 КБ) 406 скачиваний
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Re: Помогите опросить кнопку

Сообщение Goodefine »

Первый же вопрос, зачем volatile для indication?
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Zhursat
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Вт янв 31, 2012 21:09:21
Откуда: Украина

Re: Помогите опросить кнопку

Сообщение Zhursat »

Выше советовали.... Я если чесно даже не знаю, что это значит. Но работает. Впрочем, работает даже при просто int
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Аlex »

Первый же вопрос, зачем volatile для indication?
Так U235 сказал :)))
Zhursat
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Вт янв 31, 2012 21:09:21
Откуда: Украина

Re: Помогите опросить кнопку

Сообщение Zhursat »

Ну не трольте меня :oops:
Я уже вычитал, что это такое.... В данном случае использование действительно не оправдано. Просто осталось с прошлых компиляций.....
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Аlex »

Да всё нормально, не переживайте, это в порядке вещей - Вам посоветовали - Вы сделали. :)
Видимо, камушек не в Ваш огород был :)
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Re: Помогите опросить кнопку

Сообщение Goodefine »

Ну и в порядке легкой критики - привыкайте писать вместо

Код: Выделить всё

 if (PINB.0==0)
        {
                delay_ms(50);
                if (PINB.0==0)
                {
                        if (set_temp<99) set_temp++;
                        delay_ms(500);
                       
                };
        };

примерно так

Код: Выделить всё

#define BUTTON_UP (!PINB.0)
#define TERM_UP_LIMIT   99
#define DELAY_ANTI_DRB 50
#define DELAY_UP  500
...
 if (BUTTON_UP)
        {
                delay_ms(DELAY_ANTI_DRB);
                if (BUTTON_UP)
                {
                        if (set_temp<TERM_UP_LIMIT) set_temp++;
                        delay_ms(DELAY_UP);
                       
                };
        };

Потом не надо будет бегать по всему коду чтоб изменить пределы или переназначить кнопки, да и выглядит понятней.
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Zhursat
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Вт янв 31, 2012 21:09:21
Откуда: Украина

Re: Помогите опросить кнопку

Сообщение Zhursat »

Вы словно мои мысли прочитали: как раз сидел думал , что нужно поназначать дефайнами то, чем часто пользуешься. Так что критика принимается в полном обьеме. Но есть одно "Но": я уже говорил, что только начинаю знакомство с МК и с языком С в частности. Асм для меня вобще темный лес, а С немного понятней. Поэтому есть желание сразу разобраться во всем (ну или примерно во всем :))) ) без упрощений, чтобы саму логику понять. А потом уже будем превращать "количество в качество".
Ответить

Вернуться в «Периферия»