включение нагрузки 1 кнопкой без фиксации, на МК
Уррааа))) заработало) NStorm, спасибо большое) наконец я поверил в указатели))
глаза боятся, а руки что то не делают))
- Реклама
AVR вот вроде написал рабочий код с помощью ваших советов. В этот раз тоже не очень получилось? или получше?
код занял 350 байт
на астме получилось 90 байт
Код: Выделить всё
//ТИНИ_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); //вызовем процедуру управлением нагрузкой
}
//----------------------------------------------------------------------------------------------------------------------------------
код занял 350 байт
на астме получилось 90 байт
глаза боятся, а руки что то не делают))
у меня другой ник, обращаю ваше внимание.sergo80zxc писал(а):AVR вот вроде написал рабочий код с помощью ваших советов.
и советы я вам давал немного другие - ваш код продолжает борьбу с прерываниями, и от моих советов практически не поменялся.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
ARV, простите за ник) на делай и без прерываний я код же сделал) статью вашу прочитал, советы изучил, спасибо большое, действительно проще от большего к меньшему) ну а в большинстве случаев мк хватает чем заняться в основном цикле, поэтому наверное все эти делай побаловаться если только или что то простое. на астме я писал старался без всяких задержек, через таймеры в основном опросы кнопок, простые действия, в общем по максимуму навешивал на таймеры) поэтому и на си хочу писать с расчетом на многозадачность ( опрос кнопок, вывод на индикатор символов, опрос датчиков и т.д.) поэтому мне очень важны ваши советы, например на счет дефайнов, указателей, алгоритму, магических чисел)))
глаза боятся, а руки что то не делают))
Товарищи что то я рогом уперся и никак не осилю разделение программы на файлы. хочу отдельно сделать файл майн, заголовочный и сишный с функциями, при компиляции атмел студия 6 пишет ошибки аж 3 штуки
(Ошибка 1 undefined reference to `status_buttons' C:\avr-proekt-6\GccApplication22\GccApplication22\Debug/.././GccApplication22.c 85 1 GccApplication22)
(Ошибка 2 undefined reference to `Key_management' C:\avr-proekt-6\GccApplication22\GccApplication22\Debug/.././GccApplication22.c 87 1 GccApplication22
)
(Ошибка 3 undefined reference to `trigger_load' C:\avr-proekt-6\GccApplication22\GccApplication22\Debug/.././GccApplication22.c 89 1 GccApplication22
)
сама студия файлы все видит, отображаются в списке
status_boot.h
status_boot.с
Добавлено after 7 minutes 47 seconds:
забыл добавить, вот сама программа , которую хочу разбить на блоки
(Ошибка 1 undefined reference to `status_buttons' C:\avr-proekt-6\GccApplication22\GccApplication22\Debug/.././GccApplication22.c 85 1 GccApplication22)
(Ошибка 2 undefined reference to `Key_management' C:\avr-proekt-6\GccApplication22\GccApplication22\Debug/.././GccApplication22.c 87 1 GccApplication22
)
(Ошибка 3 undefined reference to `trigger_load' C:\avr-proekt-6\GccApplication22\GccApplication22\Debug/.././GccApplication22.c 89 1 GccApplication22
)
сама студия файлы все видит, отображаются в списке
Код: Выделить всё
/*
* 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; // сбросим таймер и ждем следующего тика системного таймера
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------
status_boot.h
Код: Выделить всё
#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; // сбросим таймер и ждем следующего тика системного таймера
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------
- Вложения
-
- Захват-1.jpg
- (156.39 КБ) 177 скачиваний
глаза боятся, а руки что то не делают))
- Реклама
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
Status_boot.с в проект точно добавлен? Status_buttons() в нем определена, а судя по ошибке вроде как и нет.
Захват-1.jpg скрин, да что то не вижу его((
глаза боятся, а руки что то не делают))
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
[uquote="sergo80zxc",url="/forum/viewtopic.php?p=3888118#p3888118"]да что то не вижу его(([/uquote]
Ну и? Сложно файл в проект добавить?
Ну и? Сложно файл в проект добавить?
Reflector спасибо) не обратил внимание на то, что не висит файлик в дереве)
для новичков таких как я напишу как кусочить прогу) чтоб с ума не сходили)
Добавлено after 3 minutes 2 seconds:
примерно так выглядит, все три файла видны Захват-2.jpg
для новичков таких как я напишу как кусочить прогу) чтоб с ума не сходили)
Код: Выделить всё
РАЗДЕЛЕНИЕ ПРОГРАММЫ НА ФАЙЛЫ (пилим прогу например на 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. все нажимаем построить решение и наслаждаемся рабочей программой))))
примерно так выглядит, все три файла видны Захват-2.jpg
- Вложения
-
- Захват-2.jpg
- (207.03 КБ) 169 скачиваний
глаза боятся, а руки что то не делают))
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Убирай свои простыни под спойлер. У меня уже от них тик на левом глазу. Цикл статей Татарчевского. И не появляйся на форуме, пока весь цикл не проштудируешь. Я тебе пример давал, ты не внял. А сейчас насилуешь всех участников своими простынями.
Demiurg я как раз и изучаю ваш код)) я все ваши файлики себе скачал) и пытаюсь прийти к модульности . а вот кбд_дрв и куча разных имен меня с толку сбивают, я как то привык а, в, с... пока тяжко идет , не пойму почему так тяжко воспринимается, смотрел у парней код то тат то там вроде как понимаю)
глаза боятся, а руки что то не делают))
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Все просто. Kbd_drv это целая логическая цепочка. Название из DOS. KEYBOARD DRIVER. Я, когда написал первую рабочую реализацию опроса кнопок на конечных автоматах, прыгал от радости. Преувеличил, конечно. Но радовался сильно.
И я тогда так обозвал эти программные модули.
На модули нужно разделять логически. Дисплей аппаратная часть отдельно, опрос кнопок, клавиатуры отдельно.
Названия переменных, пинов мк, функций и так далее нужно обзывать понятными именами. Даже если выходят и длинными. Это облегчает читабельность программ. В том числе и собственных...
А цикл статей перечитайте. Именно после прочтения этого цикла у меня произошёл значительный сдвиг в создании проектов. Конечные автоматы, программные таймеры. Опрос матричной клавиатуры.
На модули нужно разделять логически. Дисплей аппаратная часть отдельно, опрос кнопок, клавиатуры отдельно.
Названия переменных, пинов мк, функций и так далее нужно обзывать понятными именами. Даже если выходят и длинными. Это облегчает читабельность программ. В том числе и собственных...
А цикл статей перечитайте. Именно после прочтения этого цикла у меня произошёл значительный сдвиг в создании проектов. Конечные автоматы, программные таймеры. Опрос матричной клавиатуры.
Demiurg спасибо , штудирую) переписываю конспектами себе этот цикл статей
глаза боятся, а руки что то не делают))


