|
Поддержи наш сайт! |
Через WebMoney
R785211844650
Z210696637574
E368177590409
|
|  | | | |
Приращение переменной, при внешних прерываниях (1 просматривает)
|
|
TOPIC: Приращение переменной, при внешних прерываниях
|
Spacelabus (Пользователь)
Новичок
Постов: 10
|
| Приращение переменной, при внешних прерываниях 25.07.2011 10:52 |
Репутация: 0   |
Доброго времени суток. Без вступления перейду сразу к вопросу: Пытаюсь сделать так, чтобы при каждом нажатии на кнопку без фиксации переменная, отвечающая за задержку при мигании светодиодом увеличивалась на какое либо постоянное значение. | Code: | #define F_CPU 1000000UL // 1 MHz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned char a=20;
int main(void)
{
GICR=1<<INT0;
MCUCR=0<<ISC01|0<<ISC00;
DDRD=0;
PORTD=255;
DDRB=255;
PORTB=0;
while(1)
{
sei();
PORTB=(1<<PB0);
_delay_ms(a);
PORTB=(0<<PB0);
_delay_ms(a);}
ISR(INT0_vect);
{
a++;}}
|
Получилось такое чудо, компилируется нормально, но переменная не возрастает, то есть задержка не увеличивается. Я с прерываниями имею дело первый раз, так что кажется, что ошибка связанна с инициализацией, или объявлением процедуры прерывания. Работаю в winavr. Схема проще некуда :Диод у меня идет с 14(PD2) ножки на землю, кнопочка с 4 ножки (INT0) на землю.
В общем когда тыкаю на кнопку прерывания, светодиод реагирует(гаснет, пока кнопка зажата), но инкремент не растет, если же в процедуре прерывания напишу PORTB=255, диод нормально загорается. Так что, как я понял, переменная в процедуре прерывания не связана с переменной в цикле? Что можно сделать?
Буду рад посильной помощи.
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
ARV (Администратор)
Администратор
Постов: 2027
|
| В ответ на: Приращение переменной, при внешних прерываниях 25.07.2011 11:38 |
Репутация: 167   |
|
макрос обработки прерывания ISR у вас как оказался внутри функции main?! sei() внутри цикла - зачем?! и еще: не забывайте, что по нажатию кнопки может происходить дребезг, т.е. генерация нескольких запросов прерывания. то есть приращение переменной будет довольно непредсказуемым.
Содержимое поста отредактировано: ARV, в: 25.07.2011 11:40
Не стыдно не знать, стыдно не учиться
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
Spacelabus (Пользователь)
Новичок
Постов: 10
|
| В ответ на: Приращение переменной, при внешних прерываниях 25.07.2011 12:03 |
Репутация: 0   |
|
Да, именно в этом и была проблема, все поправил, спасибо за оперативный ответ. Но вот теперь новая трудность: переменная, дойдя до какого то значения когда стоит volatile unsigned char сбрасывается на начальное значение и даже перегоняет его, то есть как бы идет по замкнутому кругу, когда стоит volatile unsigned int то дойдя до какого то значения останавливается и дальше задержка не увеличивается Я так понимаю, что в задержке _delay_ms() нельзя писать значение больше 1000? Как тогда быть, если я хочу использовать больший диапазон значений?
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
ARV (Администратор)
Администратор
Постов: 2027
|
| В ответ на: Приращение переменной, при внешних прерываниях 25.07.2011 12:11 |
Репутация: 167   |
|
во-первых, в _delay_ms() вообще НЕЖЕЛАТЕЛЬНО использовать переменные - вы обратили внимание, какого размера получается ваш код? во-вторых, unsigned char - это всего-навсего число не более 255, а в Си нет никаких средств "контроля переполнения", поэтому 255 + 2 = 1, а вовсе не 257. если вам надо ограничивать значение - делайте это программно: if(a < 255) a++; // не более 255 в-третьих, у _delay_ms, конечно, есть ограничения на максимальную задержку, но скорее всего вы забыли, что пока задержка в вашем коде не отработает, изменение переменной никак не отразится на программе. то есть вы начали отрабатывать задержку в 1 секунду, и снова нажали кнопку: т.к. задержка продолжает отсчитываться, по нажатию вы не видите никаких изменений, и жмете еще раз, и еще... с учетом дребезга вы "наувеличивали" переменную, скажем, не на 1, а на 100, но все равно по сравнению с 1000 мс это всего-навсего 10% прирост, и вы его можете попросту не заметить.
Содержимое поста отредактировано: ARV, в: 25.07.2011 12:15
Не стыдно не знать, стыдно не учиться
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
Spacelabus (Пользователь)
Новичок
Постов: 10
|
| В ответ на: Приращение переменной, при внешних прерываниях 25.07.2011 12:43 |
Репутация: 0   |
Проблема сейчас в следующем: В _delay_ms() ставлю задержку скажем 3000, без переменной, т.е. задержка должна быть 3 секунды, а он у меня мигает слишком шустро, будто бы там стоит ~300-400. Прерываниями не пользуюсь, просто работает цикл. | Code: | #define F_CPU 1000000UL // 1 MHz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned int a=20;
ISR(INT0_vect)
{
a--;}
int main(void)
{
GICR=1<<INT0;
MCUCR=0<<ISC01|0<<ISC00;
DDRD=0;
PORTD=255;
DDRB=255;
PORTB=0;
while(1)
{
sei();
PORTB=(1<<PB0);
_delay_ms(3000);
PORTB=(0<<PB0);
_delay_ms(3000);}}
|
Вот так это все выглядит.
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
Spacelabus (Пользователь)
Новичок
Постов: 10
|
| В ответ на: Приращение переменной, при внешних прерываниях 25.07.2011 12:48 |
Репутация: 0   |
|
Причем, если ставлю несколько задержек подряд, все нормально. Но вот раньше я точно мог написать _delay_ms(2000) и задержка была бы 2 секунды. Отсюда и вопрос.
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
ARV (Администратор)
Администратор
Постов: 2027
|
| В ответ на: Приращение переменной, при внешних прерываниях 25.07.2011 13:01 |
Репутация: 167   |
|
а вы уверены, что у вас реальная тактовая частота МК совпадает с той, что задана в проекте?
Не стыдно не знать, стыдно не учиться
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
Spacelabus (Пользователь)
Новичок
Постов: 10
|
| В ответ на: Приращение переменной, при внешних прерываниях 25.07.2011 13:19 |
Репутация: 0   |
Попробовал разные, и 8 и 20 мгц, все то же. Порылся в delay.h Thus, at a CPU sped of 1MHz, delays of up to about 262.1 milliseconds can be achieved. Вроде бы похоже на правду. Примерно такая задержка и получается, что с этим можно сделать?
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
ARV (Администратор)
Администратор
Постов: 2027
|
| В ответ на: Приращение переменной, при внешних прерываниях 25.07.2011 13:33 |
Репутация: 167   |
Spacelabus писал(а):Попробовал разные, и 8 и 20 мгц, все то же. Порылся в delay.h Thus, at a CPU sped of 1MHz, delays of up to about 262.1 milliseconds can be achieved. Вроде бы похоже на правду. Примерно такая задержка и получается, что с этим можно сделать? плоховато вы порылись в документации: The maximal possible delay is 262.14 ms / F_CPU in MHz.
When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.до 262,14 миллисекунд задержка отрабатывается точно, а для бОльших значений - более грубыми шагами, т.е. с меньшей точностью, но зато можно делать задержки аж до 6,5 секунд. ищите проблему не в этих функциях, где-то она в другом месте.
Не стыдно не знать, стыдно не учиться
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
Spacelabus (Пользователь)
Новичок
Постов: 10
|
| В ответ на: Приращение переменной, при внешних прерываниях 25.07.2011 13:45 |
Репутация: 0   |
|
Нет, нет, в том Delay.h так и было. Я дернул другой, тоже заметил 6.5 секунд, все заработало, спасибо за помощь. У меня просто WinAvr 2000 года что ли, наверное с этим связанно.
|
|
|
|
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
|
|
|
|
| | |  |
|