Пример работы с протоколом RC5 decoder на AVR микроконтроллере ATmega8
"...Хорошие художники - копируют,
великие художники - воруют..."
П.Пикассо
Далее я представлю рабочий код программы-декодера сигналов протокола RC5 для ИК пультов дистанционного управления.
Программа не моя, за нее хочу сказать большое спасибо парню по имени Peter Dannegger.
Комментарии мои, но в некоторых частях кода я реально не въеду что автор хотел сказать своими комментариями поэтому перевод был или оставлен как есть или далеко не дословный.
Программа протестирована с ИК датчиком TSOP1736. Программа обработки RC5 состоит из трех файлов, которые необходимо поместить в один проект AVR Studio, названия файлов необходимо сохранить так, чтобы они подтягивали без проблем друг друга.
Содержание первого файла, я назвал его RC5_german_lib.c
В файле находиться подпрограмма инициализации модуля USART, подпрограммы отправки символа по USART и строки.
#include "rc5_german.h" #include "rc5_german_c.c" //Программа вывода символа void putchar( char c ) { while( (UCSRA & 1<<UDRE) == 0 ); UDR = c; } //Программа вывода строки void puts( char *s ) { while( *s ) putchar( *s++ ); } //Основная программа int main( void ) { uint i; char s[30];//переменная строковая TCCR0 = 1<<CS02; //Деление тактовой частоты на 256 TIMSK = 1<<TOIE0; //Разрешаем прерывание по таймеру UBRRL = bauddivider; //Устанавливаем значение baud rate UBRRH = bauddivider >> 8; UCSRA = 0;//не используем режим U2X UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;//формат данных 8бит UCSRB = 1<<RXEN^1<<TXEN;//Разрешаем прием и передачу sei();//Разрешаем глобально прерывания puts( "RC5-Decoder:\n\r" );//Выводим строку приветствия for(;;)//Главный цикл { cli();//запрет прерывания i = rc5_data;//Читаем два байта из прерывания rc5_data = 0; sei();//разрешаем прерывания if( i ) { DDRB = i; // LED output putchar(( i >> 11 & 1) + '0');//Выводим значение триггерного бита putchar(' ');//пробел itoa( i >> 6 & 0x1F, s, 10);//Выводим адрес устройства puts( s ); putchar(' '); //пробел itoa((i & 0x3F)|(~i >> 7 & 0x40), s, 10);//Выводим код команды puts( s ); puts( "\n\r" ); //Выводим конец строки } } }
Далее листинг содержания файла rc5_german_c.c
В этом файле непосредственно реализован алгоритм декодера RC5.
#include "rc5_german.h" #define RC5TIME 1.778e-3 // 1.778msec Длительность одного бита #define PULSE_MIN (uchar)(XTAL / 512 * RC5TIME * 0.4 + 0.5) #define PULSE_1_2 (uchar)(XTAL / 512 * RC5TIME * 0.8 + 0.5) #define PULSE_MAX (uchar)(XTAL / 512 * RC5TIME * 1.2 + 0.5) uchar rc5_bit;//значение бита uchar rc5_time;//Подсчет количества бит uint rc5_tmp;//Переменная для хранения временных значений uint rc5_data;//Переменная для результата //Обработчик прерывания по таймеру SIGNAL (SIG_OVERFLOW0) { uint tmp = rc5_tmp; // for faster access TCNT0 = -2; // 2 * 256 = 512 cycle if( ++rc5_time > PULSE_MAX ){ // count pulse time if( !(tmp & 0x4000) && tmp & 0x2000 )//Только если приняли 14 бит rc5_data = tmp; tmp = 0; } if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 ){ // change detect rc5_bit = ~rc5_bit; // 0x00 -> 0xFF -> 0x00 if( rc5_time < PULSE_MIN ) // to short tmp = 0; if( !tmp || rc5_time > PULSE_1_2 ){ // start or long pulse time if( !(tmp & 0x4000) ) // not to many bits tmp <<= 1; // shift if( !(rc5_bit & 1<<xRC5) ) // inverted bit tmp |= 1; // insert new bit rc5_time = 0; // count next pulse time } } rc5_tmp = tmp; }
И наконец третий файл rc5_german.h
В этом файле находятся все конфигурационные данные и переменные необходимые для работы.
#include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> #include <stdlib.h> #define uchar unsigned char #define uint unsigned int #define xRC5_IN PIND//Задаем порт для датчика #define xRC5 PD2 //Задаем ногу порта для датчика #define XTAL 16e6//Задаем частоту кварца //#define XTAL 11.0592e6 //#define XTAL 7.3728e6 //#define XTAL 5e6 #define BAUD 19200//Задаем скорость соединения по USART //#define BAUD 115200 #define bauddivider (uint)(XTAL / BAUD / 16 - 0.5) extern uint rc5_data;//Задаем переменную для хранения полученного результата
Файлы можете переименовать, единственное что так же необходимо после переименования файлов выполнить изменения в начале каждого файла, добавить в связку уже переименованные файлы.
По моим комментариям все думаю понятно, сам принцип работы протокола RC5 и структура пакета уже упоминались. Данную программу можно применять в различных конструкция требующих дистанционного управления, то есть не требующие физического контакта с объектом. Программа разработана под микроконтроллер семейства AVR Atmega8.
Принципиальная схема для декодера сигналов протокола RC5 на микроконтроллере ATmega8 показана на рис. 1
Рис. 1
Вот так выглядит собранная схема для проверки работы декодера RC5 команд.
Откомпилированный код занимает совсем мало места в памяти микроконтроллера, поэтом возможны некоторые добавки к коду, например система декодера команд - выполнение определенной функции по приходу определенной команды.
Программа выполняет прием и обработку принятой команды с пульта и отправляет полученное по порту USART на компьютер. Для приема данных от модуля USART микроконтроллера на компьютер необходимо собрать конвертер уровней.
Мониторить принятые данные рекомендую через программу Terminal RS232.
Вот что вы увидите после запуска программы.
Отклик от устройства состоит из трех частей, первая - значение триггер бита, второе - код устройства, номер команды.
По многочисленным просьбам файл с проектом:
Скачать проект RC5 на ATmega8
Как ни странно, забил все файлы, выбрал контроллер, нажал "Build" и все ок.
Никаких ошибок. Сразу вспомнился анекдот про прокладку между рулем и сидением :-)
Примечание: сам файл с библиотекой обработки RC5 протокола добавлять не нужно, его нужно просто сохранить в папку с основным файлом проекта.
Видео работы декодера RC5, немного хреновенько видно что там происходит, но поверьте оно работает:
Следующий код, выполняет определенные действия в зависимости от полученного номера кнопки нажатой на пульте Д/У.
#include "rc5_german.h" #include "rc5_german_c.c" //Программа вывода символа void putchar( char c ) {while( (UCSRA & 1<<UDRE) == 0 ); UDR = c;} //Программа вывода строки void puts( char *s ) { while( *s ) putchar( *s++ );} //Основная программа int main(void) { uint i; char s[30];//переменная строковая TCCR0 = 1<<CS02; //Деление тактовой частоты на 256 TIMSK = 1<<TOIE0; //Разрешаем прерывание по таймеру UBRRL = bauddivider; //Устанавливаем значение baud rate UBRRH = bauddivider >> 8; UCSRA = 0;//не используем режим U2X UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;//формат данных 8бит UCSRB = 1<<RXEN^1<<TXEN;//Разрешаем прием и передачу sei(); //Разрешаем глобально прерывания puts( "RC5-Decoder:\n\r" ); //Выводим строку приветствия for(;;) //Главный цикл { cli(); //запрет прерывания i = rc5_data; //Читаем два байта из прерывания rc5_data = 0; sei();//разрешаем прерывания if( i ) { int n = ((i & 0x3F)|(~i >> 7 & 0x40)); //Выделяем только код команды switch (n) //Проверяем что выполнять в зависимости от команды { case 7: puts( "This is 7"); puts( "\n\r" ); break; //выполняем действие по кнопке 7 case 5: puts( "This is 5"); puts( "\n\r" ); break; //выполняем действие по кнопке 5 case 0: puts( "This is 0"); puts( "\n\r" ); break; //выполняем действие по кнопке 0 } } } }
включить-выключить по одной кнопке
Подскажите в чем я ошибся,по нажатию одной кнопки, должно было происходить включение - выключение
для использования кварца на
для использования кварца на 7.372
#define PULSE_MIN (uchar)(XTAL / 512 * RC5TIME * 0.4 + 0.5)
#define PULSE_1_2 (uchar)(XTAL / 512 * RC5TIME * 0.8 + 0.5)
#define PULSE_MAX (uchar)(XTAL / 512 * RC5TIME * 1.2 + 0.5)
только тут нужно меня значения если uart не используется? и на какие подскажите
Тут ничего менять не нужно, у
Тут ничего менять не нужно, у тебя переменная XTAL зажается выше и тут она уже сама учатвует со своим значением. Форумыл не трогай, задай свою частоту кварца и все. В юарте если будешь использовать его посмотри в таблицу скоростей и найти свое значение Baud rate. Таблица в даташите на твой микроконтроллер.
Подскажите, хочу
Подскажите, хочу использовать,кварц на 7.372,кроме строчки XTAL 7.3728e6, нужно еще что ни будь менять, и еще вопрос если захочу на мегу16 залить, то просто изменть в настройках проекта на 16 вместо 8?
1. Да просто меняешь строчку
1. Да просто меняешь строчку и частоту в настройках проекта.
2. Да, меняешь в настройках проекта микроконтроллер на ATmega16.
Пробуй и отписывайся о успехах.
кто может, объясните строчки
кто может, объясните строчки
так ли будет
и как конкретней вписать и куда действие для вкл светодиода на ножке 3, можно ли сделать что бы по одной команде вкл она и по повторном нажатии выкл?
По двум нажатиям все можно,
По двум нажатиям все можно, для этого заводится переменная состояния включенного или выключенного светодиода.
При нажатии кнопки выполняется смена переменной например с "1" на "0" что будет означать включение светодиода. Отдельно пишешь функцию, которая проверяет эту переменную и если она равна "0" включает светодиод, только её надо вызывать сразу же после изменения состояния переменной. Все понял?
К сожалению нет, я
К сожалению нет, я начинающий, а ты можешь пример привести для вкл и выкл для
case 7: puts( "This is 7"); puts( "\n\r" ); break; //выполняем действие по кнопке 7
, а для остальных я уже тогда по аналогии, буду бесконечно признателен
вот код
Огромное спасибо :)
Огромное спасибо :)
Попробуй и отпишись, вышло
Попробуй и отпишись, вышло или нет.
не получилось((( делал
не получилось((( делал так:
Прошивка
Проблема с компиляцией в hex. Собираю все 3 файла в одном проекте студии и при компиляции вижу:
Build started 8.5.2011 at 23:53:28
avr-gcc -mmcu=atmega8 -Wall -gdwarf-2 -O0 -Wp,-M,-MP,-MT,RC5_german_lib.o,-MF,dep/RC5_german_lib.o.d -c ../../RC5_german_lib.c
../../RC5_german_lib.c:5: warning: conflicting types for built-in function 'putchar'
../../RC5_german_lib.c:12: warning: conflicting types for built-in function 'puts'
../../RC5_german_lib.c:54: fatal error: opening dependency file dep/RC5_german_lib.o.d: No such file or directory
compilation terminated.
make: *** [RC5_german_lib.o] Error 1
Build failed with 1 errors and 2 warnings...
Кто знает в чём проблемма, подскажите пожалуйсто.
выложи исходники
У меня теже грабли.
Автор выложи проект в AVRStudio. Так будет намного проще разбираться
Добавил, качайте.
Добавил, качайте.
Прошивка
Пытаюсь компилировать как вы сказали, но постоянно выдает ошибку:
RC5_german_lib.o: In function `__vector_9':
D:\RC5\default/../rc5_german_c.c:12: multiple definition of `__vector_9'
rc5_german_c.o:D:\RC5\default/../rc5_german_c.c:12: first defined here
make: *** [rc5_german_c.elf] Error 1
Build failed with 1 errors and 4 warnings...
Как исправить?
Прошивка
Уважаемый автор.
Я не силен в программировании микроконтроллеров.
Пожалуйста, подскажите, где можно скачать откомпилированную прошивку? Или расскажите пошагово как получить .hex
Спасибо.
Читаем Цель - получить *.hex
Читаем Цель - получить *.hex файл
У меня такая же ошибка
У меня такая же ошибка прикомпиляции.
RC5_german_lib.o: In function `__vector_9':
D:\RC5\default/../rc5_german_c.c:12: multiple definition of `__vector_9'
rc5_german_c.o:D:\RC5\default/../rc5_german_c.c:12: first defined here
К чему писать про "Цель - получить *.hex файл"? multiple definition of `__vector_9' - hex-файл не собирается, потому что множественное определение __vector_9.
Мало того, в хидере надо закомментировать строку 3, #include, иначе тоже компилятор орет благим матом:."
c:/avr/winavr/lib/gcc/../../avr/include/avr/signal.h:36:2: warning: #warning "This header file is obsolete. Use
Выкладывайте рабочий проект.
Уважаемый АНОНИМ, качай
Уважаемый АНОНИМ, качай проект, тот который я за 2 минуты билднул.
В результате ошибок 0! замечаний 3 - связаны с функциями вывода по UART данных.
Добрый день, Уважаемый
Добрый день,
Уважаемый extremist -есть вопросы по выложенному проекту - не нашел строк где определяется то, как будут использоваться порты В и D, также не понял вот этой строки в файле RC5_german_lib.c
DDRB = i; // LED output - по идее должно быть PORTB = i ?
Сори если вопросы чайницкие.
Михаил.
1. Михаил чего не
1. Михаил чего не регистрируешься на сайте?
2. DDRB = i; // LED output - имеется в виду настройка порта на вывод информации.
Зачем порты B и D?
Нужен один порт, даже просто один вывод порта, для подключения к нему ИК датчика.
С остальными портами можно делать что хочешь.
В других устройствах.
А чтобы в других устройствах использовать RC-5 мне надо переменную rc5_data брать и подставлять в нужные функции? И как мне значения переменной каждой кнопки узнать, подключить к компу и все кнопки считать, наверно так?
Если я не так понял, можешь небольшой кусок кода для примера выложить? Скажем: одна кнопка зажигает светодиод, а другая гасит. Думаю, кому-то пригодится. :)
Вот так обработку массива я делал
Код срабатывает если первый элемент массива "1" а второй "2".
Так же можно выполнить проверку на соответствие другой комбинации цифр, и на большее количество цифр.
В данном коде я делал что один МК принимает ИК команды пульта а второй выполняет действия при приеме определенной последовательности чисел. Это было по причине что МК который принимает ИК команды, все время срабатывает на прерывание по счетчику, по сему нормально работать он не может.
хм. а если мне надо, чтобы
хм. а если мне надо, чтобы программа одновременно смотрела и пульт, и нажатие кнопки? интересно,какое энергопотребление будет у устройства в режиме ожидания сигнала с ИК пульта?
Так заводишь устройство в
Так заводишь устройство в спящий режим, ждешь пока не будет принять сигнал на TSOP после чего будишь устройтво и обрабатываешь уже принятую комманду.
в теории легко, увидеть бы
в теории легко, увидеть бы это в синтаксисе c...
кстати, не в курсе, чем отличаются 17 от 18 серии?
Производителем и несущей
Производителем и несущей частотой.
Для кода программы определенного назначения для начала ТЗ необходимо составить и хотя бы наброски кода.
А дальше я думаю пользователи помогут.
просто видел в продаже и
просто видел в продаже и tsop1736 и tsop1836 - частота как будто одинаковая)
про ТЗ - думал попробовать в качестве эксперимента типа для учебных целей сделать термометр с несколькими датчиками на ds1820, который бы сам включался от пульта и переключался между датчиками им же, а, скажем, через минуту после включения - выключался.
как в выключенном режиме измерить энергопотребление? (просто оценить, насколько живуч он будет от батарейки?)
ставить амперметр в цепь? кажется, мне все же придется внимательно проштудировать все 223 страницы даташыта... :-)
кстати, немного не ясно про датчики - видел на инстрактаблз.ком, как подключают пульт от мака (там как будто нековский протокол, отличный от RC5, и частота не 36, а 38кГц). и там просто сказано, нужен фотоприемник -не указывали, какой именно. зачем там вообще эти разные частоты? разве мы частоту светодиода задаем не программным путем? или я не так понял? и как это решается на фотоприемниках? (что это, фотодиод? фтотранзистор или фоторезистор?) я спалил свой датчик - какое можно найти применение его фототранзистору?
и вопрос по схеме - обязательно ли нужен внешний кварц, или можно обойтись внутренним (опять по количеству ножек пытаюсь уложиться)
На первой странице даташита
На первой странице даташита на атмеловские АВР-ки дано потребление в спящем режиме. Доплюсуй до этого потребление остальной периферии (ЖКИ, датчики и прочую лабуду можно отрубать от питания в спящем режиме). Только теперь встает вопрос - как будить? Через внешнее прерывание?
Если нет требований к точности измерения временных промежутков - то юзай внутренний и не парься.
более менее понятно. еще
более менее понятно. еще разобраться, какой командой уводить в сон, и что начинает происходить после пробуждения (и что, если это же внешнее прерывание уже используется в других целях?). приплюсовать потребление в этом случае - подразумевается потребление ИК датчика (и резонатора)? и кстати, отрубать остальную периферию - через 0 на ножке микроконтроллера, или есть какие-то другие хитрые методы?
про точность измерений - в том-то и вопрос, хватит мне внутреннего для отсчета импульсов RC5 и DS18B20?
asm("sleep"); После
asm("sleep");
После пробуждения происходит загрузка состояния МК из "свопа".
Тогда внешнее прерывание будет выводить МК из сна.
Отрубать остальное можно и через 0 и через 1. Сморя какой транз поставишь.
Для работы с DS18b20 хватит точности встроенного RC генератора.
а для ИК внутреннего
а для ИК внутреннего генератора хватит? а для управления сервой?
то есть транзистор в закрытом состоянии энергию не потребляет? а микроконтроллер в спящем режиме по-прежнему способен выдавать 1 и при этом с минимальным потреблением?
и еще, как отключать сервопривод? или если нет pwm сигнала, то энергию он тоже не потребляет?
Ну блин, подумай, хватит тебе
Ну блин, подумай, хватит тебе тактовой частоты 8Мгц?
Транзистор в закрытом состоянии потребляет, зависит от типа и модели транзистора. МК в спящем режиме может выдавать на ножки как лог. ноль, так и лог. единицу.
Сервопривод отключи от питания транзисторным ключом. Если на входе ШИМа ноль, то серва все равно есть какой-то ток.
Все правильно, делаешь
Все правильно, делаешь программу, которая определяет какой код кнопки пришел.
Код из трех цифр состоит. Выбрал нужные кнопки напрмиер кнопка громкость + и -.
Записал к примеру номера кнопок: 102 и 103. Теперь надо программу, которая будет реагировать на эти масивы данных. Я именно так и делал, потом провреял поэлементно на сходство с принятым кодом. И если код пришел тот, что надо, значит выполняются действия.
Код программы вечером попробую выложить.
Для записи видео с монитора.
Есть хорошая программа HyperCam.
Ок А то бывает иногда очень
Ок А то бывает иногда очень надо что-то снять, а айфон не снимает видео у меня 3G а старый Сони Эриксон вот так снимает как на видео.