реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Светофор в "Си"для контроллера с SIG_INTERRUPT0
konstatinopol
сообщение Jan 31 2009, 12:18
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 31-01-09
Пользователь №: 44 210



Такое дело надо спрограмировать светофор. Есть 2 микроконтроллера которые соединяются друг с другом и на каждый из них зашивается одна и таже программаю. Программа почти готова, но есть одна проблемка, у меня неправильно вызыватся SIG_INTERRUPT0.
Буду ОЧЕНЬ благодарен любой помощи !!!! Зарание благодарю.
Так выглядит борт :

CODE
#include <stdint>
#include <avr>
#include <avr>
#include <avr>
#include <avr> // In/Outputs


short cntr = 0;
int a=0;
int b=0;

void lampochki()
{

if(PORTB==1)
{
PORTB=3;
}
else if(PORTB==3){
PORTB=4;

}else if(PORTB==4)
{
PORTB=2;

}else if(PORTB==2)
{
PORTB=1;
a=1;
PORTC = 1;
//long i;
//for(i = 0; i < 1000000; i++);

}
PORTC = 0;

}

int main()
{
DDRB=7;
DDRD=0;
PORTB=1;
DDRC = 7;
PORTC=0;
TCNT0 = 244;
cntr = 28;
TCCR0 = 5;
TIMSK = 1;
GICR = 64; // interrupt port D0 ein
MCUCR = 1; // oder 2
sei();

while(1){}
}

SIGNAL(SIG_OVERFLOW0){
if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}

SIGNAL(SIG_INTERRUPT0){
a=0;
}
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 31 2009, 13:55
Сообщение #2


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(konstatinopol @ Jan 31 2009, 15:18) *
Программа почти готова, но есть одна проблемка, у меня неправильно вызыватся SIG_INTERRUPT0.

Надо объявить как volatile все, что юзается в прерываниях. Т.е. это cntr и a
ЗЫ: не в обиду, программа очень кривая и страшная.
Go to the top of the page
 
+Quote Post
aesok
сообщение Jan 31 2009, 14:09
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(_Pasha @ Jan 31 2009, 16:55) *
Надо объявить как volatile все, что юзается в прерываниях. Т.е. это cntr и a


Не совсем точно!!!


Надо объявить как volatile все переменные, которые используются, И в обработчиках прерываний, И в функции main или в функциях вызываемых из main.


А переменная cntr используется только в обработчике прерывания SIGNAL(SIG_OVERFLOW0), и более грамотно объявить локальную статическую переменную cntr в SIGNAL(SIG_OVERFLOW0).

То konstatinopol, перевидите пожалуйста "у меня неправильно вызывается SIG_INTERRUPT0", с Вашего на инженерный.

Анатолий.

Сообщение отредактировал aesok - Jan 31 2009, 14:20
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 31 2009, 14:19
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(konstatinopol @ Jan 31 2009, 14:18) *
у меня неправильно вызыватся SIG_INTERRUPT0.
Начиная с какой-то версии avr-gcc надо использовать ISR() вместо SIGNAL(). Почитайте документацию на avr-libc вашего компилятора.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
konstatinopol
сообщение Jan 31 2009, 15:01
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 31-01-09
Пользователь №: 44 210



_Pasha что вы подразумеваете под " программа очень кривая и страшная"?? Как она написанна, отредоктированна или что то в ней не потдаётся логике.
что значит обьявить volatile??
Код
volatile short cntr = 0;
volatile int a=0;
Видимо так.

Анатолий нащёт того чтобы обьявить cntr в SIGNAL(SIG_OVERFLOW0) точно я незнаю, но мы всегда её обьвляли до main(). Возможно и грамотнее но мы задаём ей значение в main() равное 28.

Возможно я неправильно выразился нащёт "SIG_INTERRUPT0". Дело в том что 2 борта соединяются и на них зашивается почти одна и таже программа, единственное отличие между программами это первое значение "а".
При запуске у обоих бортов зажигаются крассные лампочки. Тот борт у которого "а=0" зажигает лампочки в таком порядке : крассная-> крассно-желтая -> зелёная -> желтая -> крассная и сажает значение а=1 и останавливается, но в тот момент когда он останавливается(ботр) в SIG_INTERRUPT0 он посылает второму борту сигнал и тот сажает своё а=0 и проходит цепочку так же как и первый. Такая логика моего светофора.
Мне кажется что в программе неправильно написал принцип отправления а=0.

В моей версии avr-gcc ещё используется SIGNAL(), на других программах уже проверенно.

