|
RC-5 протокол и ATmega8, Есть пуль RC-5 и контроллер ATmega8 |
|
|
|
Aug 23 2011, 13:37
|
Участник

Группа: Участник
Сообщений: 52
Регистрация: 10-10-08
Пользователь №: 40 823

|
Доброго времени суток форумчани! стоит задачка принимать команды с пульта 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 плиз без троллинга!
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Aug 23 2011, 14:32
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(Rom20 @ Aug 23 2011, 17:37)  заметил что он из прерываний почему то не возвращаться а все время крутиться в них, при отладке в желез та же картина, где косяк в упор не вижу. Надо избавляться от желания вставлять в процедуры прерывания циклы ожидания. А вашу задачу лучше решить так: 1) Прерывание по INT0 програмируется в режим изменения уровня ("Any logical change on INT0 generates an interrupt request"). 2) Внутри процедуры обработки прерывания от INT0: 2а) вычисляют разность между счетчиком таймера TCNT0 и старым значением таймера (под эту переменную заводят глобальную переменную oldTCNT0). 2б) обновляют значение переменной oldTCNT0 = TCNT0 2в) передают разность на USART (UDR). По величине разности можно сообразить, к какой полярности она относится. При желании можно сделать так, чтобы посылалась разность только одной полярности (например, делать посылки через раз). Тем не менее прерываться следует при каждом изменении полярности, а не только нужной, т.к. иначе разница будет включать сумму интервалов низкого и высокого уроней. Однако инфрормация о временах промежутков между сигналами тоже может оказаться полезной.
|
|
|
|
|
Aug 24 2011, 00:00
|
Участник

Группа: Участник
Сообщений: 52
Регистрация: 10-10-08
Пользователь №: 40 823

|
Цитата(Xenia @ Aug 23 2011, 17:32)  1) Прерывание по INT0 програмируется в режим изменения уровня ("Any logical change on INT0 generates an interrupt request"). Сконфигурировал МК что бы реагировал на изменение уровня сингла, изначально линия находиться в низком логическом уровне, в Proteus подаю на вход мк пачку импульсов из 14 как в протоколе RC-5 все временные выдержки импульсной пачки стоят как положено пробую принять и обработать вот по такому алгоритму: ожидаем прихода фронта, по фронту генерируется прерывание r увеличиваем на единицу запускаем таймер, возвращаемся из прерываний, таймер считает, ждем спада как только приходит спад генерируется прерывание, r увеличивается еще на единицу (вот не знаю хорошо это или нет что я второй раз как бы запускаю таймер?), проверяем значение r оно равно двум выкидываем в терминал значение нашего таймера. Но на деле подовая на вход пачку импульсов фиксированной длинны (900мкс и 1800мкс) я получаю совершенно разные цифры, но цифры хотя бы прослеживается какая то закономерность это радует  . и снова у меня где то ошибка подскажите пожалуйста где, если кто видит, или может ошибка в самом алгоритме? ISR (INT0_vect) { r++; TCCR0=(1<<CS02)|(1<<CS00); if(r==2) { UDR=TCNT0; TCNT0=0; r=0; }
|
|
|
|
|
Aug 24 2011, 02:16
|
Участник

Группа: Участник
Сообщений: 52
Регистрация: 10-10-08
Пользователь №: 40 823

|
Цитата(haker_fox @ Aug 24 2011, 04:55)  Ну, а цифры действительно будут разные, ибо "джиттер" ("дрожжание", "подергивание" сигнала во времени) никто не отменял  ну поставил в в прерываниях опрос готовности сом-порта ну это все рано ни чего не дало, ну и дребезг я тут пока не учитываю как моделирую в 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; }
Сообщение отредактировал Rom20 - Aug 24 2011, 02:17
Эскизы прикрепленных изображений
|
|
|
|
|
Aug 24 2011, 10:19
|
Участник

Группа: Участник
Сообщений: 52
Регистрация: 10-10-08
Пользователь №: 40 823

|
Цитата(Genadi Zawidowski @ Aug 24 2011, 13:26)  приём rc5 и складывание в буфер. за программу конечно спасибо, но я таких еще с 10 нагуглил, мне охото самому написать и во всем разобраться а не готовое решение брать......
|
|
|
|
|
Aug 24 2011, 12:32
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(Rom20 @ Aug 24 2011, 14:19)  за программу конечно спасибо, но я таких еще с 10 нагуглил, мне охото самому написать и во всем разобраться а не готовое решение брать...... почитайте: http://arv.radioliga.com/content/view/219/43/ специально старался... как раз для того, чтобы сделать самому  проверено не в одном проекте, работает (да и чего б не работать-то?). не используются прерывания, таймеры и прочее. однако, ничто не мешает их использовать и получить какой-то выигрыш...
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Aug 28 2011, 06:29
|
Участник

Группа: Участник
Сообщений: 52
Регистрация: 10-10-08
Пользователь №: 40 823

|
Народ хелп плиз. Написал программу в симуляторе 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'; } } } }
|
|
|
|
|
Aug 28 2011, 11:09
|
Местный
  
Группа: Свой
Сообщений: 289
Регистрация: 6-12-05
Пользователь №: 11 864

|
Цитата //прерывание по приему 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)));
|
|
|
|
|
Aug 28 2011, 11:17
|
Участник

Группа: Участник
Сообщений: 52
Регистрация: 10-10-08
Пользователь №: 40 823

|
Цитата(-SANYCH- @ Aug 28 2011, 14:09)  Может нужно вот так:
//прерывание по приему USART ISR (USART_RXC_vect) { v=UDR; while(!(UCSRA&(1<<UDRE))); UDR=v; }
зачем скобочки в конце функции? должно быть так while(!(UCSRA&(1<<UDRE))); это без разницы как работает и та и так конструкция, и вообще вопрос был поставлен правильный ли алгоритм обработки сигнала, а не для того что бы к листингу программы придераться
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|