Re: включение нагрузки 1 кнопкой без фиксации, на МК
Добавлено: Сб май 09, 2020 00:44:59
Уррааа))) заработало) NStorm, спасибо большое) наконец я поверил в указатели))
Здесь можно немножко помяукать :)
https://radiokot.ru/forum/
Код: Выделить всё
//ТИНИ_13а
//
// Напишем 2 пустые функции как учил AVR (каждая функция выполняет свою задачу и вместе они выполняют задуманное)
// Потом уже напишем код для каждой
//
//
// 2.(status_buttons) --анализ статуса кнопок
// 3.(trigger_load) --переключает нагрузку по статусу кнопок
//
//
//
//
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1200000 UL
#define KEY1 PB0 // пин В0 теперь зовется key1
#define LED1 PB1 // пин В1 порта В зовется LED1
#define KEY2 PB4 // пин В4 теперь зовется key2
#define LED2 PB3 // пин В3 порта В зовется LED2
#define ON_LOAD 1 // включена нагрузка
#define OF_LOAD 0 // выключена нагрузка
#define PORTx PORTB // наш рабочий портец
volatile uint8_t i= 0, k= 0,m= 0, n= 0; //объявляем восьмибитные переменные счеткики.
volatile uint8_t press_KEY1= 0, press_KEY2= 0; // статус нажатой и отпущеной кнопки(press_KEY1-пин KEY1,press_KEY2-пин KEY2)
//--------------------------------------------------------------------------------------------------------------------------------
int main(void)
{
DDRB = ~((1 << KEY1) | (1 << KEY2)); // бит РВ0 и РВ4 конфигурируем как вход
PORTB = (1 << KEY1) | (1 << KEY2); // входы подтянем
TIMSK0 = 0b00000010; // бит РВ1(TOIE0) устанавливаем в 1, разрешения прерывания по переполнению таймера /счетчика Т0
TCCR0A = 0b00000000; // биты РВ0(WGM00) и РВ1(WGM01) сбрасываем в 0, настройка режима Normal
TCCR0B = 0b00000011; // настраиваем предделитель на 64 (биты CS02=0,CS01=1,CS00=1),бит В3(WGM02) сбрасываем в 0,режим Normal
GTCCR = 0b00000001; // бит РВ0(PSR10) устанавливаем в 1, Сброс предделителя TO (сбрасываем пред. в конце настроек)
sei(); // Разрешить прерывания
while (1)
{ // Основной цикл программы, он пуст, так как вся работа в прерывании
}
}
//--------------------------------------------------------------------------------------------------------------------------------
void counter_buttons(volatile uint8_t *press_KEY,uint8_t KEY, volatile uint8_t *c, volatile uint8_t *d) // счетчики статуса наших кнопок
{
if (~PINB & (1<<KEY)) // Если (KEY) разряд порта B сброшен,(т.е. кнопка нажата) то выполняется Код1. В противном случае, выполняется Код2.
{
(*c)++; // (Код1) (*c) счетчик указатель нажатого состояния кнопки ( лог 0)
}
if ((*c)>=5) // Если счетчик (*c) больше или равно 5 то начнем отлавливать отпускание.
{
if (PINB & (1 << KEY)) // Если (KEY) разряд порта B установлен,(т.е. кнопка не нажата) то выполняется Код1
{
(*d)++; // (Код1) (*d) счетчик указатель отпущеного состояния кнопки ( лог 1)
}
if ((*d)>=5) // Если счетчик (*d) больше или равно 5 то у нас наконец то есть полный цикл нажатие и отпускание кнопки
{
(*press_KEY)=1; // кнопка нажата и отпущена (полный цикл работы кнопки осуществлен) пишем 1 в статусную переменную (press_KEY)
(*c)=0,(*d)=0 ; // сбросим счетчики
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------
void trigger_load(volatile uint8_t *press_KEY,volatile uint8_t LED ) // переключает нагрузку
{
switch(*press_KEY)
{
case ON_LOAD:
PORTx ^= (1 << LED); // инверсируем состояние пина
*press_KEY=0; // сбросим статус кнопки
break; //
case OF_LOAD: ; break; //
}
}
//---------------------------------------------------------------------------------------------------------------------------------
ISR(TIM0_OVF_vect)
{
counter_buttons (&press_KEY1,KEY1,&i,&k); //вызываем функцию статуса кнопки( i- счетчик нажатого состояния, k - не нажатого)
counter_buttons (&press_KEY2,KEY2,&m,&n); //передаем в функцию не переменные, а их адреса таким образом значения по выходу из фун. сохранятся
trigger_load (&press_KEY1,LED1); //вызовем процедуру управлением нагрузкой
trigger_load (&press_KEY2,LED2); //вызовем процедуру управлением нагрузкой
}
//----------------------------------------------------------------------------------------------------------------------------------
у меня другой ник, обращаю ваше внимание.sergo80zxc писал(а):AVR вот вроде написал рабочий код с помощью ваших советов.
Код: Выделить всё
/*
* GccApplication22.c
*
* Created: 04.09.2020 1:38:16
* Author: сергей
*/
// ---------------ПРОГА УПРАВЛЯЕТ 7 НАГРУЗКАМИ на одном порту ОДНОЙ КНОПКОЙ------------------по одному пину инверсирует или сразу все 7 пинов включить или выключить
//
// прога работает, не совсем удобно управление, но глюков в железе не обнаружил))) смысл проги инверсировать семь нагрузок одной кнопкой
//
// работает так, например нажимаешь и отпускаешь быстро 5 раз кнопку на пине (PD0) то есть набрали адрес нагрузки (PD5), затем нажимаем и держим
// кнопку (PD0) примерно секунду и отпускаем, светодиод на пине (PD5) загорается и горит , что бы его погасить делаем также, набиваем адрес 5 нажатий
// и долгим нажатием выключаем светодиод (PD5), и так со всеми семью нагрузками.
//
// И если нужно включить сразу все 7 пинов набиваем 8 раз и один раз долго нажимаем и потом отпускаем
// А если нужно выключить сразу все 7 пинов набиваем 9 раз и один раз долго нажимаем и потом отпускаем
//
// кнопка -(PD0) , нагрузки (PD1,PD2,PD3,PD4,PD5,PD6,PD7)
//
//прога аналогичная (GccApplication11.c) но тут мы изъяли из обработчика прерывания по таймеру тяжелые функции и повесили их в главный суперцикл
//на прерывании таймера повесили только изменение статуса системного таймера ( в каждом тике устанавливам (sis_taimer) в 1)
//а в главном суперцикле сбрасывали после нужных действий его в ноль.
//в главном суперцикле осуществляется проверка системного таймера, если он =1, то пробегаем интерацию разок и до следующиго тика таймера крутимся
//в суперцикле
//
//
#include <avr/io.h>
#include "status_boot.h"
#include <avr/interrupt.h>
#define F_CPU 1000000 UL
#define KEY1 PD0 // пин В0 теперь зовется key1
#define LED1 PD1 // пин В1 порта В зовется LED1
#define LED2 PD2 // пин В2 порта В зовется LED2
#define LED3 PD3 // пин В3 порта В зовется LED3
#define LED4 PD4 // пин В4 порта В зовется LED4
#define LED5 PD5 // пин В5 порта В зовется LED5
#define LED6 PD6 // пин В6 порта В зовется LED6
#define LED7 PD7 // пин В7 порта В зовется LED7
#define PORTx PORTD // наш рабочий портец
#define PINx1 PIND // наш рабочий портец
volatile unsigned char sis_taimer =0; // объявим переменную системного таймера
//--------------------------------------------------------------------------------------------------------------------------------
int status_buttons(int KEY, int PINx); // статус нашей кнопки ( 0-не нажата, 1-нажата, 2-коротко нажата и отпущена, 3-длинно нажата и отпущена).
//---------------------------------------------------------------------------------------------------------------------------------
int Key_management(int ST_KEY); // функция считает количество нажатий и выдает статус нагрузки ( какую нагрузку включить или выключить )
//---------------------------------------------------------------------------------------------------------------------------------
void trigger_load(int ST_LOAD ); // функция переключения нагрузки.
//---------------------------------------------------------------------------------------------------------------------------------
ISR(TIMER0_OVF_vect) // прерывание по переполнению таймера
{
sis_taimer =1; // установим в 1 переменную нашего системного таймера
}
//----------------------------------------------------------------------------------------------------------------------------------
int main(void)
{
DDRD = ~(1 << KEY1); // бит РВ0 конфигурируем как вход
PORTD = (1 << KEY1); // вход подтянем
TIMSK0 = 0b00000001; // бит РВ0(TOIE0) устанавливаем в 1, разрешения прерывания по переполнению таймера /счетчика Т0
TCCR0A = 0b00000000; // биты (WGM02,WGM01,WGM00) сбрасываем в 0, настройка режима Normal
TCCR0B = 0b00000011; // настраиваем предделитель на 64 (биты CS02=0,CS01=1,CS00=1),бит В3(WGM02) сбрасываем в 0,режим Normal
GTCCR = 0b00000001; // бит РВ0(PSRSYNC) устанавливаем в 1, Сброс предделителя TO (сбрасываем пред. в конце настроек)
sei(); // Разрешить прерывания
while (1) // Основной цикл программы
{
if (sis_taimer ==1) // Если системный таймер равен 1 то выполняется Код1, будет срабатывать по тику прерывания таймера (наш системный таймер)
{
int ST_KEY1 = 0; // объявляем локальную переменную --- в нее будем загружать возвращаемое значение функции (status_buttons)
int ST_LOAD1 = 0; // объявляем локальную переменную --- в нее будем загружать возвращаемое значение функции (Key_management)
ST_KEY1 = status_buttons( KEY1,PINx1); // вызываем функцию (status_buttons) передаем в нее фактические параметры и присваиваем результат выполнения функции переменной (ST_KEY1)
ST_LOAD1 = Key_management( ST_KEY1); // вызываем функцию (Key_management) передаем в нее фактические параметры и присваиваем результат выполнения функции переменной (ST_LOAD1)
trigger_load( ST_LOAD1 ); // функция переключения нагрузки
sis_taimer =0; // сбросим таймер и ждем следующего тика системного таймера
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------
Код: Выделить всё
#include <avr/io.h>
#ifndef status_boot
#define status_boot
// Прототипы функций (возвращаемое значение, название, параметры).
int status_buttons(int KEY, int PINx);
int Key_management(int ST_KEY);
void trigger_load(int ST_LOAD );
#endif /* sКод: Выделить всё
//#######################################################################################################################
//#
//# БИБЛИОТЕКА ОБРАБОТКИ НАЖАТИЙ КЛАВИШ
//#
//#######################################################################################################################
#include <avr/io.h>
#include "status_boot.h"
int status_buttons(int KEY, int PINx) // статус нашей кнопки ( 0-не нажата, 1-нажата, 2-коротко нажата и отпущена, 3-длинно нажата и отпущена).
{
int status_KEY=0; // объявим переменную статуса кнопки
static int counter_ON_press=0; // счетчик нажатого состояния (static это значит при выходе из функции значение в переменной запомнится, 0 один раз инициализируется)
static int counter_OF_press=0; // счетчик не нажатого состояния (static это значит при выходе из функции значение в переменной запомнится, 0 один раз инициализируется)
if (~PINx & (1<<KEY)) // Если (KEY) разряд порта B сброшен,(т.е. кнопка нажата) то выполняется Код1. В противном случае, выполняется Код2.
{
status_KEY =1; // пишем в статус 1 (КНОПКА НАЖАТА)
}
if (PINx & (1 << KEY)) // Если (KEY) разряд порта B установлен,(т.е. кнопка не нажата) то выполняется Код1
{
status_KEY =0; // пишем в статус 0 (КНОПКА НЕ НАЖАТА)
}
if ((status_KEY>=1) && (counter_ON_press) < 230) // если кнопка нажата и счетчик нажатого состояние меньше 230 ( защита от переполнения)
{
(counter_ON_press) ++; // инкрементируем счетчик нажатого состояния
}
if ((counter_ON_press) >=5 && (counter_ON_press) < 100) // если счетчик нажатой кнопки больше или равен 5 и меньше 100, у нас короткое нажатие
{
if ((status_KEY==0) && (counter_OF_press) < 230) // если кнопка не нажата и счетчик не нажатого состояние меньше 230 ( защита от переполнения)
{
(counter_OF_press) ++; // инкрементируем счетчик не нажатого состояния
if (counter_OF_press>=5) // если счетчик не нажатой кнопки больше или равен 5 , то считаем кнопка у нас была нажата и отпущена
{
status_KEY =2; // пишем в статус 2 (КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА)
counter_ON_press=0; // обнуляем счетчик
counter_OF_press=0; // обнуляем счетчик
}
}
}
if ((counter_ON_press) >=100 && (counter_ON_press) < 500) // если счетчик нажатой кнопки больше или равен 40 и меньше 200, у нас длинное нажатие
{
if ((status_KEY==0) && (counter_OF_press) < 230) // если кнопка не нажата и счетчик не нажатого состояние меньше 230 ( защита от переполнения)
{
(counter_OF_press) ++; // инкрементируем счетчик не нажатого состояния
if (counter_OF_press>=5) // если счетчик не нажатой кнопки больше или равен 5 , то считаем кнопка у нас была нажата и отпущена
{
status_KEY =3; // пишем в статус 3 (КНОПКА ДЛИННО НАЖАТА И ОТПУЩЕНА)
counter_ON_press=0; // обнуляем счетчик
counter_OF_press=0; // обнуляем счетчик
}
}
}
return (status_KEY); // возвращаем значение статуса кнопки в вызов
}
int Key_management(int ST_KEY) // функция считает количество нажатий и выдает статус нагрузки ( какую нагрузку включить или выключить )
{
int ST_LOAD=0; // объявим переменную СТАТУС НАГРУЗКИ ее используем для выдачи значения из нашей функции
static int B=0; // объявим переменную (static) счетчик НАЖАТОЙ И ОТПУЩЕНОЙ кнопки (переменная при выходе из функции сохранит значение)
if (ST_KEY==2) // если кнопка нажата и отпущена
{
(B) ++; // инкрементируем счетчик нажатой и отпущеной кнопки
}
if (ST_KEY==3) // если у нас есть долгое нажатие мы считаем что код нагрузки набран и считываем далее сколько было нажатий
{
switch (B)
{
case 1: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 1 РАЗ
(ST_LOAD)=1; // в статус нагрузки заносим 1
break;
case 2: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 2 РАЗА
(ST_LOAD)=2; // в статус нагрузки заносим 2
break;
case 3: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 3 РАЗА
(ST_LOAD)=3; // в статус нагрузки заносим 3
break;
case 4: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 4 РАЗА
(ST_LOAD)=4; // в статус нагрузки заносим 4
break;
case 5: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 5 РАЗ
(ST_LOAD)=5; // в статус нагрузки заносим 5
break;
case 6: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 6 РАЗ
(ST_LOAD)=6; // в статус нагрузки заносим 6
break;
case 7: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 7 РАЗ
(ST_LOAD)=7; // в статус нагрузки заносим 7
break;
case 8: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 8 РАЗ
(ST_LOAD)=8; // в статус нагрузки заносим 8
break;
case 9: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 9 РАЗ
(ST_LOAD)=9; // в статус нагрузки заносим 9
break;
}
B=0; // обнулим счетчик нажатой и отпущеной кнопки
}
return (ST_LOAD); // возвращаем значение
}
void trigger_load(int ST_LOAD ) // функция переключения нагрузки.
{
switch (ST_LOAD)
{
case 1: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 1 РАЗ
PORTx ^= (1 << LED1); // инверсируем состояние пина
break;
case 2: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 2 РАЗА
PORTx ^= (1 << LED2); // инверсируем состояние пина
break;
case 3: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 3 РАЗА
PORTx ^= (1 << LED3); // инверсируем состояние пина
break;
case 4: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 4 РАЗА
PORTx ^= (1 << LED4); // инверсируем состояние пина
break;
case 5: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 5 РАЗ
PORTx ^= (1 << LED5); // инверсируем состояние пина
break;
case 6: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 6 РАЗ
PORTx ^= (1 << LED6); // инверсируем состояние пина
break;
case 7: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 7 РАЗ
PORTx ^= (1 << LED7); // инверсируем состояние пина
break;
case 8: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 8 РАЗ
PORTx |=(1 << LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4) | (1<<LED5) | (1<<LED6) | (1<<LED7); // установим пины с 1 по 7 в еденицу
break;
case 9: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 9 РАЗ
PORTx &= ~((1<<LED1)|(1 << LED2)|(1 << LED3)|(1 << LED4)|(1 << LED5)|(1 << LED6)|(1 << LED7)); // пины с 1 по 7 сброшены в ноль
break;
}
}
Код: Выделить всё
/*
* GccApplication20.c
*
* Created: 31.08.2020 0:31:23
* Author: сергей
*/
// ---------------ПРОГА УПРАВЛЯЕТ 7 НАГРУЗКАМИ на одном порту ОДНОЙ КНОПКОЙ------------------по одному пину инверсирует или сразу все 7 пинов включить или выключить
//
// прога работает, не совсем удобно управление, но глюков в железе не обнаружил))) смысл проги инверсировать семь нагрузок одной кнопкой
//
// работает так, например нажимаешь и отпускаешь быстро 5 раз кнопку на пине (PD0) то есть набрали адрес нагрузки (PD5), затем нажимаем и держим
// кнопку (PD0) примерно секунду и отпускаем, светодиод на пине (PD5) загорается и горит , что бы его погасить делаем также, набиваем адрес 5 нажатий
// и долгим нажатием выключаем светодиод (PD5), и так со всеми семью нагрузками.
//
// И если нужно включить сразу все 7 пинов набиваем 8 раз и один раз долго нажимаем и потом отпускаем
// А если нужно выключить сразу все 7 пинов набиваем 9 раз и один раз долго нажимаем и потом отпускаем
//
// кнопка -(PD0) , нагрузки (PD1,PD2,PD3,PD4,PD5,PD6,PD7)
//
//прога аналогичная (GccApplication11.c) но тут мы изъяли из обработчика прерывания по таймеру тяжелые функции и повесили их в главный суперцикл
//на прерывании таймера повесили только изменение статуса системного таймера ( в каждом тике устанавливам (sis_taimer) в 1)
//а в главном суперцикле сбрасывали после нужных действий его в ноль.
//в главном суперцикле осуществляется проверка системного таймера, если он =1, то пробегаем интерацию разок и до следующиго тика таймера крутимся
//в суперцикле
//
//
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1000000 UL
#define KEY1 PD0 // пин В0 теперь зовется key1
#define LED1 PD1 // пин В1 порта В зовется LED1
#define LED2 PD2 // пин В2 порта В зовется LED2
#define LED3 PD3 // пин В3 порта В зовется LED3
#define LED4 PD4 // пин В4 порта В зовется LED4
#define LED5 PD5 // пин В5 порта В зовется LED5
#define LED6 PD6 // пин В6 порта В зовется LED6
#define LED7 PD7 // пин В7 порта В зовется LED7
#define PORTx PORTD // наш рабочий портец
#define PINx1 PIND // наш рабочий портец
volatile unsigned char sis_taimer =0; // объявим переменную системного таймера
//--------------------------------------------------------------------------------------------------------------------------------
int status_buttons(int KEY, int PINx) // статус нашей кнопки ( 0-не нажата, 1-нажата, 2-коротко нажата и отпущена, 3-длинно нажата и отпущена).
{
int status_KEY=0; // объявим переменную статуса кнопки
static int counter_ON_press=0; // счетчик нажатого состояния (static это значит при выходе из функции значение в переменной запомнится, 0 один раз инициализируется)
static int counter_OF_press=0; // счетчик не нажатого состояния (static это значит при выходе из функции значение в переменной запомнится, 0 один раз инициализируется)
if (~PINx & (1<<KEY)) // Если (KEY) разряд порта B сброшен,(т.е. кнопка нажата) то выполняется Код1. В противном случае, выполняется Код2.
{
status_KEY =1; // пишем в статус 1 (КНОПКА НАЖАТА)
}
if (PINx & (1 << KEY)) // Если (KEY) разряд порта B установлен,(т.е. кнопка не нажата) то выполняется Код1
{
status_KEY =0; // пишем в статус 0 (КНОПКА НЕ НАЖАТА)
}
if ((status_KEY>=1) && (counter_ON_press) < 230) // если кнопка нажата и счетчик нажатого состояние меньше 230 ( защита от переполнения)
{
(counter_ON_press) ++; // инкрементируем счетчик нажатого состояния
}
if ((counter_ON_press) >=5 && (counter_ON_press) < 100) // если счетчик нажатой кнопки больше или равен 5 и меньше 100, у нас короткое нажатие
{
if ((status_KEY==0) && (counter_OF_press) < 230) // если кнопка не нажата и счетчик не нажатого состояние меньше 230 ( защита от переполнения)
{
(counter_OF_press) ++; // инкрементируем счетчик не нажатого состояния
if (counter_OF_press>=5) // если счетчик не нажатой кнопки больше или равен 5 , то считаем кнопка у нас была нажата и отпущена
{
status_KEY =2; // пишем в статус 2 (КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА)
counter_ON_press=0; // обнуляем счетчик
counter_OF_press=0; // обнуляем счетчик
}
}
}
if ((counter_ON_press) >=100 && (counter_ON_press) < 500) // если счетчик нажатой кнопки больше или равен 40 и меньше 200, у нас длинное нажатие
{
if ((status_KEY==0) && (counter_OF_press) < 230) // если кнопка не нажата и счетчик не нажатого состояние меньше 230 ( защита от переполнения)
{
(counter_OF_press) ++; // инкрементируем счетчик не нажатого состояния
if (counter_OF_press>=5) // если счетчик не нажатой кнопки больше или равен 5 , то считаем кнопка у нас была нажата и отпущена
{
status_KEY =3; // пишем в статус 3 (КНОПКА ДЛИННО НАЖАТА И ОТПУЩЕНА)
counter_ON_press=0; // обнуляем счетчик
counter_OF_press=0; // обнуляем счетчик
}
}
}
return (status_KEY); // возвращаем значение статуса кнопки в вызов
}
//---------------------------------------------------------------------------------------------------------------------------------
int Key_management(int ST_KEY) // функция считает количество нажатий и выдает статус нагрузки ( какую нагрузку включить или выключить )
{
int ST_LOAD=0; // объявим переменную СТАТУС НАГРУЗКИ ее используем для выдачи значения из нашей функции
static int B=0; // объявим переменную (static) счетчик НАЖАТОЙ И ОТПУЩЕНОЙ кнопки (переменная при выходе из функции сохранит значение)
if (ST_KEY==2) // если кнопка нажата и отпущена
{
(B) ++; // инкрементируем счетчик нажатой и отпущеной кнопки
}
if (ST_KEY==3) // если у нас есть долгое нажатие мы считаем что код нагрузки набран и считываем далее сколько было нажатий
{
switch (B)
{
case 1: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 1 РАЗ
(ST_LOAD)=1; // в статус нагрузки заносим 1
break;
case 2: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 2 РАЗА
(ST_LOAD)=2; // в статус нагрузки заносим 2
break;
case 3: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 3 РАЗА
(ST_LOAD)=3; // в статус нагрузки заносим 3
break;
case 4: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 4 РАЗА
(ST_LOAD)=4; // в статус нагрузки заносим 4
break;
case 5: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 5 РАЗ
(ST_LOAD)=5; // в статус нагрузки заносим 5
break;
case 6: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 6 РАЗ
(ST_LOAD)=6; // в статус нагрузки заносим 6
break;
case 7: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 7 РАЗ
(ST_LOAD)=7; // в статус нагрузки заносим 7
break;
case 8: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 8 РАЗ
(ST_LOAD)=8; // в статус нагрузки заносим 8
break;
case 9: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 9 РАЗ
(ST_LOAD)=9; // в статус нагрузки заносим 9
break;
}
B=0; // обнулим счетчик нажатой и отпущеной кнопки
}
return (ST_LOAD); // возвращаем значение
}
//---------------------------------------------------------------------------------------------------------------------------------
void trigger_load(int ST_LOAD ) // функция переключения нагрузки.
{
switch (ST_LOAD)
{
case 1: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 1 РАЗ
PORTx ^= (1 << LED1); // инверсируем состояние пина
break;
case 2: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 2 РАЗА
PORTx ^= (1 << LED2); // инверсируем состояние пина
break;
case 3: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 3 РАЗА
PORTx ^= (1 << LED3); // инверсируем состояние пина
break;
case 4: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 4 РАЗА
PORTx ^= (1 << LED4); // инверсируем состояние пина
break;
case 5: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 5 РАЗ
PORTx ^= (1 << LED5); // инверсируем состояние пина
break;
case 6: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 6 РАЗ
PORTx ^= (1 << LED6); // инверсируем состояние пина
break;
case 7: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 7 РАЗ
PORTx ^= (1 << LED7); // инверсируем состояние пина
break;
case 8: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 8 РАЗ
PORTx |=(1 << LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4) | (1<<LED5) | (1<<LED6) | (1<<LED7); // установим пины с 1 по 7 в еденицу
break;
case 9: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 9 РАЗ
PORTx &= ~((1<<LED1)|(1 << LED2)|(1 << LED3)|(1 << LED4)|(1 << LED5)|(1 << LED6)|(1 << LED7)); // пины с 1 по 7 сброшены в ноль
break;
}
}
//---------------------------------------------------------------------------------------------------------------------------------
ISR(TIMER0_OVF_vect) // прерывание по переполнению таймера
{
sis_taimer =1; // установим в 1 переменную нашего системного таймера
}
//----------------------------------------------------------------------------------------------------------------------------------
int main(void)
{
DDRD = ~(1 << KEY1); // бит РВ0 конфигурируем как вход
PORTD = (1 << KEY1); // вход подтянем
TIMSK0 = 0b00000001; // бит РВ0(TOIE0) устанавливаем в 1, разрешения прерывания по переполнению таймера /счетчика Т0
TCCR0A = 0b00000000; // биты (WGM02,WGM01,WGM00) сбрасываем в 0, настройка режима Normal
TCCR0B = 0b00000011; // настраиваем предделитель на 64 (биты CS02=0,CS01=1,CS00=1),бит В3(WGM02) сбрасываем в 0,режим Normal
GTCCR = 0b00000001; // бит РВ0(PSRSYNC) устанавливаем в 1, Сброс предделителя TO (сбрасываем пред. в конце настроек)
sei(); // Разрешить прерывания
while (1) // Основной цикл программы
{
if (sis_taimer ==1) // Если системный таймер равен 1 то выполняется Код1, будет срабатывать по тику прерывания таймера (наш системный таймер)
{
int ST_KEY1 = 0; // объявляем локальную переменную --- в нее будем загружать возвращаемое значение функции (status_buttons)
int ST_LOAD1 = 0; // объявляем локальную переменную --- в нее будем загружать возвращаемое значение функции (Key_management)
ST_KEY1 = status_buttons( KEY1,PINx1); // вызываем функцию (status_buttons) передаем в нее фактические параметры и присваиваем результат выполнения функции переменной (ST_KEY1)
ST_LOAD1 = Key_management( ST_KEY1); // вызываем функцию (Key_management) передаем в нее фактические параметры и присваиваем результат выполнения функции переменной (ST_LOAD1)
trigger_load( ST_LOAD1 ); // функция переключения нагрузки
sis_taimer =0; // сбросим таймер и ждем следующего тика системного таймера
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------
Код: Выделить всё
РАЗДЕЛЕНИЕ ПРОГРАММЫ НА ФАЙЛЫ (пилим прогу например на 3 части. Майн, заголовочный H и СИшный с функциями)
в 6 студии делал.
создаешь проект основной проги, потом через меню файл добавляешь заголовочный файл и сишный файл и через меню файл сохраняешь в папке с файлами проекта
все 3 файла должны быть видны в дереве файлов в студии
--
1. создаем проект с майном
2. в меню ФАЙЛ нажимаем первую вкладку СОЗДАТЬ ФАЙЛ там выподет список видов файлов , заголовочный -- include file--, файл СИ -- file C-- и еще 2 не нужных нам.
3. выбираем -- include file -- создаем . вписываем все что нужно в него, то есть дефайны и названия функций с аргументами пример---
status_BTN.h
---------------------------------------------------------------------------------------------------------
#include <avr/io.h>
#ifndef status_boot
#define status_boot
#define KEY1 PD0 // пин В0 теперь зовется key1 пишем наши дефайны а то ругается студия))
#define LED1 PD1 // пин В1 порта В зовется LED1 не находит наши обозваные порты в функциях)
#define LED2 PD2 // пин В2 порта В зовется LED2
#define LED3 PD3 // пин В3 порта В зовется LED3
#define LED4 PD4 // пин В4 порта В зовется LED4
#define LED5 PD5 // пин В5 порта В зовется LED5
#define LED6 PD6 // пин В6 порта В зовется LED6
#define LED7 PD7 // пин В7 порта В зовется LED7
#define PORTx PORTD // наш рабочий портец
#define PINx1 PIND // наш рабочий портец
// Прототипы функций (возвращаемое значение, название, параметры).
int status_buttons(int KEY, int PINx); // не забываем ставить ( ; ) после объявления функции
int Key_management(int ST_KEY);
void trigger_load(int ST_LOAD );
#endif /* status_boot */
------------------------------------------------------------------------------------------------------------
и в меню файл почти последнея вкладка --- переместить в --, нажимаем, выбираем папку с нашим проектом,меняем имя на нормальное какое то ( по умолчанию при создании набор букв)
и сохраняем , в дереве проекта справа сразу появляется наш заголовочный файл и мы спокойны)))
4. также создаем наш СИ файл с самими телами функций.
в меню ФАЙЛ нажимаем первую вкладку СОЗДАТЬ ФАЙЛ там выподет список видов файлов , заголовочный -- include file--, файл СИ -- file C-- и еще 2 не нужных нам.
выбираем -- С file -- создаем . вписываем все что нужно в него, то есть наши функции целиком , пример ---
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <avr/io.h>
#include "status_boot.h"
int status_buttons(int KEY, int PINx) // статус нашей кнопки ( 0-не нажата, 1-нажата, 2-коротко нажата и отпущена, 3-длинно нажата и отпущена).
{
int status_KEY=0; // объявим переменную статуса кнопки
static int counter_ON_press=0; // счетчик нажатого состояния (static это значит при выходе из функции значение в переменной запомнится, 0 один раз инициализируется)
static int counter_OF_press=0; // счетчик не нажатого состояния (static это значит при выходе из функции значение в переменной запомнится, 0 один раз инициализируется)
if (~PINx & (1<<KEY)) // Если (KEY) разряд порта B сброшен,(т.е. кнопка нажата) то выполняется Код1. В противном случае, выполняется Код2.
{
status_KEY =1; // пишем в статус 1 (КНОПКА НАЖАТА)
}
if (PINx & (1 << KEY)) // Если (KEY) разряд порта B установлен,(т.е. кнопка не нажата) то выполняется Код1
{
status_KEY =0; // пишем в статус 0 (КНОПКА НЕ НАЖАТА)
}
if ((status_KEY>=1) && (counter_ON_press) < 230) // если кнопка нажата и счетчик нажатого состояние меньше 230 ( защита от переполнения)
{
(counter_ON_press) ++; // инкрементируем счетчик нажатого состояния
}
if ((counter_ON_press) >=5 && (counter_ON_press) < 100) // если счетчик нажатой кнопки больше или равен 5 и меньше 100, у нас короткое нажатие
{
if ((status_KEY==0) && (counter_OF_press) < 230) // если кнопка не нажата и счетчик не нажатого состояние меньше 230 ( защита от переполнения)
{
(counter_OF_press) ++; // инкрементируем счетчик не нажатого состояния
if (counter_OF_press>=5) // если счетчик не нажатой кнопки больше или равен 5 , то считаем кнопка у нас была нажата и отпущена
{
status_KEY =2; // пишем в статус 2 (КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА)
counter_ON_press=0; // обнуляем счетчик
counter_OF_press=0; // обнуляем счетчик
}
}
}
if ((counter_ON_press) >=100 && (counter_ON_press) < 500) // если счетчик нажатой кнопки больше или равен 40 и меньше 200, у нас длинное нажатие
{
if ((status_KEY==0) && (counter_OF_press) < 230) // если кнопка не нажата и счетчик не нажатого состояние меньше 230 ( защита от переполнения)
{
(counter_OF_press) ++; // инкрементируем счетчик не нажатого состояния
if (counter_OF_press>=5) // если счетчик не нажатой кнопки больше или равен 5 , то считаем кнопка у нас была нажата и отпущена
{
status_KEY =3; // пишем в статус 3 (КНОПКА ДЛИННО НАЖАТА И ОТПУЩЕНА)
counter_ON_press=0; // обнуляем счетчик
counter_OF_press=0; // обнуляем счетчик
}
}
}
return (status_KEY); // возвращаем значение статуса кнопки в вызов
}
int Key_management(int ST_KEY) // функция считает количество нажатий и выдает статус нагрузки ( какую нагрузку включить или выключить )
{
int ST_LOAD=0; // объявим переменную СТАТУС НАГРУЗКИ ее используем для выдачи значения из нашей функции
static int B=0; // объявим переменную (static) счетчик НАЖАТОЙ И ОТПУЩЕНОЙ кнопки (переменная при выходе из функции сохранит значение)
if (ST_KEY==2) // если кнопка нажата и отпущена
{
(B) ++; // инкрементируем счетчик нажатой и отпущеной кнопки
}
if (ST_KEY==3) // если у нас есть долгое нажатие мы считаем что код нагрузки набран и считываем далее сколько было нажатий
{
switch (B)
{
case 1: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 1 РАЗ
(ST_LOAD)=1; // в статус нагрузки заносим 1
break;
case 2: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 2 РАЗА
(ST_LOAD)=2; // в статус нагрузки заносим 2
break;
case 3: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 3 РАЗА
(ST_LOAD)=3; // в статус нагрузки заносим 3
break;
case 4: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 4 РАЗА
(ST_LOAD)=4; // в статус нагрузки заносим 4
break;
case 5: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 5 РАЗ
(ST_LOAD)=5; // в статус нагрузки заносим 5
break;
case 6: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 6 РАЗ
(ST_LOAD)=6; // в статус нагрузки заносим 6
break;
case 7: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 7 РАЗ
(ST_LOAD)=7; // в статус нагрузки заносим 7
break;
case 8: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 8 РАЗ
(ST_LOAD)=8; // в статус нагрузки заносим 8
break;
case 9: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 9 РАЗ
(ST_LOAD)=9; // в статус нагрузки заносим 9
break;
}
B=0; // обнулим счетчик нажатой и отпущеной кнопки
}
return (ST_LOAD); // возвращаем значение
}
void trigger_load(int ST_LOAD ) // функция переключения нагрузки.
{
switch (ST_LOAD)
{
case 1: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 1 РАЗ
PORTx ^= (1 << LED1); // инверсируем состояние пина
break;
case 2: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 2 РАЗА
PORTx ^= (1 << LED2); // инверсируем состояние пина
break;
case 3: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 3 РАЗА
PORTx ^= (1 << LED3); // инверсируем состояние пина
break;
case 4: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 4 РАЗА
PORTx ^= (1 << LED4); // инверсируем состояние пина
break;
case 5: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 5 РАЗ
PORTx ^= (1 << LED5); // инверсируем состояние пина
break;
case 6: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 6 РАЗ
PORTx ^= (1 << LED6); // инверсируем состояние пина
break;
case 7: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 7 РАЗ
PORTx ^= (1 << LED7); // инверсируем состояние пина
break;
case 8: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 8 РАЗ
PORTx |=(1 << LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4) | (1<<LED5) | (1<<LED6) | (1<<LED7); // установим пины с 1 по 7 в еденицу
break;
case 9: // КНОПКА КОРОТКО НАЖАТА И ОТПУЩЕНА 9 РАЗ
PORTx &= ~((1<<LED1)|(1 << LED2)|(1 << LED3)|(1 << LED4)|(1 << LED5)|(1 << LED6)|(1 << LED7)); // пины с 1 по 7 сброшены в ноль
break;
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5. и в меню файл почти последнея вкладка --- переместить в --, нажимаем, выбираем папку с нашим проектом,меняем имя на нормальное какое то ( по умолчанию при создании набор букв)
и сохраняем , в дереве проекта справа сразу появляется наш заголовочный файл и мы спокойны)))
6. все нажимаем построить решение и наслаждаемся рабочей программой))))