Вот принцеп соединения бортов, вроде правильно.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 31 2009, 15:25
Сообщение #6


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(konstatinopol @ Jan 31 2009, 19:01) *
_Pasha что вы подразумеваете под " программа очень кривая и страшная"??
Мне кажется что в программе неправильно написал принцип отправления а=0.

То, что мы сейчас делаем - как раз следствие "кривоватости" void lampochki()
Попробуйте кроме всего сказанного выше вернуть задержку, только зачем Вам такая огромная задержка?
Код
  PORTB=1; 
                                        a=1; 
                                        PORTC = 1; 
                                        //long i; 
                                        //for(i = 0; i < 1000000; i++); 
                               
                                } 
        PORTC = 0;


И еще. Настройка периферии не через символические имена сильно напрягает, потому что надо лазать в инфу. Т.е. мало кто захочет смотреть и проверять, все ли правильно установлено. Так что вот это GICR = 64; не читабельно.
Go to the top of the page
 
+Quote Post
rvk
сообщение Jan 31 2009, 15:33
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 165
Регистрация: 13-05-06
Из: Камышин
Пользователь №: 17 067



Если у Вас трудности с прерыванием, зачем его вообще организовывать?
Можно предположить, что SIGNAL(SIG_OVERFLOW0) это прерывание от Timer0,
и когда отстреляется 28 прерываний и в это время a=0 запускаются лампочки.
После того как лампочки отстрелялись, устанавливается PORTC=1 и тут же PORTC=0,
все происходит очень быстро, возможно, маловероятно, но возможно, второй борд не успевает
словить этот импульс. У Вас в программе есть цикл for(i=0;i<10000;i++) , который заблокирован
в тексте программы. Уберите две черты "//" и сделайте хотя бы
for(i=0;i<100;i++) ; Этого должно с гарантией хватить на ширину импульса.

Если после этого не сработает, можно отказаться от прерываний.
Процессор все равно простаивает, во время ожидания импульса на PORTD0,
вот пусть опрашивает PIND и обрабатывает импульс.
Можно вообще отказаться от прерываний. Если Вы скажете, что это возможно,
приведу здесь текст модуля без прерываний.

PS: пока писал текст опередили, но менять не буду, кашу маслом не испортитьsmile.gif

Сообщение отредактировал rvk - Jan 31 2009, 15:44
Go to the top of the page
 
+Quote Post
konstatinopol
сообщение Jan 31 2009, 15:37
Сообщение #8


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 31-01-09
Пользователь №: 44 210



Цитата(_Pasha @ Jan 31 2009, 19:25) *
То, что мы сейчас делаем - как раз следствие "кривоватости" void lampochki()
Попробуйте кроме всего сказанного выше вернуть задержку, только зачем Вам такая огромная задержка?

И еще. Настройка периферии не через символические имена сильно напрягает, потому что надо лазать в инфу. Т.е. мало кто захочет смотреть и проверять, все ли правильно установлено. Так что вот это GICR = 64; не читабельно.


Под вернуть задержку вы подразумиваете это??
Код
PORTB=1; 
   a=1; 
   PORTC = 1; 
   long i; 
   for(i = 0; i < 10000; i++); 

PORTC = 0;


А что нащёт GICR = 64; , препод так требует, да и я подругому не умею.
Go to the top of the page
 
+Quote Post
rvk
сообщение Jan 31 2009, 15:44
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 165
Регистрация: 13-05-06
Из: Камышин
Пользователь №: 17 067



Про задержку верно, только вместо 10000 поставить 100, этого должно с запасом хватить.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 31 2009, 16:16
Сообщение #10


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(konstatinopol @ Jan 31 2009, 17:37) *
А что нащёт GICR = 64; , препод так требует, да и я подругому не умею.
Объсните преподу, что он не прав. Заодно и лишний балл (если препод адекватный) заработаете. Не умеете - учитесь, ведь именно этому (учиться) и должны учить в институте, не так ли?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
konstatinopol
сообщение Jan 31 2009, 16:18
Сообщение #11


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 31-01-09
Пользователь №: 44 210



Такая ситуация что в данный момент я немогу опробовать программу.
Хочу ещё спросить про логику, то что есть в программе достаточно чтобы это всё работало так как задуманно. Или надо её ещё подработать??
Как только протестирую всё на борте, так сразу же отпишусь.
Go to the top of the page
 
+Quote Post
aesok
сообщение Jan 31 2009, 16:24
Сообщение #12


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(konstatinopol @ Jan 31 2009, 18:01) *
Анатолий нащёт того чтобы обьявить cntr в SIGNAL(SIG_OVERFLOW0) точно я незнаю, но мы всегда её обьвляли до main(). Возможно и грамотнее но мы задаём ей значение в main() равное 28.


Ваш пример:

CODE
short cntr = 0;

int main()
{
...
cntr = 28;
...
}

SIGNAL(SIG_OVERFLOW0){
if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}



Чем это плохо:
1. Объявление, инициализация и использование разнесены далеко по тексту
программы. Это ухудшает сопровождение программы. В С нет необходимости
инициализировать нулем глобальные переменные, по стандарту это сделает
компилятор. То есть можно просто написать "short cntr;" и в cntr будет 0 перед
входом в main.

Также Вы можете инициализировать глобальные переменные при объявлении любым
значением:
CODE
short cntr = 28;

SIGNAL(SIG_OVERFLOW0){
if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}



2. Представьте что ваш проект будет увеличиваться и вам потребуется второй
таймер пишем:
CODE
short cntr;
... много текста ....
short cntr; // добавляем

int main()
{
...
cntr = 28;
... много текста ....
cntr = 144; // добавляем
...
}

SIGNAL(SIG_OVERFLOW0){
if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}

SIGNAL(SIG_OVERFLOW1){
if(!(cntr--))
{
TCNT0=244;
cntr=144;
if(a==0)
lampochki();
}
}


Но это неправильно, cntr будет изменяться сразу из двух обработчиков
прерываний, и придется переименовывать cntr в cntr_for_timer0 и добавлять
cntr_for_timer1. Для экономии своего времени на отладке проекта и
придумывании/написании имен переменых проще объявить cntr локальными
статическими переменными:

CODE
SIGNAL(SIG_OVERFLOW0){
static short cntr = 28;

if(!(cntr--))
{
TCNT0=244;
cntr=28;
if(a==0)
lampochki();
}
}

SIGNAL(SIG_OVERFLOW1){
static short cntr = 244;

if(!(cntr--))
{
TCNT0=244;
cntr=144;
if(a==0)
lampochki();
}
}


Здесь объявление, инициализация и использование находятся рядом, что
упрощает понимание и изменение кода. Этот код более безопасный, локальные
перемене cntr видны только внутри своих обработчиков SIGNAL(SIG_OVERFLOW0)
и SIGNAL(SIG_OVERFLOW1) и не могут быть изменены из других частей программы.

PS: Что означает static и чем локальная статическая переменная отличается от не статической прочтите в любой книге по языку С.

Анатолий.



Цитата(rvk @ Jan 31 2009, 18:44) *
Про задержку верно, только вместо 10000 поставить 100, этого должно с запасом хватить.


Время исполнения:
for(i = 0; i < 10000; i++);
или:
for(i = 0; i < 100; i++);
и даже:
for(i = 0; i < 10; i++);

На любом опримизирующем компиляторе одиноково и равно нулю.

Анатолий.
Go to the top of the page
 
+Quote Post
konstatinopol
сообщение Jan 31 2009, 16:29
Сообщение #13


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 31-01-09
Пользователь №: 44 210



Спасибо Анатолий, теперь я понял что вы имели введу, это действительно упрощает код, если в SIGNAL(SIG_OVERFLOW0) занести static short cntr = 244;. А со static я уже знаком, благодарю вас.
Go to the top of the page
 
+Quote Post
rvk
сообщение Jan 31 2009, 16:58
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 165
Регистрация: 13-05-06
Из: Камышин
Пользователь №: 17 067



Цитата(aesok @ Jan 31 2009, 19:24) *
Время исполнения:
for(i = 0; i < 10000; i++);
или:
for(i = 0; i < 100; i++);
и даже:
for(i = 0; i < 10; i++);

На любом опримизирующем компиляторе одиноково и равно нулю.

Анатолий.


Вот такой код сработает при любом уровне оптимизации.

for(i=0;i<100;i++){
PORTC=1;
}

Сообщение отредактировал rvk - Jan 31 2009, 16:59
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Jan 31 2009, 19:40
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Цитата(aesok @ Jan 31 2009, 19:24) *
Время исполнения:
for(i = 0; i < 10000; i++);
или:
for(i = 0; i < 100; i++);
и даже:
for(i = 0; i < 10; i++);
На любом опримизирующем компиляторе одиноково и равно нулю.

Вовсе нет. Даже на Вашем любимом GCC. Зависит от способа объявления переменной i.
Она ведь может и квалификатор volatile иметь.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st June 2025 - 00:05
Рейтинг@Mail.ru


Страница сгенерированна за 0.01538 секунд с 7
ELECTRONIX ©2004-2016