Код на языке С, при котором нажимая на одну кнопку выполняется только одно действие, нажимая на другую кнопку – другое.
Для примера, создадим код на Си, при котором на каждой кнопке будет гореть свой светодиод или несколько светодиодов.
Код на языке СИ с подключение 2-х кнопок (можно подключить хоть сколько), написан в AtmelStudio4 и прошит в Atmega88 с помощью 5 проводков и PonyProg2000:
#include <avr/io.h> #include "delay.h" #include "delay.c" #define F_CPU 16000000UL // 1 MHz clock speed int main(void) { DDRC = 0xFF; //Nakes PORTB as Output DDRB = 0b0000110; // Конфигурируем вывод порта PB1 - как вход PORTB |= ( 1 << 1 ); // Подключаем к PB1 подтягивающий резистор на плюс питания PORTB |= ( 1 << 2 ); // Подключаем к PB2 подтягивающий резистор на плюс питания char in = 1; // Объявляем переменную in и записываем в неё число 1 char ip = 0; // Объявляем переменную in и записываем в неё число 0 - будет показывать какая кнопка включена while(1) // Бесконечный цикл { if (!(PINB & (1<<PINB1)) && in == 1 ) /* если PB1 стал равен нулю и значение in при этом = 1, то мы поймали замыкание кнопки на входе, т. е. перепад из 1 в 0 */ { in = 0; // 1. Стало быть уровень входного сигнала стал равен нулю ip = 1; // Первая кнопка нажата _delay_ms(100); // 2. Задержка 100мс. Выжидаем окончания дребезга контактов } // Теперь ждём момента, когда копка будет отпушена: if (PINB & (1 << PINB1) && in == 0) /* если PB1 стал равен единице и in = 0, то мы поймали на входе размыкание кнопки, т. е. перепад из 0 в 1 */ { in = 1; // В этот момент уровень входного сигнала стал равен нулю _delay_ms(100); /* Задержка 100мс - опять ждём окончания дребезга, больше ничего в момент размыкания кнопки делать не будем */ } if (!(PINB & (1<<PINB2)) && in == 1 ) /* если PB2 стал равен нулю и значение in при этом = 1, то мы поймали замыкание кнопки на входе, т. е. перепад из 1 в 0 */ { in = 0; // 1. Стало быть уровень входного сигнала стал равен нулю ip = 2; // Вторая кнопка нажата _delay_ms(100); // 2. Задержка 100мс. Выжидаем окончания дребезга контактов } // Теперь ждём момента, когда копка будет отпушена: if (PINB & (1 << PINB2) && in == 0) /* если PB1 стал равен единице и in = 0, то мы поймали на входе размыкание кнопки, т. е. перепад из 0 в 1 */ { in = 1; // В этот момент уровень входного сигнала стал равен нулю _delay_ms(100); /* Задержка 100мс - опять ждём окончания дребезга, больше ничего в момент размыкания кнопки делать не будем */ } if (ip == 1) { PORTC = 0b0000010; // 3. Включаем светодиод на ножке PC1 } if (ip == 2) { PORTC = 0b0000100; // 3. Включаем светодиод на ножке PC2 } } }
Примечание:
Скачать черновик на си и hex код:
– в zip архиве.
– в tar.gz архиве.
Примечание:
—————-
Для числа 1 (Dec, в десятичной системе 1) – 00000001 (Bin, в двоичной системе 0b00000001):
1 << 0 = 1 (00000001); 1 << 1 = 2 (00000010); 1 << 2 = 4 (00000100) 1 << 5 = 32 (00100000); 1 >> 2 = 0 (00000000).
Сдвиг влево на один разряд выполняет умножение числа на 2, а сдвиг вправо – деление числа на 2.
————–
Чтобы для данного примера записать “1” в бит с номером 5 и загрузить результирующий байт в регистр порта PORTB (установка высокого уровня для канала PB5) можно использовать любую из следующих, равнозначных по результату конструкций операторов:
PORTB = PORTB | 32; PORTB = PORTB | (1 << 5); PORTB = PORTB | (1 << PB5); PORTB |= (1 << PB5);
Наиболее удобно использовать последний вариант – он краток, в нем используется комбинация из операций логического ИЛИ и присваивания.