Форум myROBOT.ru » Шаг за шагом » Программирование микроконтроллеров » Почему не работает код

Страниц (2): [1] 2 »
 

1. Artem - 27 Марта, 2013 - 15:22:59 - перейти к сообщению
Здравствуйте Улыбка
Осваиваю программирование микроконтроллеров, в данный момент разбираюсь с внешними прерываниями. Значит, подключил 2 кнопки, мигаю светодиодами, всё замечательно, но никак не получается реализовать вот этот код:
CODE:
#define F_CPU 1000000UL // указываем частоту в герцах
#include <avr/io.h> // подключаем библиотеку АВР
#include <util/delay.h> // подключаем библиотеку задержек
#include <avr/interrupt.h> // подключаем библиотеку прерываний
#define nop() {asm("nop");}

int s = 50000; // переменная для задержки

unsigned int x;

void delay(int t)
{
for (x=t; x>0 ;x--)
nop ();
}

SIGNAL(SIG_INTERRUPT0)//обработка прерываний INT0
{
cli();//запрещение прерываний на время обработки прерывания

PORTC |=_BV(PC4);

s=s+50000;

_delay_ms(200);

PORTC &=~_BV(PC4);

_delay_ms(200);

sei();//разрешение прерываний
}

SIGNAL(SIG_INTERRUPT1)//обработка прерываний INT1
{
cli();//запрещение прерываний на время обработки прерывания

PORTC |=_BV(PC4);

s=s-50000;

_delay_ms(200);

PORTC &=~_BV(PC4);

_delay_ms(200);

sei();//разрешение прерываний

}

int main(void)
{
DDRC = 0xFF; //все вывод
DDRD = 0x00; //все вход

GICR=0b11000000; //разрешаем прерывание int0 и int1 - кнопка
MCUCR=0b00001010;// int by rising front - для кнопки 1 и 2

sei();//разрешение прерываний

while (1==1)//вечный цикл
{

PORTC |=_BV(PC5);

delay(s);

PORTC &=~_BV(PC5);

delay(s);

}
}

взят он вот отсюда: http://avrlab.com/node/37

вобщем, я убрал светодиодную дорожку и оставил один светодиод, для наглядности, в обработчиках прерываний, помимо изменения переменной мигаю другим светодиодом. так вот в чём проблема: светодиод мигает всегда с одинаковой частотой, не зависимо от того нажимаю я на кнопки или нет, а дожно быть вот как: нажал на кнопку, сработало прерывание, значение переменной s увеличилось на 50000 и светодиод начал мигать реже. При этом, когда я нажимаю на кнопки светодиоды мигают, как описанно в подпрограмме обработчике прерываний. Я не знаю в чём может быть проблема, но наверно она в подпрограмме задержки, я не совсем понимаю, как она работает.
Помогите!!!
заранее спасибо Улыбка
2. elmot - 27 Марта, 2013 - 16:04:56 - перейти к сообщению
как минимум s должно быть volatile
3. Artem - 27 Марта, 2013 - 16:07:14 - перейти к сообщению
А почему? По размеру int вроде тоже подходит?
4. elmot - 27 Марта, 2013 - 16:20:42 - перейти к сообщению
volatile - это не тип данных, это указание компилятору, что переменную надо всегда писать на ее место в памяти. Такой квалификатор необходимо применять к переменным, которые используются более чем из одного потока - в данном случае в нее лазают обработчик прерывания и основной код. Без модификатора компилятор может оптимизировать код и храниить переменную скажем, в регистре.
http://ru.wikipedia.org/wiki/%D0...0%B8%D0%BF%D0%B0
5. Artem - 27 Марта, 2013 - 16:27:54 - перейти к сообщению
А, понятно, сейчас попробуем, но почему у автора статьи нет никакого квалификатора переменной?
(Добавление)
Да, вы правы, теперь всё заработало как нужно высший восторг
Но непонятно одно, почему когда я нажимаю на одну кнопку светодиод мигает всё чаще и чаще( переменная уменьшается) и через некоторое количество нажатий на кнопку светодиод опять начинает мигать с прежней частотой, переменная как бы уменьшается, уменьшается, а затем опять возвращается в первоначальное значение, почему это происходит?
6. killgur - 27 Марта, 2013 - 16:42:12 - перейти к сообщению
А откуда взялось такое значение 50000!?

В прерываниях чаще всего просто устанавливают флаг.

Обработку по флагу надо делать в основной программе,

что то включать выключать в прерывании верный способ словить неприятностей.

Эта программа созданна каким то генератором кода?
7. Artem - 27 Марта, 2013 - 16:45:53 - перейти к сообщению
killgur пишет:
А откуда взялось такое значение 50000!?

