Перейти к содержанию
    

Доброго времени суток форумчани! стоит задачка принимать команды с пульта RC-5 и обрабатывать их контроллером. Пересмотрел кучу статей по этой теме попробовал собрать несколько проектов и инета так ни чего и не заработала, уже неделю сижу парюсь, в итого только принимаю какую то ахинею и выкидываю ее в ком порт, вроде сам протокол изучи нормально как идет передача понимаю а что то не работает, вот кусок кода

ISR (INT0_vect)

{

uint8_t u;

TCCR0=(1<<CS02)|(1<<CS00);

TCNT0=0;

while(PIND&(1<<2))

{

}

u=TCNT0;

UDR=u+0x30;

}

 

генерирую прерывания по нарастающему фронту, а дальше пробую померить длительность каждого бита, по идеи при нажатии одной кнопки на пульте должен в ком порт получать минимум 14 символов, т.к протокол 14 бит, ну получаю всего один и то каждый раз разный. или может что ни так у меня с прерываниями прогнал программу в симуляторе AVRstudio и заметил что он из прерываний почему то не возвращаться а все время крутиться в них, при отладке в желез та же картина, где косяк в упор не вижу.

P.S плиз без троллинга!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

заметил что он из прерываний почему то не возвращаться а все время крутиться в них, при отладке в желез та же картина, где косяк в упор не вижу.

Надо избавляться от желания вставлять в процедуры прерывания циклы ожидания.

 

А вашу задачу лучше решить так:

1) Прерывание по INT0 програмируется в режим изменения уровня ("Any logical change on INT0 generates an interrupt request").

2) Внутри процедуры обработки прерывания от INT0:

2а) вычисляют разность между счетчиком таймера TCNT0 и старым значением таймера (под эту переменную заводят глобальную переменную oldTCNT0).

2б) обновляют значение переменной oldTCNT0 = TCNT0

2в) передают разность на USART (UDR). По величине разности можно сообразить, к какой полярности она относится. При желании можно сделать так, чтобы посылалась разность только одной полярности (например, делать посылки через раз). Тем не менее прерываться следует при каждом изменении полярности, а не только нужной, т.к. иначе разница будет включать сумму интервалов низкого и высокого уроней. Однако инфрормация о временах промежутков между сигналами тоже может оказаться полезной.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1) Прерывание по INT0 програмируется в режим изменения уровня ("Any logical change on INT0 generates an interrupt request").

Сконфигурировал МК что бы реагировал на изменение уровня сингла, изначально линия находиться в низком логическом уровне, в Proteus подаю на вход мк пачку импульсов из 14 как в протоколе RC-5 все временные выдержки импульсной пачки стоят как положено пробую принять и обработать вот по такому алгоритму:

ожидаем прихода фронта, по фронту генерируется прерывание r увеличиваем на единицу запускаем таймер, возвращаемся из прерываний, таймер считает, ждем спада как только приходит спад генерируется прерывание, r увеличивается еще на единицу (вот не знаю хорошо это или нет что я второй раз как бы запускаю таймер?), проверяем значение r оно равно двум выкидываем в терминал значение нашего таймера. Но на деле подовая на вход пачку импульсов фиксированной длинны (900мкс и 1800мкс) я получаю совершенно разные цифры, но цифры хотя бы прослеживается какая то закономерность это радует :biggrin: . и снова у меня где то ошибка подскажите пожалуйста где, если кто видит, или может ошибка в самом алгоритме?

ISR (INT0_vect)

