Дык а что задумывалось-то? И какие результаты? По Файлам Вашим не сильно ясно. Если работает нестабильно, можно попробовать поиграться значениями "тиков" таймера для распознавания, обычно помогает.
_________________ Оптимизм х (Опыт + Знания) = const
x+=14; if(x>=84) { y+=1; x=1; } if(y>7) { y=1; x=1; } } if (tick >= st_min && tick <st_max>= rp_min && tick <rp_max>= l_min && tick < l_max && start_cond) //если случилось от 22 до 115 тиков { ++b_cnt; //приняли "1" и увеличили счетчик битов if (b_cnt < 9) addr_1 = (addr_1 <<1>= 9 && b_cnt < 17) addr_0 = (addr_0 <<1>= 16 && b_cnt < 25) cmd_1 = (cmd_1 <<1>= 24) cmd_0 = (cmd_0 <<1>= s_min && tick < s_max && start_cond) //если случилось от 10 до 21 тика { ++b_cnt; //приняли "0" и увеличили счетчик битов if (b_cnt < 9) addr_1 = (addr_1 <<1>= 9 && b_cnt < 17) addr_0 = (addr_0 <<1>= 16 && b_cnt < 25) cmd_1 = (cmd_1 <<1>= 24) cmd_0 = (cmd_0 << 1); } TCNT0 = 0; //обнулили тики if (b_cnt == 32) //если приняли уже 4 байта { // if ((addr_1+addr_0) == 0xFF) addr = addr_0; //закомментировано, потому как в пульте First // else addr = 0; //16-bit адрес 0x6120, т.о. проверка адреса не проходит if ((cmd_1 + cmd_0) == 0xFF) cmd = cmd_1; //проверили правильность приема команды else cmd = 0; b_cnt = 0; //обнулили счетчик битов start_cond = 0; //сбросили стартовое условие repeat_cond = 0; TCCR0=0x00; //остановили таймер TCNT0=0x00; first_int = 1; printf("addr = %i ... cmd = %i \n\r" , addr_1, cmd_1); x=1; y=1; } PORTC.0 = 0; }
И вродебы всё работает правильно когда я клацаю пультиком и ShowTiming = 1 - тоесть результаты замеров длительности импульсов выводятся на экран(вроде бы и очень быстро выводится но вёравно время какое-то есть) а вот как только выключаю вывод отладочной инфы на экран - сразу всё прекращяется, лампочка которую я в начале прерывания зажигаю а потом в конце тушу - горит заметно меньшее время - ибо не надо выводить на экран цыфру значения таймера. но вот в принципе ж то на периодичность импульсов это не влияет и обработка прерывания вродебы 200 раз успевает закончиться к моменту прихода следующего импульса с ТСОПА.....а в уарт всётаки перестают кидаться адреса и коды кнопок.... и ещё странность - у меня есть пара пультиков от нагревателя (а-ля китайский кондиционер) и от колонок 5.1 Люксеон - так вот пультик от нагревателя в адресе имеет 1 а коды 28 64 125 240 254 - ну это ладно но а как обьяснить что пультик от колонок адрес имеет 0? это разве реально такой адрес? пультики от ТВ у меня сони так что пробывать смысла нет не могу никак понять.....значения таймингов у меня в еепроме валяются:
Код:
eeprom unsigned char l_min = 19; //диапазон для "длинного" (long) интервала в посылке, в "тиках" таймера, 1,28..2,176мс eeprom unsigned char l_max = 22; eeprom unsigned char s_min = 2; //диапазон для "короткого" (short) интервала в посылке, в "тиках" таймера, 0,704..1,088мс eeprom unsigned char s_max = 6; eeprom unsigned char st_min = 180; //диапазон для "старт" интервала в посылке, в "тиках" таймера, 0,704..1,088мс eeprom unsigned char st_max = 210; eeprom unsigned char rp_min = 160; //диапазон для "Повтор" интервала в посылке, в "тиках" таймера, 0,704..1,088мс eeprom unsigned char rp_max = 170;
и я могу их изменять на ходу не перепрошивая камня - через менюшку ком порта но...блин....оно-то и работает....пока включен вывод на экран....проверенно - это не изза общих переменных и т.д. ибо первый раз я обрадовавшить заремил этот кусочек и прошив офигел что не работает не поверив своим глазам сделал вывод по условию которое менюшкой из ком порта менять можно и оказалось таки да ((
может переменные границ интервалов сделать нормальными переменными и обновлять их из еепром только при старте системы?
Оказывается причина проста - изза маханькой задержки длинный стартовый импульс в 210 тиков таймера ставал ещё бОльшим в тиках так как при отсутствии задержки на вывод таймер быстрее обнулялся в прерывании и как следствие переполнение таймера ввел дополнительную переменную и по переполнению таймера увеличивал её а по переполнении и переменной - глушу таймер и обнуляю переменную вот собственно и всё
Если кому нужны исходники на мегу 16 в которых организована работа с ds18b20 в скоростном режиме(вне зависимости от количества термометров скорость обновления 2 раза в секунду), работа с LCD nokia 3310 + знакосинтезатор, работа с ком-портом(буферизированный приём, менюшка, примеры работы с констанмами, регулирование яркости с запоминанием и т.д.) + работа с ИРДА пультиками (и показан пример как поморгать лампочками )
могу выложить
Исходники на CodeVisionAVR C
+ написанная собственноручно прога для получения по кому данных о температурах и вывод её на экран + рисование графика с маштабируемостью и сохранением накопленных данных на винт(тоже с исходниками на VisualStudio C#)
Раскажите пожалуйста как вы расчитываете значение таймера вот в этой строке
TCCR0 = 0x04;
Я собрал приёмник на Atmega8 использовал Т0. Значение интервалов первоначально были вот такими:
l_min 40
l_max 68
s_min 22
s_max 34
Не заработало. После смены значений на такие
l_min 90
l_max 200
s_min 40
s_max 70
с третьего нажатия кнопки появлялся результат но соответсвенно постоянно разный. Теперь я думаю, что у меня просто не правильно выставлена частота таймера. Использую кварц 8 мГц. Научите меня расчитывать эту самую частоту. и как правильно расчитать эти самые "тики".
В общем, получилось что код несколько эволюционировал. Потребовалось получить несколько более удобный вариант декодера, в котором основная обработка вынесена из обработчика. Более того, прерывания вовсе не обязательны. В большинстве случаев можно обойтись проверкой флагов. Громоздкий приемный буфер заменен на одно интовое число-приемник. Приемный модуль оформлен в виде .с-модуля (некий аналог плюсового класса) и .h-интерфейса. Компилятор - GCC под Студией.
Отказ от прерываний позволил успешно интегрировать модуль в такую критичную по времени систему как USB-AVR одновременно с аналогичным модулем для трех разновидностей nec-протокола. (для примера, исходники nec-приемника приведены здесь - CVAVR).
Пример использования приемника RC5 в основном модуле (main) - ключевые моменты:
Код:
//...остальные хидеры #include "rc5reciver.h" ... //инициализация: PORTD|=(1<<PD3); //подтяжка на приемный пин /*прерывание инт1 сконфигурировано на любое изменение уровня, но не разрешено */ MCUCR=0x04; GIFR=0x80; ... int main(void) { //---------Локальные переменные---------// uchar fl_change=0; //флаг события фронта uchar fl_begin_ir=0; //флаг начала посылки uchar time_front=0; //время между фронтами, в тиках таймера struct ir_code ir_code; //тут храним структуру посылки //----------// ... for(;;){ //----обработчик переполнения таймера - это можно и в обработчик //(только без условия). Плюс тогда надо сделать флаг глобальным if (TIMER0_OVERFLOW){ T0_STOP; TCNT0=0x00; fl_begin_ir=0; reset_rc5(); CLEAR_FL_T0_OVERFLOW; LED_OFF; } //---------- //--------обработчик изменения уровня (можно в обработчик) if (ANY_CHANGE_INTERRUPT){ uchar tcnt_t0=TCNT0; //чтобы уменьшить погрешность TCNT0=0x00; //фиксируем время между фронтами if(fl_begin_ir) { time_front=tcnt_t0; fl_change=1; } else { T0_RUN; time_front=0; fl_begin_ir=1; reciever_rc5(&time_front); //здесь функция практически сразу //завершится после входа в нее } CLEAR_FL_T0_OVERFLOW; //на всякий случай очищаем флаг CLEAR_ANY_CHANGE_INTERRUPT; } //---------- //----------
if(fl_change){//если есть измерение между фронтами fl_change=0; switch (reciever_rc5(&time_front)) { case CONTINUE: break;
case ERROR: fl_begin_ir=0; T0_STOP; TCNT0 = 0x00; reset_rc5(); break;
case RC5_CODE: fl_begin_ir=0; rc5_parser(&ir_code); //загоняем код в структуру //используем лежащий в структуре код printf ("(%d,%d,%d,%d)",ir_code.toogle, ir_code.device_high,ir_code.device_low,ir_code.command); reset_rc5(); break; }
} //----------// } }
Сами файлы модуля прикреплены. Код выдран из рабочего проекта, поэтому желательно посмотреть внимательно перед использованием на предмет возможного наличия артефактов. Константы в хидере под частоту в 12МГц. МК - Atmega8. Подобный вариант более гибок и легок для встраивания (таймер умышленно не используется в самом модуле (только в одном месте - надо бы убрать) - если таймерных задач несколько, то дирижировать ими удобно в main). Суть в том, чтобы приемной функции передавать время между фронтами, сразу (или почти сразу) после событий этих фронтов. И все. В общем, сами посмотрите...
Вложения:
Комментарий к файлу: RC5 module rc5reciver.rar [1.75 KiB]
Скачиваний: 362
_________________ Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Chip type : ATmega8535 Program type : Application AVR Core Clock frequency: 4,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 128 *****************************************************/
// Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; PTR=0; PTR1=0;
while(1) { if (command>0)PTR=1; } } // External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { counter = TCNT0; //сохраяем значение таймера-счетчика TCNT0 = 0x00; //обнуляем таймер error = 1; //поставили ошибку - потом сбросим в теле, если все ок
if (cnt_bit == 0) //старт посылки { TCCR0 = 0x04; //запускаем таймер, частота 31250кГц (или надо править диапазоны тиков для интервалов) code [cnt_bit] = !PIND.2; //записываем бит кода, PIND.2 - входная нога, прерывание 0 cnt_bit++; //увеличиваем счетчик принятых бит state = 1; //ставим флаг, т.к. была 1 }
else //в других случаях (не первое срабатывание прерывания) { if ((counter>s_min) && (counter<s_max)) //проверка короткого промежутка { if (state) //если была 1 { state = 0; //обнуляем состояние error = 0; //и ошибку, т.к. все корректно } else //если был 0 { state = 1; //ставим флаг, т.к. теперь - 1 code[cnt_bit] = !PIND.2; //записываем данные - состояние линии cnt_bit++; //увеличиваем счетчик приема error=0; //обнуляем ошибку, т.к. все корректно }; };
if ((counter>l_min) && (counter<l_max)) //проверка длинного промежутка { code[cnt_bit] = !PIND.2; //записываем данные - состояние линии cnt_bit++; //увеличиваем счетчик приема error = 0; //обнуляем ошибку, т.к. все корректно };
if (error == 1) //если не попали ни в один из промежутков, то { char i = 0; //внутренняя переменная
Я не уверен что я правильно MCUCR настроил, я не знаю каким должно быть прерывание INTO по фронту, по спаду, по низкому уровню или по любому изменению...
Я писал с идеей что PTR и PTR1 равны нулю всегда, кроме случаев, когда command больше ноля...Любая команда должна просигналить что она принята переводом из ноля в единицу.
Ну, понятно, что я не спец в программировании, поэтому и задаю "такие" вопросы...Но у меня на индикаторе высвечивается не один-ноль, у меня на индикаторе "ноль-ноль", если бы там появилась единица, я бы не задавал никаких вопросов...Я бы сделал вывод что RC5 принимает, а сейчас я делаю вывод что у меня или неправильно настроен RC5 или я не могу связать его с индикацией...
...Но у меня на индикаторе высвечивается не один-ноль, у меня на индикаторе "ноль-ноль", если бы там появилась единица, я бы не задавал никаких вопросов....
А не легче в обработчике при успешном приеме светодиод поджигать? И таймер1 пока выключить нафиг....
_________________ Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 36
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения