Я тут призадумался...
А можно сделать так чтобы при нажатии кнопки менялась пауза (при этом работая с делеем без таймера ), дело в том что если в скобки _deley_ms() ставишь переменную, то компилятор начинает материться, если задаешь значение например U через дефаин то все работает, но менять значения U уже нельзя . Значит нужно изучать таймеры??
61. Andrey 2004 - 17 Марта, 2019 - 13:19:45 - перейти к сообщению
62. Predator - 17 Марта, 2019 - 13:35:20 - перейти к сообщению
у функции _delay_ms() есть один ядреный недостаток: процессор крутится в этой функции и никак не может узнать, что-же там с кнопками.
итак рекомендую:
1) разобрать прерывания: для начала повесить прерывание на кнопку, чтобы обработчик заставил переключить светодиод, при этом в основной программе главный цикл пустой.
2) разобраться с дребезгом, чтобы одно нажатие было одним нажатием.
3) завести таймер: переключать светодиод по прерыванию от таймера.
для целевого количества миганий, для подсчета количества уже мигнутых ... нужно позаводить глобальных переменных.
итак рекомендую:
1) разобрать прерывания: для начала повесить прерывание на кнопку, чтобы обработчик заставил переключить светодиод, при этом в основной программе главный цикл пустой.
2) разобраться с дребезгом, чтобы одно нажатие было одним нажатием.
3) завести таймер: переключать светодиод по прерыванию от таймера.
для целевого количества миганий, для подсчета количества уже мигнутых ... нужно позаводить глобальных переменных.
63. Andrey 2004 - 17 Марта, 2019 - 15:23:28 - перейти к сообщению
хорошо, на счет делея вроде понял, но а что с этой проблемой делать
Здесь я не знаю о чем и думать, вроде все операторы более менее знаю, а подходящего варианта не нашел .
Andrey 2004 пишет:
Проблема в том что у меня или получается бесконечный цикл (при первом нажатии кнопки цикл замыкается и не реагирует на дальнейшие нажатия);
Или получается сделать все это при помощи For где я действительно могу менять переменную i
,но при этом светодиод мигает до тех пор пока не достигнет значения переменной i а затем гаснет до следующего нажатия кнопки.
Или получается сделать все это при помощи For где я действительно могу менять переменную i
,но при этом светодиод мигает до тех пор пока не достигнет значения переменной i а затем гаснет до следующего нажатия кнопки.
Здесь я не знаю о чем и думать, вроде все операторы более менее знаю, а подходящего варианта не нашел .
64. Predator - 17 Марта, 2019 - 15:59:28 - перейти к сообщению
тут надо конкретно вашу программу смотреть - собственно даже не операторы, а алгоритм.
и да, теперь вы переходите на следующий уровень: от написания операторов к программированию (переход от быдлокодера к программисту).
подозреваю, что в бесконечном цикле крутится по причине того, что внутри цикла в принципе не опрашивает кнопку.
и да, теперь вы переходите на следующий уровень: от написания операторов к программированию (переход от быдлокодера к программисту).
подозреваю, что в бесконечном цикле крутится по причине того, что внутри цикла в принципе не опрашивает кнопку.
65. Andrey 2004 - 17 Марта, 2019 - 16:03:40 - перейти к сообщению
CODE:
#define F_CPU 8000000UL //16MHz
#include <avr/io.h>
#include <util/delay.h>
#define l 10
volatile unsigned char i;
volatile unsigned char p;
int main(void) {
DDRB = 0xFF;
PORTB = 0x00;
DDRD=0x00;
PORTD=0xFF;
i=0;
while(1)
{
if (PIND & (1<<1))
{
_delay_ms(5);
if (PIND & (1<<1))
{
while (PIND & (1<<1)) {}
i++;
_delay_ms(10);
}
}
for(int p=0;p<i;p++)
{
PORTB=0b00000010;
_delay_ms(50);
PORTB=0b00000000;
_delay_ms(50);
}
}
}
#include <avr/io.h>
#include <util/delay.h>
#define l 10
volatile unsigned char i;
volatile unsigned char p;
int main(void) {
DDRB = 0xFF;
PORTB = 0x00;
DDRD=0x00;
PORTD=0xFF;
i=0;
while(1)
{
if (PIND & (1<<1))
{
_delay_ms(5);
if (PIND & (1<<1))
{
while (PIND & (1<<1)) {}
i++;
_delay_ms(10);
}
}
for(int p=0;p<i;p++)
{
PORTB=0b00000010;
_delay_ms(50);
PORTB=0b00000000;
_delay_ms(50);
}
}
}
Вот код от которого я "пляшу"
(Добавление)
сейчас скину свои неудачные варианты
(Добавление)
В принципе все мои попытки сводятся к одному соединить фор который может считать кол во
миганий и ваил который зацикливает что либо.Вот один из моих "кодов":
CODE:
#define F_CPU 8000000UL //16MHz
#include <avr/io.h>
#include <util/delay.h>
#define l 10
volatile unsigned char i;
volatile unsigned char p;
int main(void) {
DDRB = 0xFF;
PORTB = 0x00;
DDRD=0x00;
PORTD=0xFF;
i=0;
while(1)
{
if (PIND & (1<<1))
{
_delay_ms(5);
if (PIND & (1<<1))
{
while (PIND & (1<<1)) {}
i++;
_delay_ms(10);
}
}
while (PIND & (1<<1))
{
for (p=0;p<i;p++)
{
PORTB=0b00000010;
_delay_ms(50);
PORTB=0b00000000;
_delay_ms(50);
if (PIND & (1<<1))
{
i++;
}
_delay_ms(200);
}
}
}
}
#include <avr/io.h>
#include <util/delay.h>
#define l 10
volatile unsigned char i;
volatile unsigned char p;
int main(void) {
DDRB = 0xFF;
PORTB = 0x00;
DDRD=0x00;
PORTD=0xFF;
i=0;
while(1)
{
if (PIND & (1<<1))
{
_delay_ms(5);
if (PIND & (1<<1))
{
while (PIND & (1<<1)) {}
i++;
_delay_ms(10);
}
}
while (PIND & (1<<1))
{
for (p=0;p<i;p++)
{
PORTB=0b00000010;
_delay_ms(50);
PORTB=0b00000000;
_delay_ms(50);
if (PIND & (1<<1))
{
i++;
}
_delay_ms(200);
}
}
}
}
66. Predator - 18 Марта, 2019 - 10:08:34 - перейти к сообщению
В первом случае у вас происходит проверка нажатия кнопки, после отпускания фиксируется факт нажатия и только тогда программа продолжает работать дальше.
Есть еще нюанс: в процессе мигания светодиодом (в цикле p=0;p<i;p++) проверка кнопки не происходит, то есть нужно нажать и держать пока не промигается.
Во втором случае чуть хуже: вы проверяете нажатие кнопки, после отпускания фиксируется факт нажатия и только тогда программа продолжает работать дальше. (пока как в первом случае)
А дальше, через 10 мс, в случае нажатой кнопки вы начинаете мигать, иначе снова проверять нажатие фиксировать. В общем чтобы начать мигать надо отпустить кнопку и за 10 мс успеть обратно нажать. Рекомендую перевести эту задачу на другую кнопку.
Есть еще нюанс: в процессе мигания светодиодом (в цикле p=0;p<i;p++) проверка кнопки не происходит, то есть нужно нажать и держать пока не промигается.
Во втором случае чуть хуже: вы проверяете нажатие кнопки, после отпускания фиксируется факт нажатия и только тогда программа продолжает работать дальше. (пока как в первом случае)
А дальше, через 10 мс, в случае нажатой кнопки вы начинаете мигать, иначе снова проверять нажатие фиксировать. В общем чтобы начать мигать надо отпустить кнопку и за 10 мс успеть обратно нажать. Рекомендую перевести эту задачу на другую кнопку.
67. Andrey 2004 - 20 Марта, 2019 - 19:10:48 - перейти к сообщению
Благодарю за помощь!!!
Но мне кажется, что для решения моей последней задачи нужно изучить прерывания.
Тогда без лишних мучений можно будет написать этот код правильно.
Но мне кажется, что для решения моей последней задачи нужно изучить прерывания.
Тогда без лишних мучений можно будет написать этот код правильно.
68. Andrey 2004 - 26 Марта, 2019 - 19:44:09 - перейти к сообщению
Все сделал программу при помощи прерывания вот что получилось:
Что смутило, у меня при попадании в "прерывание" процессор не просто "проходит" по коду
единожды, а выполняет этот код в течении некоторого времени. Таким образом, когда я в цикл прерывания писал просто " i++;" без задержки, процессор при первом нажатии кнопки PD3 присваивал переменной "i" не "1",а "41".
Так и должно быть??
CODE:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile unsigned char i;
volatile unsigned char p;
ISR(INT1_vect)
{
i++;
_delay_ms(30);
}
int main(void)
{
DDRB |=(1<<1);
PORTB &=~(1<<1);
DDRD &=~(1<<3);
PORTD |=(1<<3);
i=0;
GICR |=(1<<7);// Разрешаем прерывание INT1
MCUCR =0b00000010;// Генерация сигнала при низком уровне на ножке PD3
sei();//Разрешить прерывания
while(1)
{
_delay_ms(50);
for(p=0;p<i;p++)
{
PORTB|=(1<<1);
_delay_ms(15);
PORTB &=~(1<<1);
_delay_ms(15);
}
}
}
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile unsigned char i;
volatile unsigned char p;
ISR(INT1_vect)
{
i++;
_delay_ms(30);
}
int main(void)
{
DDRB |=(1<<1);
PORTB &=~(1<<1);
DDRD &=~(1<<3);
PORTD |=(1<<3);
i=0;
GICR |=(1<<7);// Разрешаем прерывание INT1
MCUCR =0b00000010;// Генерация сигнала при низком уровне на ножке PD3
sei();//Разрешить прерывания
while(1)
{
_delay_ms(50);
for(p=0;p<i;p++)
{
PORTB|=(1<<1);
_delay_ms(15);
PORTB &=~(1<<1);
_delay_ms(15);
}
}
}
Что смутило, у меня при попадании в "прерывание" процессор не просто "проходит" по коду
единожды, а выполняет этот код в течении некоторого времени. Таким образом, когда я в цикл прерывания писал просто " i++;" без задержки, процессор при первом нажатии кнопки PD3 присваивал переменной "i" не "1",а "41".
Так и должно быть??
69. Predator - 26 Марта, 2019 - 22:31:34 - перейти к сообщению
Так и должно быть??
Это и есть дребезг контактов.
41 раз переколбасилась кнопка (контачит-не контачит) -> прерывание 41 раз вызвалось и отработало.
задержка и есть решение этой проблемы, на мой взгляд оптимальное, только я еще после задержки перепроверяю, что юзер всё еще держит кнопку, а не это помеха проскочила.
Это и есть дребезг контактов.
41 раз переколбасилась кнопка (контачит-не контачит) -> прерывание 41 раз вызвалось и отработало.
задержка и есть решение этой проблемы, на мой взгляд оптимальное, только я еще после задержки перепроверяю, что юзер всё еще держит кнопку, а не это помеха проскочила.
70. Andrey 2004 - 27 Марта, 2019 - 08:11:46 - перейти к сообщению
Мда... Про то что здесь может быть дребезг я и забыл.
Сейчас сижу балуюсь с внешними прерываниями, и вдруг понимаю что мне их не хватает,
в смысле не "их" а их количества . А есть помимо INT0 и INT1 другие виды внешних прерываний???
Сейчас сижу балуюсь с внешними прерываниями, и вдруг понимаю что мне их не хватает,
в смысле не "их" а их количества . А есть помимо INT0 и INT1 другие виды внешних прерываний???
71. Predator - 27 Марта, 2019 - 09:19:19 - перейти к сообщению
В обработчике можно проводить анализ на тему "что случилось", если не хватает именно ног с прерываниями - тут сложнее.
Если собираетесь просто много кнопок насобирать, то их можно опрашивать по прерыванию от таймера, на 10 ног можно навесить 25 кнопок (5 строк-5столбцов).
Если собираетесь просто много кнопок насобирать, то их можно опрашивать по прерыванию от таймера, на 10 ног можно навесить 25 кнопок (5 строк-5столбцов).
72. Andrey 2004 - 27 Марта, 2019 - 13:39:55 - перейти к сообщению
Да, пока не хватает именно ног с прерываниями. Можете объяснить как проводить этот анализ?
73. Predator - 27 Марта, 2019 - 13:49:35 - перейти к сообщению
если именно ног не хватает - не поможет.
Анализ - да всё просто (у пиков 16 - вообще одно прерывание на все случаи жизни) попадаем в обработчик и последовательно осматриваем регистры модулей, ищем кто вызвал.
С кнопками - примерно так:
сработало прерывание на таймер (пусть каждые 100 мс) - проверяем, что там с портом, если нажата кнопка - обрабатываем нажатие.
Если нужно обрабатывать не кнопку - тут сложнее, всё зависит от срочности реакции.
Анализ - да всё просто (у пиков 16 - вообще одно прерывание на все случаи жизни) попадаем в обработчик и последовательно осматриваем регистры модулей, ищем кто вызвал.
С кнопками - примерно так:
сработало прерывание на таймер (пусть каждые 100 мс) - проверяем, что там с портом, если нажата кнопка - обрабатываем нажатие.
Если нужно обрабатывать не кнопку - тут сложнее, всё зависит от срочности реакции.
74. Andrey 2004 - 27 Марта, 2019 - 18:41:38 - перейти к сообщению
Predator пишет:
С кнопками - примерно так:
сработало прерывание на таймер (пусть каждые 100 мс) - проверяем, что там с портом, если нажата кнопка -
сработало прерывание на таймер (пусть каждые 100 мс) - проверяем, что там с портом, если нажата кнопка -
Спасибо, понял, наверно так и сделаю.
(Добавление)
Вот сделал программу для семисегментного индикатора:
CODE:
//-----------------------------***Семисигментный индикатор c массивом***-----------------------------//
# define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define razriad PORTC
#define chislo PORTB
unsigned int razr1 = 0, razr2 = 0, razr3 = 0, razr4 = 0;
unsigned char LOL;
//----------------------------------------------------------------------------------------//
ISR(TIMER0_OVF_vect)
{
if (LOL == 1) {razriad = 0b00000001; chislo = chisla [razr1];}
if (LOL == 2) {razriad = 0b00000010; chislo = chisla [razr2];}
if (LOL == 3) {razriad = 0b00000100; chislo = chisla [razr3];}
if (LOL == 4) {razriad = 0b00001000; chislo = chisla [razr4];}
LOL++;
if( LOL > 4 ) LOL = 0;
}
int chisla [10]=
{
0b00111111,//0
0b00000110,//1
0b01011011,//2
0b01001111,//3
0b01100110,//4
0b01101101,//5
0b01111101,//6
0b00000111,//7
0b01111111,//8
0b01101111,//9
};
void vse_chislo (unsigned int razbivka_chisla)
{
razr1 = razbivka_chisla/1000;//тысячи
razr2 = razbivka_chisla%1000/100;//сотни
razr3 = razbivka_chisla%100/10;//десятки
razr4 = razbivka_chisla%10;//еденицы
}
int main(void)
{
DDRC=0xFF;
PORTC=0x00;
DDRB=0xFF;
PORTB=0x00;
TCCR0|=(1<<1); TCCR0&= ~ ((1<<0)|(1<<2));
TIMSK|=(1<<0);
TCNT0 = 0;
sei();
//----------------------------------------------------------------------------------------//
razriad=0b00000001;
chislo = 0b00111111;
while(1)
{
vse_chislo (1987);
}
}
# define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define razriad PORTC
#define chislo PORTB
unsigned int razr1 = 0, razr2 = 0, razr3 = 0, razr4 = 0;
unsigned char LOL;
//----------------------------------------------------------------------------------------//
ISR(TIMER0_OVF_vect)
{
if (LOL == 1) {razriad = 0b00000001; chislo = chisla [razr1];}
if (LOL == 2) {razriad = 0b00000010; chislo = chisla [razr2];}
if (LOL == 3) {razriad = 0b00000100; chislo = chisla [razr3];}
if (LOL == 4) {razriad = 0b00001000; chislo = chisla [razr4];}
LOL++;
if( LOL > 4 ) LOL = 0;
}
int chisla [10]=
{
0b00111111,//0
0b00000110,//1
0b01011011,//2
0b01001111,//3
0b01100110,//4
0b01101101,//5
0b01111101,//6
0b00000111,//7
0b01111111,//8
0b01101111,//9
};
void vse_chislo (unsigned int razbivka_chisla)
{
razr1 = razbivka_chisla/1000;//тысячи
razr2 = razbivka_chisla%1000/100;//сотни
razr3 = razbivka_chisla%100/10;//десятки
razr4 = razbivka_chisla%10;//еденицы
}
int main(void)
{
DDRC=0xFF;
PORTC=0x00;
DDRB=0xFF;
PORTB=0x00;
TCCR0|=(1<<1); TCCR0&= ~ ((1<<0)|(1<<2));
TIMSK|=(1<<0);
TCNT0 = 0;
sei();
//----------------------------------------------------------------------------------------//
razriad=0b00000001;
chislo = 0b00111111;
while(1)
{
vse_chislo (1987);
}
}
Но при компиляции выдает ошибку:
Error 'chisla' undeclared (first use in this function)
При двойном щелчке кидает вот сюда:
CODE:
if (LOL == 1) {razriad = 0b00000001; chislo = (сюда)chisla [razr1];}
Что не так ??
75. Predator - 27 Марта, 2019 - 20:10:59 - перейти к сообщению
CODE:
int chisla [10]=
{
0b00111111,//0
0b00000110,//1
0b01011011,//2
0b01001111,//3
0b01100110,//4
0b01101101,//5
0b01111101,//6
0b00000111,//7
0b01111111,//8
0b01101111,//9
};
int chisla [10]=
{
0b00111111,//0
0b00000110,//1
0b01011011,//2
0b01001111,//3
0b01100110,//4
0b01101101,//5
0b01111101,//6
0b00000111,//7
0b01111111,//8
0b01101111,//9
};
перенесите выше, чем
CODE:
ISR(TIMER0_OVF_vect)
{
if (LOL == 1) {razriad = 0b00000001; chislo = chisla [razr1];}
if (LOL == 2) {razriad = 0b00000010; chislo = chisla [razr2];}
if (LOL == 3) {razriad = 0b00000100; chislo = chisla [razr3];}
if (LOL == 4) {razriad = 0b00001000; chislo = chisla [razr4];}
LOL++;
if( LOL > 4 ) LOL = 0;
}
ISR(TIMER0_OVF_vect)
{
if (LOL == 1) {razriad = 0b00000001; chislo = chisla [razr1];}
if (LOL == 2) {razriad = 0b00000010; chislo = chisla [razr2];}
if (LOL == 3) {razriad = 0b00000100; chislo = chisla [razr3];}
if (LOL == 4) {razriad = 0b00001000; chislo = chisla [razr4];}
LOL++;
if( LOL > 4 ) LOL = 0;
}
иначе вы сперва используете, потом объявляете. Некоторые компиляторы умеют такое разруливать, но это скорее исключение.