{

r++;

TCCR0=(1<<CS02)|(1<<CS00);

if(r==2)

{

UDR=TCNT0;

TCNT0=0;

r=0;

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Официальная документация от Atmel предписывает выводить данные в последний порт только с обязательной проверкой соответствующего флага. Может быть USART не успевает передать данные, в то время как ему даются новые?

 

2. Для измерения длительности импульсов следует использовать т.н. "захват". Искать в документации по слову "Capture". К сожалению я не знаком с этим делом, поэтому более подробно ничего сказать не могу.

 

Ну, а цифры действительно будут разные, ибо "джиттер" ("дрожжание", "подергивание" сигнала во времени) никто не отменял :crying:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, а цифры действительно будут разные, ибо "джиттер" ("дрожжание", "подергивание" сигнала во времени) никто не отменял :crying:

ну поставил в в прерываниях опрос готовности сом-порта ну это все рано ни чего не дало, ну и дребезг я тут пока не учитываю как моделирую в proteuse а тут модель ближе к идеальной, длительность короткого импульса 900мкс длинного 1800мкс, а данные в сом-порт приходят одни и те же, вопрос толи счетчик считает не правильно или где то еще ошибка в моих суждениях:

ISR (INT0_vect)

{

r++;

TCCR0=(1<<CS02)|(1<<CS00);

if(r==2)

{

while(!(UCSRA&(1<<UDRE)))

{}

UDR=TCNT0;

TCNT0=0;

r=0;

}

post-40823-1314151883_thumb.png

Изменено пользователем Rom20

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

приём rc5 и складывание в буфер.

Жуткого размера страшная программа :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Жуткого размера страшная программа :)

 

Ну что делать, если топикстартера на гугле забанили? Вот я и сложил сюда рабочий проект. Вот оригинал из двух функций:

http://faq.embedders.org/_examples_code/re...www.markh.de).c

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

приём rc5 и складывание в буфер.

за программу конечно спасибо, но я таких еще с 10 нагуглил, мне охото самому написать и во всем разобраться а не готовое решение брать......

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так из многих "нагугленных" эта заработала сразу, без напильника (естественно, речь не о привязке к компилятору).

Разберётесь потом - даже можете своё сделать на основе работающей программы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

за программу конечно спасибо, но я таких еще с 10 нагуглил, мне охото самому написать и во всем разобраться а не готовое решение брать......
почитайте: http://arv.radioliga.com/content/view/219/43/ специально старался... как раз для того, чтобы сделать самому :)

 

проверено не в одном проекте, работает (да и чего б не работать-то?). не используются прерывания, таймеры и прочее. однако, ничто не мешает их использовать и получить какой-то выигрыш...

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Народ хелп плиз. Написал программу в симуляторе AVRstudio при шаговой отладке все хорошо принимает данные с пульта, а вот в железе начинаются проблемы в сом-порт гонит в основном одни "1". Использую следующий алгоритм. изначально нога контроллера притянута к +5в

1. Разрешаю прерывания по изменению уровня сигнал заведен на PD2

2. при первом прерывании (спаду) запускаю таймер

3. при появлении высокого логического уровня снова генерируется прерывание считываю значение таймера

4. Проверяю длину импульса

4а. Если импульс длинный то однозначно я нахожусь на середине бита и можно производить считывание, считываю значение порта ложу в переменную

4б Если импульс короткий проверяю где нахожусь: если на границе битов то ничего не считываю просто запоминаю что граница, если на середине бита то считываю значение порта ложу в перемененную.

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

 

 

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

#include <avr/signal.h>

volatile int v,r,p,u=0, oldp,gr;

uint16_t j,k,f,x,y1,y2,pult;

uint8_t c,a,e,q,m=0,m1;

ISR (INT0_vect)

{

r++;//переменная r служит для подсчета для того что бы узнать где находимся на середине или на границе при коротких импульсях

TCCR0=(1<<CS02);//запускаем таймер

p=TCNT0;//считываем заначение таймера

TCNT0=0;//

if(r==2)// если находимся на середине бита то запоминаем предыдущее значение таймера

{

oldp=p;

r=0;

}

}

//прерывание по приему USART

ISR (USART_RXC_vect)

{

v=UDR;

_delay_us(5);

UDR=v;

}

// инициализация настроек

void inic()

{

 

DDRC=0xFF;

DDRB=0xFF;

DDRB&=~(1<<0);

PORTB=0;

PORTB|=(1<<3);

//натсраиваем скорость 19200 бот/c

UBRRL=25;

UBRRH=0;

UCSRA=0;

// настраиваем приемник передатчик

UCSRB=(1<<RXEN) |(1<<TXEN)|(1<<RXCIE);

// 8 бит данных

UCSRC=(1<<UCSZ0) |(1<<UCSZ1)|(1<<URSEL);

MCUCR=(1<<ISC00);

GICR=(1<<INT0);

}

void main()

{

inic();

while(1)

{

sei();

while(1)

{

if ((p>0x18)&&(p<0x1F))// если интервал короткий

{

if(p==oldp)//проверяем где находимся на границе или на середине бита если на середине бита то gr=1

{

gr=1;

oldp=0;

}

if (((p>0x18)&&(p<0x1F))&&gr)// если интервал короткий и мы находимся на середине то можно считывать значение порта

{

 

gr=0;

p=0;

j=PIND&(1<<2);

_delay_us(50);

j=PIND&(1<<2);

if(j)

{

while(!(UCSRA&(1<<UDRE)))

{}

pult|=(1<<u);

UDR='1';

}

if(!j)

{

while(!(UCSRA&(1<<UDRE)))

{}

pult&=~(1<<u);

UDR='0';

}

u++;// стчик для складирования битов

}

p=0;

 

}

//динный импульс

if ((p>0x37) && (p<0x3B))// если импульс длинный то мы однозначно на середине считываем значение порта

{

r=0;

gr=0;

p=0;

j=PIND&(1<<2);

_delay_us(50);

j=PIND&(1<<2);

if(j)

{

while(!(UCSRA&(1<<UDRE)))

{}

UDR='1';

pult|=(1<<u);

}

if(!j)

{

while(!(UCSRA&(1<<UDRE)))

{}

pult&=~(1<<u);

UDR='0';

}

u++;

}

if(u==14)

{

u=0;

while(!(UCSRA&(1<<UDRE)))

{}

UDR='E';

}

}

}

}

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

//прерывание по приему USART

ISR (USART_RXC_vect)

{

v=UDR;

_delay_us(5);

UDR=v;

}

 

Может нужно вот так:

 

//прерывание по приему USART

ISR (USART_RXC_vect)

{

v=UDR;

while(!(UCSRA&(1<<UDRE)));

UDR=v;

}

 

 

while(!(UCSRA&(1<<UDRE)))

{}

 

зачем скобочки в конце функции?

должно быть так while(!(UCSRA&(1<<UDRE)));

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может нужно вот так:

 

//прерывание по приему USART

ISR (USART_RXC_vect)

{

v=UDR;

while(!(UCSRA&(1<<UDRE)));

UDR=v;

}

 

 

 

 

зачем скобочки в конце функции?

должно быть так while(!(UCSRA&(1<<UDRE)));

это без разницы как работает и та и так конструкция, и вообще вопрос был поставлен правильный ли алгоритм обработки сигнала, а не для того что бы к листингу программы придераться

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...