роботы робототехника микроконтроллеры


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

> Без описания
Artem Post Id


Главнокомандующий


Сообщений всего: 347
Дата рег-ции: Май 2012  



Здравствуйте Улыбка
Осваиваю программирование микроконтроллеров, в данный момент разбираюсь с внешними прерываниями. Значит, подключил 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 и светодиод начал мигать реже. При этом, когда я нажимаю на кнопки светодиоды мигают, как описанно в подпрограмме обработчике прерываний. Я не знаю в чём может быть проблема, но наверно она в подпрограмме задержки, я не совсем понимаю, как она работает.
Помогите!!!
заранее спасибо Улыбка
 
 Top
elmot Post Id



Гуру


Сообщений всего: 1141
Дата рег-ции: Дек. 2010  



как минимум s должно быть volatile
 
 Top
Artem Post Id


Главнокомандующий


Сообщений всего: 347
Дата рег-ции: Май 2012  



А почему? По размеру int вроде тоже подходит?
 
 Top
elmot Post Id



Гуру


Сообщений всего: 1141
Дата рег-ции: Дек. 2010  



volatile - это не тип данных, это указание компилятору, что переменную надо всегда писать на ее место в памяти. Такой квалификатор необходимо применять к переменным, которые используются более чем из одного потока - в данном случае в нее лазают обработчик прерывания и основной код. Без модификатора компилятор может оптимизировать код и храниить переменную скажем, в регистре.
http://ru.wikipedia.org/wiki/%D0...0%B8%D0%BF%D0%B0
 
 Top
Artem Post Id


Главнокомандующий


Сообщений всего: 347
Дата рег-ции: Май 2012  



А, понятно, сейчас попробуем, но почему у автора статьи нет никакого квалификатора переменной?
(Добавление)
Да, вы правы, теперь всё заработало как нужно высший восторг
Но непонятно одно, почему когда я нажимаю на одну кнопку светодиод мигает всё чаще и чаще( переменная уменьшается) и через некоторое количество нажатий на кнопку светодиод опять начинает мигать с прежней частотой, переменная как бы уменьшается, уменьшается, а затем опять возвращается в первоначальное значение, почему это происходит?
 
 Top
killgur Post Id



Гуру


Сообщений всего: 1189
Дата рег-ции: Февр. 2010  



А откуда взялось такое значение 50000!?

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

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

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

Эта программа созданна каким то генератором кода?

(Отредактировано автором: 27 Марта, 2013 - 16:46:42)

 
 Top
Artem Post Id


Главнокомандующий


Сообщений всего: 347
Дата рег-ции: Май 2012  



killgur пишет:
А откуда взялось такое значение 50000!?

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

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

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



Гуру


Сообщений всего: 1189
Дата рег-ции: Февр. 2010  



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


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

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


Главнокомандующий


Сообщений всего: 347
Дата рег-ции: Май 2012  



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

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


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



Гуру


Сообщений всего: 1189
Дата рег-ции: Февр. 2010  



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

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


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


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

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

http://avrlab.com/delay-routine

(Отредактировано автором: 27 Марта, 2013 - 17:05:11)

 
 Top
Artem Post Id


Главнокомандующий


Сообщений всего: 347
Дата рег-ции: Май 2012  



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

я тоже об этом думал, и даже попробовал, но для какого-либо заметного изменения в частоте мигания лампочкой нужно будет нажать на кнопку примерно 4000 раз! я уменьшил увеличение переменной, при каждом нажатии кнопки, до 5000 уже неплохо Улыбка
(Добавление)
Ну вот, я побаловался с этим, получилось почти как у автора статьи, только светодиодов меньше Улыбка и по яркости они хуже Улыбка
вот видео: http://www.youtube.com/watch?v=m6JfiWLe25I
 
 Top
Artem Post Id


Главнокомандующий


Сообщений всего: 347
Дата рег-ции: Май 2012  



А я ещё хотел спросить, существуют ли микроконтроллеры у которых есть 4 вектора внешних прерываний или у всех микроконтроллеров их 2?
 
 Top
killgur Post Id



Гуру


Сообщений всего: 1189
Дата рег-ции: Февр. 2010  



Artem пишет:
А я ещё хотел спросить, существуют ли микроконтроллеры у которых есть 4 вектора внешних прерываний или у всех микроконтроллеров их 2?


stm32f1 - 18 вектров

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


например
 
 Top
Artem Post Id


Главнокомандующий


Сообщений всего: 347
Дата рег-ции: Май 2012  



killgur пишет:
Atmega 64 -6 векторов

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



Гуру


Сообщений всего: 1189
Дата рег-ции: Февр. 2010  



Artem пишет:
killgur пишет:
Atmega 64 -6 векторов

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


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

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

http://rln.nnov.ru/index.php?ind=reviews&op=entry_view&iden=224

(Отредактировано автором: 28 Марта, 2013 - 15:03:32)

 
 Top
Страниц (2): [1] 2 »
« Программирование микроконтроллеров »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 





Powered by Exclusive Bulletin Board
ExBB FM 1.0 RC1 Smiles by Fool from Foolstown
  Яндекс.Метрика   Рейтинг@Mail.ru