число взялось экспериментальным путём, потому что при таком числе повторений программы задержки мигание светодиода становяться различимы.
killgur пишет:
что то включать выключать в прерывании верный способ словить неприятностей.

да, я уже понял, уже убрал включение и выключение светодиода из обработчика прерываний.
killgur пишет:
Эта программа созданна каким то генератором кода?

нет, программа в этом виде написана мной, а вот шаблон взят из ссылки, которую я привёл.
8. killgur - 27 Марта, 2013 - 16:47:18 - перейти к сообщению
Artem пишет:
А, понятно, сейчас попробуем, но почему у автора статьи нет никакого квалификатора переменной?
(Добавление)
Да, вы правы, теперь всё заработало как нужно высший восторг
Но непонятно одно, почему когда я нажимаю на одну кнопку светодиод мигает всё чаще и чаще( переменная уменьшается) и через некоторое количество нажатий на кнопку светодиод опять начинает мигать с прежней частотой, переменная как бы уменьшается, уменьшается, а затем опять возвращается в первоначальное значение, почему это происходит?


Потому как при очередном сложении значение обнулилось т.к. превысило размерность используемого для подсчетов регистра. (или превысило размерность использованного типа данных)

Надо контроль ввести если значение больше предельного то не прибавлять.
9. Artem - 27 Марта, 2013 - 16:51:27 - перейти к сообщению
killgur пишет:
Потому как при очередном сложении значение обнулилось т.к. превысило размерность используемого для подсчетов регистра. (или превысило размерность использованного типа данных)

Надо контроль ввести если значение больше предельного то не прибавлять.


Понятно, значит нужно поменьше значение переменной, а нельзя, в функции задержки, вместо "нет операции" поставить просто задержку _delay_ms(100);-это ничего не измени? зато можно будет уменьшить количество повторений, а следовательно и значение переменной s.
10. killgur - 27 Марта, 2013 - 16:59:50 - перейти к сообщению
Artem пишет:
killgur пишет:
Потому как при очередном сложении значение обнулилось т.к. превысило размерность используемого для подсчетов регистра. (или превысило размерность использованного типа данных)

Надо контроль ввести если значение больше предельного то не прибавлять.


Понятно, значит нужно поменьше значение переменной, а нельзя, в функции задержки, вместо "нет операции" поставить просто задержку _delay_ms(100);-это ничего не измени? зато можно будет уменьшить количество повторений, а следовательно и значение переменной s.


наверно даже нужно так сделать. и прибавлять не 50000 а 1 Улыбка))

автор исходного кода того же мнения

http://avrlab.com/delay-routine
11. Artem - 27 Марта, 2013 - 17:06:58 - перейти к сообщению
killgur пишет:
наверно даже нужно так сделать. и прибавлять не 50000 а 1 ))

я тоже об этом думал, и даже попробовал, но для какого-либо заметного изменения в частоте мигания лампочкой нужно будет нажать на кнопку примерно 4000 раз! я уменьшил увеличение переменной, при каждом нажатии кнопки, до 5000 уже неплохо Улыбка
(Добавление)
Ну вот, я побаловался с этим, получилось почти как у автора статьи, только светодиодов меньше Улыбка и по яркости они хуже Улыбка
вот видео: http://www.youtube.com/watch?v=m6JfiWLe25I
12. Artem - 28 Марта, 2013 - 08:59:03 - перейти к сообщению
А я ещё хотел спросить, существуют ли микроконтроллеры у которых есть 4 вектора внешних прерываний или у всех микроконтроллеров их 2?
13. killgur - 28 Марта, 2013 - 11:42:35 - перейти к сообщению
Artem пишет:
А я ещё хотел спросить, существуют ли микроконтроллеры у которых есть 4 вектора внешних прерываний или у всех микроконтроллеров их 2?


stm32f1 - 18 вектров

Atmega 64 -6 векторов


например
14. Artem - 28 Марта, 2013 - 14:12:12 - перейти к сообщению
killgur пишет:
Atmega 64 -6 векторов

6 векторов-это внешние прерывания, или все вместе?
Потому что если считать все, то и в ATmega8 шесть штук наберётся Улыбка
15. killgur - 28 Марта, 2013 - 14:46:54 - перейти к сообщению
Artem пишет:
killgur пишет:
Atmega 64 -6 векторов

6 векторов-это внешние прерывания, или все вместе?
Потому что если считать все, то и в ATmega8 шесть штук наберётся Улыбка


ну даташит посмотрите, сколько ног INT

Можно еще использовать групповые прерывания их даже в attiny2313 7 штук

http://rln.nnov.ru/index.php?ind...iew&iden=224