alfa20 0 23 августа, 2011 Опубликовано 23 августа, 2011 · Жалоба Доброго времени суток форумчани! стоит задачка принимать команды с пульта 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 плиз без троллинга! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 45 23 августа, 2011 Опубликовано 23 августа, 2011 · Жалоба заметил что он из прерываний почему то не возвращаться а все время крутиться в них, при отладке в желез та же картина, где косяк в упор не вижу. Надо избавляться от желания вставлять в процедуры прерывания циклы ожидания. А вашу задачу лучше решить так: 1) Прерывание по INT0 програмируется в режим изменения уровня ("Any logical change on INT0 generates an interrupt request"). 2) Внутри процедуры обработки прерывания от INT0: 2а) вычисляют разность между счетчиком таймера TCNT0 и старым значением таймера (под эту переменную заводят глобальную переменную oldTCNT0). 2б) обновляют значение переменной oldTCNT0 = TCNT0 2в) передают разность на USART (UDR). По величине разности можно сообразить, к какой полярности она относится. При желании можно сделать так, чтобы посылалась разность только одной полярности (например, делать посылки через раз). Тем не менее прерываться следует при каждом изменении полярности, а не только нужной, т.к. иначе разница будет включать сумму интервалов низкого и высокого уроней. Однако инфрормация о временах промежутков между сигналами тоже может оказаться полезной. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alfa20 0 24 августа, 2011 Опубликовано 24 августа, 2011 · Жалоба 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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 24 августа, 2011 Опубликовано 24 августа, 2011 · Жалоба 1. Официальная документация от Atmel предписывает выводить данные в последний порт только с обязательной проверкой соответствующего флага. Может быть USART не успевает передать данные, в то время как ему даются новые? 2. Для измерения длительности импульсов следует использовать т.н. "захват". Искать в документации по слову "Capture". К сожалению я не знаком с этим делом, поэтому более подробно ничего сказать не могу. Ну, а цифры действительно будут разные, ибо "джиттер" ("дрожжание", "подергивание" сигнала во времени) никто не отменял :crying: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alfa20 0 24 августа, 2011 Опубликовано 24 августа, 2011 (изменено) · Жалоба Ну, а цифры действительно будут разные, ибо "джиттер" ("дрожжание", "подергивание" сигнала во времени) никто не отменял :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; } Изменено 24 августа, 2011 пользователем Rom20 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 24 августа, 2011 Опубликовано 24 августа, 2011 · Жалоба приём rc5 и складывание в буфер. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 45 24 августа, 2011 Опубликовано 24 августа, 2011 · Жалоба приём rc5 и складывание в буфер. Жуткого размера страшная программа :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 24 августа, 2011 Опубликовано 24 августа, 2011 (изменено) · Жалоба Жуткого размера страшная программа :) Ну что делать, если топикстартера на гугле забанили? Вот я и сложил сюда рабочий проект. Вот оригинал из двух функций: http://faq.embedders.org/_examples_code/re...www.markh.de).c Изменено 24 августа, 2011 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alfa20 0 24 августа, 2011 Опубликовано 24 августа, 2011 · Жалоба приём rc5 и складывание в буфер. за программу конечно спасибо, но я таких еще с 10 нагуглил, мне охото самому написать и во всем разобраться а не готовое решение брать...... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 24 августа, 2011 Опубликовано 24 августа, 2011 · Жалоба Так из многих "нагугленных" эта заработала сразу, без напильника (естественно, речь не о привязке к компилятору). Разберётесь потом - даже можете своё сделать на основе работающей программы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 24 августа, 2011 Опубликовано 24 августа, 2011 · Жалоба за программу конечно спасибо, но я таких еще с 10 нагуглил, мне охото самому написать и во всем разобраться а не готовое решение брать......почитайте: http://arv.radioliga.com/content/view/219/43/ специально старался... как раз для того, чтобы сделать самому :) проверено не в одном проекте, работает (да и чего б не работать-то?). не используются прерывания, таймеры и прочее. однако, ничто не мешает их использовать и получить какой-то выигрыш... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Allregia 9 24 августа, 2011 Опубликовано 24 августа, 2011 · Жалоба Мне в свое время, помогли эти три ссылки: http://altor1.narod.ru/Articles/IRC.pdf http://altor1.narod.ru/Site_gif/custom_rem...o_amplifier.pdf http://altor1.narod.ru/Articles/ProjFilesS...htctrl_soft.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alfa20 0 28 августа, 2011 Опубликовано 28 августа, 2011 · Жалоба Народ хелп плиз. Написал программу в симуляторе 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'; } } } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
*ZEVS* 0 28 августа, 2011 Опубликовано 28 августа, 2011 · Жалоба //прерывание по приему 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))); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alfa20 0 28 августа, 2011 Опубликовано 28 августа, 2011 · Жалоба Может нужно вот так: //прерывание по приему USART ISR (USART_RXC_vect) { v=UDR; while(!(UCSRA&(1<<UDRE))); UDR=v; } зачем скобочки в конце функции? должно быть так while(!(UCSRA&(1<<UDRE))); это без разницы как работает и та и так конструкция, и вообще вопрос был поставлен правильный ли алгоритм обработки сигнала, а не для того что бы к листингу программы придераться Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться