Прием команд с пульта дистанционного управления

Обновлено 21.01.14. Исходники переписаны под AVR Studio 6 (с тулчейном)

В этой статье я расскажу, как принимать команды с пульта (ПДУ) с кодировкой RC5. Подробное описание протокола не имеет смысла так как этого в интернете предостаточно.

Схема:

Микроконтроллер Atmega8 (тактирование 1 МГц от внутреннего генератора), ИК-приемник TSOP1736 подключен к входу захвата ICP, на порту D висят светодиоды.



Я все это сделал на своей отладочной плате, которую спаял когда то минут за 20.

Верху слева ИК-приемник, справа - светодиоды.

Итак, сейчас мы сделаем чтобы при нажатии на цифровую кнопку на ПДУ зажигался соответствующий светодиод (от 0 до 7). Код, ну очень простой:
#include "rc5.h"
#include "main.h"

int main (void)
{
PORTB = 0b00000000; DDRB = 0b00000000;
PORTC = 0b00000000; DDRC = 0b00000000;
PORTD = 0b00000000; DDRD = 0b11111111; // тут светодиоды

Rc5_SetRx(); // инициализируем таймер 1

sei(); // глобально разрешаем прерывания

while(1)
{
if (rc5.dataOK) { // если получены данные с ПДУ
PORTD = 0; // тушим все светодиоды
sbi(PORTD, rc5.command); // зажигаем светодиод, соответствующий комманде с ПДУ

rc5.dataOK = 0; // сбрасываем флаг
}
}

}

После инициализации таймера и разрешения прерываний включается захват, и микроконтроллер начинает обрабатывать данные, принятые с пульта. Если получен пакет данных, то активируется флаг rc5.dataOK, а принятая команда записывается с переменную структуры rc5.command.
Стоит иметь ввиду, что пульт отправляет не только команду, а и номер системы, если 0, то это команда для телевизора.
rc5.h содержит функции, для работы с RC5 и структуру rc5:
struct {
unsigned char control_bit;
unsigned char system;
unsigned char command;
unsigned char flag;
unsigned char dataOK;
unsigned char error;
} rc5;

После приема пакета с пульта поднимается флаг dataOK, в system записывается номер системы, в command - номер команды, если в пакете была ошибка, то поднимается флаг error.

А вот видео работы устройства: http://youtu.be/Dqghjc3oivY

Скачать файлы

Комментарии

  1. Здравствуйте, а нет ли у Вас кода с таким алгоритмом, нажали на кнопку пульта светик горит, отпустили светик погас(ну очень нужно).

    ОтветитьУдалить
  2. типа так:
    while(1)
    {
    if (rc5.dataOK) { // если получены данные с ПДУ
    sbi(PORTD, 1); // зажигаем светодиод на PORTD.1
    rc5.dataOK = 0; // сбрасываем флаг
    }
    else сbi(PORTD, 1); // если данные не получены, тушим светодиод на PORTD.1

    _delay_ms(700);
    }

    ОтветитьУдалить
  3. Интересно!
    Попробую собрать. А фюз биты как выставить в программе AVRDUDE?

    ОтветитьУдалить
  4. их менять не надо, (если применяешь атмегу), прошивка заточена под 1МГц

    ОтветитьУдалить
  5. Как я понял, светодиод только один может гореть? А нету у Вас прошивки что б все диоды можно было включить?
    Спасибо.

    ОтветитьУдалить
  6. PORTD = 0; // тушим все светодиоды
    sbi(PORTD, rc5.command); // зажигаем светодиод, соответствующий комманде с ПДУ

    замени на PORTD = 0xFF;

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

    int u=0;//декларируем переменную состояния, задаем значение 0
    /////////////////////////////////////////////////
    if(u==0) //если предидущее значение было ноль
    {u=1;}//меняем на единицу
    else
    {u=0;}//если не ноль то меняем на ноль
    break;
    /////////////////////////////////////////////////

    void u_check (void)
    {
    if(u==0) {PORTB = 0b00000001;}//включаем светодиод
    else (PORTB = 0b00000000;}//выключаем светодиод
    }, но я не пойму как сделать переход или условие, в rc5.command что именно хранится?
    может так
    if (rc5.dataOK)
    if (rc5.command == 000001){ // если получены данные с ПДУ
    и эта кнопка 1
    if(u==0) //если предидущее значение было ноль
    {u=1;}//меняем на единицу
    else
    {u=0;}//если не ноль то меняем на ноль

    rc5.dataOK = 0; // сбрасываем флаг
    }

    ОтветитьУдалить
  8. На PORTB.0 висит приемник, этой ножкой дрыгать нельзя. Предложим, вам нужно управлять светодиодом на PORTD.0
    while(1)
    {
    if (rc5.dataOK) { // если получены данные с ПДУ
    if (rc5.command==1){ // если это кнопка 1
    if (CheckBit(PIND, 0)) cbi(PORTD, 0); // если светодиод включен, выключаем
    else sbi(PORTD, 0); // если светодиод выключен, включаем
    }

    rc5.dataOK = 0; // сбрасываем флаг
    }
    }

    ОтветитьУдалить
  9. отлично, получилось спасибо, теперь у меня возникло еще парочка вопросов что такое CheckBit и cbi? и куда лучше поставить задержку между приемами команда, а то лампочка сразу выключается((или не с первого раза включается(

    ОтветитьУдалить
  10. а это дефайны такие, чтобы было более удобно писать код.
    Задержку лучше ставить в конце бесконечного цикла (while(1))

    ОтветитьУдалить
  11. Здравствуйте, а Вы можете выложить HEX файл с таким алгоритмом:нажали на кнопку пульта светик горит, отпустили светик погас(ну очень нужно).

    ОтветитьУдалить
  12. ну так я же готовый исходник привел. просто вставь тот текст и скомпилируй

    ОтветитьУдалить
  13. Kibermaster, наверно я тебя замучил((( но у меня опять возникла проблема, помоги плиз, делаю дистанционное управление светом, первая часть получилась, а вторая нет, суть при нажатии одной клавиши с помощью шим яркость увеличивается, при нажатии другой-уменьшается, вот то что я смог сделать

    #include
    #include
    #include "rc5.h"
    #include "main.h"

    int main (void)
    {//1

    PORTB = 0b00000000; DDRB = 0b00000010;
    PORTC = 0b00000000; DDRC = 0b00000000;
    PORTD = 0b00000000; DDRD = 0b11111111; // òóò ñâåòîäèîäû
    unsigned int i=0;
    Rc5_SetRx(); // èíèöèàëèçèðóåì òàéìåð 1
    TCCR1A = (1 << COM1A1)|(0 << COM1A0) // Óñòàíîâèì áèòû COM1A1-COM1A0:0b10,
    // îçíà÷àåò ñáðîñ âûâîäà êàíàëà A ïðè ñðàâíåíèè
    |(1 << WGM11)|(0 << WGM10); // Óñòàíîâèì áèòû WGM13-10:0b1110, ñîãëàñíî òàáëèöå ýòî

    TCCR1B = (1 << WGM13)|(1 << WGM12) // áóäåò ðåæèì - FAST PWM, ãäå âåðõíèé ïðåäåë ñ÷åòà çàäàåòñÿ áèòîì ICR1
    |(0 << CS12)|(0 << CS11)|(1 << CS10); // Áèòàìè CS12-10:0b001 çàäàåì èñòî÷íèê òàêòîâîãî
    // ñèãíàëà äëÿ òàéìåðà ÌÊ, âêëþ÷åí áåç äåëèòåëÿ
    TCNT1 = 0x00; // íà÷àëüíàÿ óñòàíîâêà ñ÷åò÷èêà
    ICR1 = 0xFF; // çàäàåì ïåðèîä ØÈÌ, çäåñü ó íàñ ÷èñëî 255,
    // ïî ôîðìóëå fPWM=fclk_I/O/N*(1+ICR1)
    // âû÷èñëÿåì ÷àñòîòó ØÈÌ, îíà áóäåò ðàâíà 15625 Hz
    OCR1A = 0x00; // íà÷àëüíûé êîýôôèöèåíò çàïîëíåíèÿ ØÈÌ
    sei(); // ãëîáàëüíî ðàçðåøàåì ïðåðûâàíè

    while(1)
    {//2
    if (rc5.dataOK)
    { // åñëè ïîëó÷åíû äàííûå ñ ÏÄÓ 3
    if (rc5.command==7)
    { // åñëè ýòî êíîïêà 1 4
    if (i 0) // êîýôôèöèåíò çàïîëíåíèÿ ØÈÌ èçìåíÿåòñÿ îò 255 äî 0
    {
    i=i-20; // óìåíüøàåì i íà åäèíèöó(òàê òîæå ìîæíî ïèñàòü)
    OCR1A = i; // çàïèñûâàåì ïåðåìåííóþ â ðåãèñòð ñðàâíåíèÿ
    }
    }
    rc5.dataOK = 0; // ñáðàñûâàåì ôëàã
    }
    }
    }

    ссылался на http://radioparty.ru/index.php/prog-avr/program-c/240-lesson8?start=3

    ОтветитьУдалить
  14. Kibermaster, наверно я тебя замучил((( но у меня опять возникла проблема, помоги плиз, делаю дистанционное управление светом, первая часть получилась, а вторая нет, суть при нажатии одной клавиши с помощью шим яркость увеличивается, при нажатии другой-уменьшается, вот то что я смог сделать

    #include
    #include
    #include «rc5.h»
    #include «main.h»

    int main (void)
    {//1

    PORTB = 0b00000000; DDRB = 0b00000010;
    PORTC = 0b00000000; DDRC = 0b00000000;
    PORTD = 0b00000000; DDRD = 0b11111111;
    unsigned int i=0;
    Rc5_SetRx();
    TCCR1A = (1 << COM1A1)|(0 << COM1A0)

    |(1 << WGM11)|(0 << WGM10);

    TCCR1B = (1 << WGM13)|(1 << WGM12)
    |(0 << CS12)|(0 << CS11)|(1 << CS10);
    TCNT1 = 0×00;
    ICR1 = 0xFF;

    OCR1A = 0×00;
    sei();

    while(1)
    {//2
    if (rc5.dataOK)
    {
    if (rc5.command==7)
    {
    if (i 0)
    {
    i=i-20;
    OCR1A = i;
    }
    }
    rc5.dataOK = 0;
    }
    }
    }

    ссылался на http://radioparty.ru/index.php/prog-avr/program-c/240-lesson8?start=3

    ОтветитьУдалить
  15. А чем скомпилировать?

    ОтветитьУдалить
  16. как заставить этот код работать на 8МГц?

    ОтветитьУдалить
  17. как я понял в этом месте с погрешностью не более 10%
    // RC5_T нужно расчитать вручную (особенности компилятора)
    #define RC5_T 14304 //((F_CPU/PRESCALER/1000)*1.778) в моем случае получается 14304(8000*1.778)
    #define FAULT_TIME_RC5 RC5_T*17 // не должно быть более 65535
    #define TOLERANCE (RC5_T/10) // 10%

    не получается решить проблему с не стабильностью включения выключения(думал подниму частоту добавлю стабильности)))
    что посоветуете?

    ОтветитьУдалить
  18. а что там нестабильного?

    ОтветитьУдалить
  19. я сразу прошу прощения за свой быдло код))) когда я делаю так(см.код) то отклики не стабильны либо сразу включится и выключится или вкл. но с 3его раза вобщем в этом духе. не прошу код за меня написать прошу хотя бы направить на путь истинный. чую что должно быть но сообразить не могу.

    #include
    #include
    #include "rc5.h"
    #include "main.h"
    //#include

    int main (void)
    {
    PORTD = 0b00000000; DDRD = 0b00000000; // прием
    PORTA = 0b00000000; DDRA = 0b11111111;
    PORTC = 0b00000000; DDRC = 0b11111111;

    Rc5_SetRx(); // инициализируем таймер 1

    sei(); // глобально разрешаем прерывания

    while(1)
    {
    if (rc5.dataOK) { // если получены данные с ПДУ
    if (rc5.command==1){ // если это кнопка 1
    if (CheckBit(PINA, 0)) cbi(PORTA, 0); // если светодиод включен, выключаем
    else sbi(PORTA, 0); // если светодиод выключен, включаем
    }
    rc5.dataOK = 0; // сбрасываем флаг

    }
    /*
    if (rc5.dataOK) { // если получены данные с ПДУ
    if (rc5.command==2){ // если это кнопка 1
    if (CheckBit(PINA, 1)) cbi(PORTA, 1); // если светодиод включен, выключаем
    else sbi(PORTA, 1); // если светодиод выключен, включаем
    }
    rc5.dataOK = 0; // сбрасываем флаг

    }*/
    if (rc5.dataOK) { // если получены данные с ПДУ

    if (rc5.command==9){ // если это кнопка 1
    if (CheckBit(PINC, 1)) cbi(PORTC, 1); // если светодиод включен, выключаем
    else sbi(PORTC, 1); // если светодиод выключен, включаем
    }
    rc5.dataOK = 0; // сбрасываем флаг

    //и так далие перебирая каждый порт
    }
    }
    }

    ОтветитьУдалить
  20. вместо того, чтобы дважды проверять приход данных, нужно просто проверять, какие данные пришли

    ОтветитьУдалить
  21. появилось время опять вернулся к RC5. но опять не получается решить не стабильность, т.е. нажатие на кнопку должно быть очень четким иначе происходит двойное, а то и тройное нажатие.

    while(1)
    {
    if (rc5.dataOK) {
    if (rc5.command==1){
    if (CheckBit(PINA, 0)) cbi(PORTA, 0);
    else sbi(PORTA, 0);
    }
    rc5.dataOK = 0;

    if (rc5.command==2){
    if (CheckBit(PINA, 1)) cbi(PORTA, 1);
    else sbi(PORTA, 1);
    }
    rc5.dataOK = 0;
    }
    }
    }

    ОтветитьУдалить
  22. просто нужно после выполнения алгоритма по нажатию кнопки (в конце if (rc5.dataOK)) ставить задержку где то на 0,7-1 секунду

    ОтветитьУдалить
  23. прееелестно) работает на 5 балов спасибо) до этого побывал задержки, но ставил не туда))

    ОтветитьУдалить
  24. сейчас прикидываю как код покрасивее сделать.

    ОтветитьУдалить
  25. Всем привет.
    Я в программировании полный 0, поэтому у меня есть немного вопросов.
    Спаял на днях вашу схему, и возник вопрос как и чем програмировать.
    В интернете нашел ну очень простую схему (даже и не схема :) ) программатора для AVR, так называемая "5 проводков".
    И вот вроде запрограммировал мк прошивкой из приложенного фаила (rc5.HEX) , но как привязать ее к пульту?
    программировал программой CodeVisionAVR.
    Пульт от Горизонта RC5-7.
    Подскажите пожалуйста.

    ОтветитьУдалить
  26. А что за кнопка?
    На схеме ее нету.
    И для чего она?

    ОтветитьУдалить
  27. я про кнопку на пульте

    ОтветитьУдалить
  28. да ни как привязывать не надо, просто прошить. После прошивки девайс должен реагировать на нажатие кнопок пульта

    ОтветитьУдалить
  29. у меня ни в какую...

    ОтветитьУдалить
  30. struct {
    unsigned char control_bit;
    unsigned char system;
    unsigned char command;
    unsigned char flag;
    unsigned char dataOK;
    unsigned char error;
    } rc5;

    можно поподробнее про это?

    ОтветитьУдалить
  31. Кстати, каким пультом вы пользуетесь? Мой подойдет?

    ОтветитьУдалить
  32. я просто пришел на базар и попросил пульт rc5:)

    ОтветитьУдалить
  33. #include "rc5.h"
    #include "main.h"

    int main (void)
    {
    PORTB = 0b00000000; DDRB = 0b00000000;
    PORTC = 0b00000000; DDRC = 0b00000000;
    PORTD = 0b00000000; DDRD = 0b11111111; // тут светодиоды

    Rc5_SetRx(); // инициализируем таймер 1

    sei(); // глобально разрешаем прерывания

    while(1)
    {
    if (rc5.dataOK) { // если получены данные с ПДУ
    PORTD = 0; // тушим все светодиоды
    sbi(PORTD, rc5.command); // зажигаем светодиод, соответствующий комманде с ПДУ

    rc5.dataOK = 0; // сбрасываем флаг
    }
    }

    }


    это полный код прошивки или только отрывок? Или вообще что это?)

    ОтветитьУдалить
  34. прошил... ничего не изменилось(

    ОтветитьУдалить
  35. а как вы прописали имено кнопки 1-8 (или какие там)?
    Помогите пожалуйста.

    ОтветитьУдалить
  36. ну при нажатии цифровых кнопок пульт передает цифру, которая написана на кнопке, а МК при приеме включает этот бит на порте МК

    ОтветитьУдалить
  37. я уже раз 20 пробовал прошить мк... все безуспешно...
    может я что-то не так делаю?
    можете если вас не затруднит подробно расписать процесс програмирования?
    или скажите, куда вам можно написать.

    ОтветитьУдалить
  38. так в инете же куча инфы как заливать прошивку с подробным описанием

    ОтветитьУдалить
  39. я не так изложил вопрос.
    Атмега у меня прошивается фаилом rc5.HEX !!! (или нужно кодом,выложенным в теме??? ) выложенным вами.
    после программирования нажимаю на кнопки ПДУ и ничего.
    такое чувство что пульт не подходит.
    перепробывал все пульты которые нашел... ничего.
    кстати! программировать отдельно мк, или можно прямо в схеме?
    Извените меня, если надоедаю тупыми вопросами... просто программирование это не мое... а вот эта схема позарез нужна...

    ОтветитьУдалить
  40. программировать можно любо как.
    если вы прошили нормально, то или ик-приемник нерабочий, или пульт не подходит

    ОтветитьУдалить
  41. ладно... сейчас попробую поменять приемник...

    ОтветитьУдалить
  42. програмировать нужно фаилом rc5.HEX (выложенным вами) ,или нужно кодом из темы???

    ОтветитьУдалить
  43. приемник проверил - рабочий.
    как можно проверить подходит пульт или нет?

    ОтветитьУдалить
  44. попробовать его на рабочем устройстве:)

    ОтветитьУдалить
  45. он рабочий.
    я спрашивал как проверить подходит пульт к схеме или нет?

    ОтветитьУдалить
  46. ну к схеме подходит пулmт с командами RC5. Если не написано на пульте, то разберите его и посмотрите, какая там стоит микра

    ОтветитьУдалить
  47. микросхема хз какая, залика компаундом (капля так называемая)

    ОтветитьУдалить
  48. Здравствуйте. У меня ИК-приемник SM0038 (приемник телевизора) схема будут работать для него?
    или только для TSOP1736?

    ОтветитьУдалить
  49. вообще, должен подойти, только распиновку проверьте. И еще частота может отличаться, из-за чего сигнал будет приниматься немного хуже

    ОтветитьУдалить
  50. Здравствуйте. У меня вопрос Atmega8 A сколько раз могу прошить ? 1000 раз или больший?

    ОтветитьУдалить
  51. в дш написано, что 10000

    ОтветитьУдалить
  52. я не мог найти datasheete. значит 10000 раз да . спасибо

    ОтветитьУдалить
  53. Здравствуйте. У меня программатор не прошивает больше 6 кб Ошибка выдают. программатор у меня Chip Blaster а чип Atmega8. Знаю что Atmega8 можно писать программу до 8 кб , а у меня hex файл 7 кб.
    Что делать помогите пожалуйста.

    ОтветитьУдалить
  54. hex - это прошивка в текстовом формате, реально она весит, помойму, меньше 1кб. Я думаю, что у вас какие то проблемы с тактированием, ну или с питанием

    ОтветитьУдалить
  55. Здравствуйте.Cпасибо за статью.
    Собрал на макетке - "поковырятся".Но меня больше интресовал алгоритм уже обсуждаемый с пользователем mastech ,при нажатии кнопки включался светодиод, по нажатии этой же клавиши второй раз, он выключался.
    С номером системы(№0) разобрался,поскольку пульт "самопальный" -пришлось компилировать новый hex,там был прописан №29-освещение.
    Добавил #include .Задержку 700 мс поставил в конце цикла while(1):

    while(1)
    {
    if (rc5.dataOK) // если получены данные с ПДУ
    {
    if (rc5.command==1) // если это кнопка 1
    {
    if (CheckBit(PIND, 0)) cbi(PORTD, 0); //если канал 1 включен, выключаем
    else sbi(PORTD, 0); // если канал 1 выключен, включаем
    }
    rc5.dataOK = 0; // сбрасываем флаг

    if (rc5.command==2) // если это кнопка 2
    {
    if (CheckBit(PIND, 1)) cbi(PORTD, 1); //если канал 2 включен, выключаем
    else sbi(PORTD, 1); // если канал 2 выключен, включаем
    }
    rc5.dataOK = 0; // сбрасываем флаг

    if (rc5.command==3) // если это кнопка 3
    {
    if (CheckBit(PIND, 2)) cbi(PORTD, 2); //если канал 3 включен, выключаем
    else sbi(PORTD, 2); // если канал 3 выключен, включаем
    }
    rc5.dataOK = 0; // сбрасываем флаг

    if (rc5.command==4) // если это кнопка 4
    {
    if (CheckBit(PIND, 3)) cbi(PORTD, 3); //если канал 4 включен, выключаем
    else sbi(PORTD, 3); // если канал 4 выключен, включаем
    }
    rc5.dataOK = 0; // сбрасываем флаг
    }
    _delay_ms(700); //задержка 700 мс
    }

    Правильно ли это?Работает нормально,но иногда замечается нечеткое срабатывание.Я еще бью на пульт,надо покупать заводской...

    ОтветитьУдалить
  56. установите задержку внутрь цикла if (rc5.dataOK), тогда срабатывание будет четким

    ОтветитьУдалить
  57. Так я ставил ее в конце цикла if (rc5.dataOK)после последнего rc5.dataOK = 0 - было еще хуже.Может в начале цикла поставить,первым после скобки.

    ОтветитьУдалить
  58. когда задержка стоит в цикле while(1), то наличие принятой команды проверяется каждые 700мс, есл иперенести эту задержку в if (rc5.dataOK) (в конец), то наличие принятой команды будет производиться постоянно и когда она появится, то сначала будет выполнение нужных функций, затем, через 700мс девайс будет опять реагировать на комманду с пду

    ОтветитьУдалить
  59. а, бля, rc5.dataOK = 0; нужно поставьт после задержки. Вобщем, так:
    while(1)
    {
    if (rc5.dataOK) // если получены данные с ПДУ
    {
    if (rc5.command==1) // если это кнопка 1
    {
    if (CheckBit(PIND, 0)) cbi(PORTD, 0); //если канал 1 включен, выключаем
    else sbi(PORTD, 0); // если канал 1 выключен, включаем
    }

    if (rc5.command==2) // если это кнопка 2
    {
    if (CheckBit(PIND, 1)) cbi(PORTD, 1); //если канал 2 включен, выключаем
    else sbi(PORTD, 1); // если канал 2 выключен, включаем
    }

    if (rc5.command==3) // если это кнопка 3
    {
    if (CheckBit(PIND, 2)) cbi(PORTD, 2); //если канал 3 включен, выключаем
    else sbi(PORTD, 2); // если канал 3 выключен, включаем
    }

    if (rc5.command==4) // если это кнопка 4
    {
    if (CheckBit(PIND, 3)) cbi(PORTD, 3); //если канал 4 включен, выключаем
    else sbi(PORTD, 3); // если канал 4 выключен, включаем
    }

    _delay_ms(700); //задержка 700 мс
    rc5.dataOK = 0; // сбрасываем флаг
    }

    }

    ОтветитьУдалить
  60. Я понял Вас конечно.Но я изначально так и сделал с задержкой,при этом при нечетком нажатии светодиод вспыхивал и потухал.Возможно увеличить задержку до 1сек.
    Та и пульт может давать погрешности,нужен заводской,хотя я делал его для аудиоусилителя - работал отлично.

    ОтветитьУдалить
  61. Ой извените я неувидел предпоследнее сообщение.

    ОтветитьУдалить
  62. Да Вы были правы,перепрошил все заработало.Да и флаг надо сбрасывать один раз в конце цикла.
    Большое спасибо.

    ОтветитьУдалить
  63. Добрый вечер Kibermaster.
    Подскажите,а как быть,если я хочу увеличить частоту МК Atmega8 до 8 МГц?
    Я так думаю нужно перещитывать RC5_T в файле rc5.h.Но как понять:


    // RC5_T нужно расчитать вручную (особенности компилятора)
    #define RC5_T 1778 //((F_CPU/PRESCALER/1000)*1.778)

    ???

    ОтветитьУдалить
  64. частоту поделить на пределитель таймера, поделить на 1000 и все это умножить на 1.778

    ОтветитьУдалить
  65. здравствуйте. как получить сигнал от ИК приемника(38 КГц) его data подключен в PB0 у.
    не знаю как настроит таймеры .
    помогите пожалуйста.
    за ранние спасибо.

    ОтветитьУдалить
  66. так в статье же все готовое есть

    ОтветитьУдалить
  67. Здравствуйте! Не могли бы Вы привести пример этого кода для CAVR - никак не получается портировать самостоятельно(((((

    ОтветитьУдалить
  68. сорри, но я в нем никогда не писал, но на 90% уверен, что код будет тот же

    ОтветитьУдалить
  69. здравствуйте. я собрал USB-HID устройство (прошивка под 12МГц внешний кварц).
    а вашей случей прошивка под 1МГц можно сделать 12МГц.(проверил не роботала )
    она будет работать?
    мой USB-HID устройство я хотел посмотреть команды пульта.
    свой USB-HID устройство не работает 1МГц.
    что делать помогите пожалуйста.

    ОтветитьУдалить
  70. в rc5.h сверху 2 макроса, которые надо под свою частоту пересчитать

    ОтветитьУдалить
  71. я не знаю как будет частоту 12МГц.
    напишите пожалуйста.

    ОтветитьУдалить
  72. напишите пожалуйста что меня и значения .

    ОтветитьУдалить
  73. #define RC5_T 2667
    а в функции Rc5_SetRx нужно установить делитель на 8:
    TCCR1B= _BV(CS11)|_BV(ICNC1);

    ОтветитьУдалить
  74. спасибо вам большое что вы помогайте мне.
    всё работает.
    Вы очень добрый человек.
    как вы расшитовали эта #define RC5_T 2667 ?
    меня тоже научите пожалуйста.
    за ранние спасибо.

    ОтветитьУдалить
  75. я хотел управлять часы с помощью пулта.
    я не знаю как будет частоту 32768 Гц. (часовой кварц )
    научите пожалуйста.

    ОтветитьУдалить
  76. напротив этого макроса есть формула, по которой можно посчитать.

    ОтветитьУдалить
  77. спасибо я всё понял значения PRESCALER=8

    ОтветитьУдалить
  78. добрый день, hex в архиве работает, как только я закомпиливаю код в атмел студио 6 работать перестаёт хоть и компилит без ошибок. в чём может быть проблема? я вообще с cvavr работал, может что не так делаю? создаю проект GCC C++ Executable Project потом с боку в solution explorer выбираю Atmegu8 добавляю файлы main.c rc5.c main.h rc5.h в проект и жму Buil All, соданный hex не работает :(

    ОтветитьУдалить
  79. лично у меня студия 5 и 6 как то криво работают. Я использую студию 4 и последний тулчейн

    ОтветитьУдалить
  80. да, инсталировал 4 версию и заработало. а может вы знаете что сделать чтобы на CVAVR заработало? компилмруя выдаёт 3 таких ошибки http://s21.postimg.org/ntrm55ul3/osybki.png

    ОтветитьУдалить
  81. ошибки, во первый, из-за того, что обработчики прерывания в CVAVR пишутся не так, как в WinAVR, а во вторых, из-за того, что в этих компиляторах разные макросы для битовых операций, ну и main должен объявлять по-ином, что и указано в ошибках на вашем скрине.
    int main(void) замените на void main(void)
    _BV(CS10) на (1<На счет прерываний - посмотрите в инете, как они должны объявляться в CVAVR.

    ОтветитьУдалить
  82. вот что вычитал в нете, но не доходит как точно нужно переписать это ISR(TIMER1_CAPT_vect) ? :/

    в CodeVision:

    interrupt [прерывание] void adc_isr(void)
    { }

    #include

    ISR(прерывание_vect)
    { }

    В примерах слово "прерывание" нужно заменить на название прерывания из ДатаШита либо из заголовочного файла *.h для используемого МК.

    ОтветитьУдалить
  83. Попробуйте что то типа
    interrupt [TIM1_ICMP] void timer1_icmp_isr(void)

    ОтветитьУдалить
  84. ещё больше ошибок стало :D

    ОтветитьУдалить
  85. исправил все пред идущие ошибки появилась одна последняя http://s24.postimg.org/4n4eitqgl/posledniaja.png в чём тут может быть проблема?

    ОтветитьУдалить
  86. замените структуру на:
    struct rc5_t{
    unsigned char control_bit;
    unsigned char system;
    unsigned char command;
    unsigned char flag;
    unsigned char dataOK;
    unsigned char error;
    } ;
    struct rc5_t rc5;

    ОтветитьУдалить
  87. всё равно тоже самое, не понимаю что за фигня, компилирует без ошибок, а Buil All при создании hex кидает эту ошибку. пробовал вообще удалять куски кода и вообще всё оставляя тот rc5.h и всё равно та ошибка

    ОтветитьУдалить
  88. Подтверждаю наблюдение sergejus'a - под AVR Studio 6.1 компилится, но не работает. Буду пробовать под 4-ой...

    ОтветитьУдалить
  89. Уважаемый Kibermaster, возник следующий вопрос: в доке по rc5 сказано, что часть команд (напр. громкость) передается в виде строки. Правильно ли я понял? И поддерживает ли Ваш код возврат значения этого типа?

    ОтветитьУдалить
  90. не строки, а набора импульсов. Фактически, там просто 3 байта

    ОтветитьУдалить
  91. Мужики. не работает. компилится. но кнопки на пульте жму - не работает.
    компилил и под 6.1 авр студио и под 4й. результат один.

    у меня вместо 8й меги стоит 32я. порты в функции мейн поменял под свои. мб что менять надо еще в коде?

    и ик-приемник стоит 536aa3p. работоспособность проверена.

    в чем может быть дело?

    ОтветитьУдалить
  92. если приемник подключили правильно (распиновка не как у TSOP1736)? то советую перекомпилировать в 4 студии

    ОтветитьУдалить
  93. приемник подключен правильно проверял его. подключал к int0. работает.
    в 4й студии компилил результат тот же.
    а может дело в пульте? я от телека беру самсунга. aa59-00581a
    такой
    http://www.displayland.ru/images/pdu/AA59-00581A.jpg
    мож он сигналы какие не те посылает?

    ОтветитьУдалить
  94. от самсунга не подойдет, так как там кодировка другая

    ОтветитьУдалить
  95. Ой. получилось. сначала купил пульт горизонт rc-5 mini. не работало. потом заменил ик-приемник на sm3374. и все заработало) кстати компилил в атмел студио 6.1

    ОтветитьУдалить
  96. Автор, спасибо за статью и подскажите что за чудеса творятся..
    Главный код. Вот так не работает (Ваш код):

    while(1)
    {
    if (rc5.dataOK) { // если получены данные с ПДУ
    PORTD = 0; // тушим все светодиоды
    sbi(PORTD, rc5.command); // зажигаем светодиод, соответствующий комманде с ПДУ

    rc5.dataOK = 0; // сбрасываем флаг
    }
    }



    А вот так работает:

    int i=0;
    while(1)
    {
    if (rc5.dataOK) { // если получены данные с ПДУ
    PORTA = 0; // тушим все светодиоды
    sbi(PORTA, rc5.command); // зажигаем светодиод, соответствующий комманде с ПДУ

    rc5.dataOK = 0; // сбрасываем флаг
    }
    if (i++>20000) //Считаем 20к прохождения кода
    {
    i=0; //сбрасываем переменную счета
    PORTA = 0; // тушим все светодиоды
    }
    }

    Эта штука просто выключает порт с задержкой. Но почему она влияет на работу главного кода? Без нее вообще не работает.
    Если вместо всего этого моего ифа поставить i=0; (что тоже бессмысленно и не влияет на работу кода), то работает, но оочень тупит. Очень долго нужно жать на кнопку пульта чтобы состояние светодеодов изменилось.
    Такое чувство, что нужно писать какой нибудь код после кода if(rc5.dataOK), всё равно какой, но лишь бы чтоб он был..
    Просто чудеса..
    Микроконтроллер AtMega-16.
    Спасибо.

    ОтветитьУдалить
  97. И еще вопрос. Можно каким-то чудом сделать это всё на кварце 16 мгц? Может как-то прескейлер настроить.. Пробовал, ничего не вышло.
    PS. Дефайны пересчитывал..

    ОтветитьУдалить
  98. Получается так:
    При нажатии кнопки на пду он отправляет комманду, мк ее принимает и обрабатывает, так как после кода обработки ничего нет, то он сразу же опять реагирует на комманду с пду (при зажатой кнопке она отправляется несколько раз в секунду). Вобщем, после обработки программы сделайте задержку 1 секунду.

    ОтветитьУдалить
  99. в rc5.h переопределить дефайны.

    ОтветитьУдалить
  100. Спасибо заработало. Тогда не получилось. Всё так же сделал. Может та проблема повлияла.
    Может кому понадобится:
    настройки под 16мГц

    в rc5.h :
    #define RC5_T 111 //((F_CPU/PRESCALER/1000)*1.778) //хотя я думаю ничего страшного что получилось 111,125

    в rc5.с
    TCCR1B = _BV(CS12) | _BV(ICNC1); //Предделитель: 256

    На делителе 1024 не получилось.

    ОтветитьУдалить
  101. Здравствуйте, Kibermaster!
    Как правильно написать код, чтобы при нажатии на кнопку "1" пульта выполнялась первая программа (несколько комбинаций светодиодов), при нажатии на кнопку "2" - вторая программа...
    а то у меня кучу ошибок выдает типа: ../main.c:33: error: lvalue required as left operand of assignment

    ОтветитьУдалить
  102. а что вы написали?

    ОтветитьУдалить
  103. я хочу написать программку для гирлянды

    ОтветитьУдалить
  104. вы писали, что у вас куча ошибок, откуда они взялись?
    Пишите через reply, иначе буду удалять

    ОтветитьУдалить
  105. не могу кирилицу выставить...
    я только учусь и пытаюсь такой код написать:

    #include
    #include
    #include
    #include "rc5.h"
    #include "main.h"

    int main (void)
    {
    PORTB = 0b00000000; DDRB = 0b00000000;
    PORTC = 0b00000000; DDRC = 0b11111111;
    PORTD = 0b00000000; DDRD = 0b11111111; // òóò ñâåòîäèîäû

    Rc5_SetRx(); // èíèöèàëèçèðóåì òàéìåð 1

    sei(); // ãëîáàëüíî ðàçðåøàåì ïðåðûâàíèÿ

    while(1)
    {
    if (rc5.dataOK) { // Если получены данные с пульта
    {
    if (rc5.command==1) // åñëè ýòî êíîïêà 1
    {

    PORTD = 0; // òóøèì âñå ñâåòîäèîäû
    sbi(PORTD, 0); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTD, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTD, 2); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTD, 3); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b00011111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b00111111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b01111111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b11111111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ

    }

    rc5.dataOK = 0; // ñáðàñûâàåì ôëàã
    }

    {
    if (rc5.command==2) // åñëè ýòî êíîïêà 2
    {
    PORTB = 0; // òóøèì âñå ñâåòîäèîäû
    PORTC = 0; // òóøèì âñå ñâåòîäèîäû
    PORTD = 0; // òóøèì âñå ñâåòîäèîäû
    sbi(PORTC = 0b00001111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b00011111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b00101111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b01001111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b10001111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b01001111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b00101111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC = 0b00011111, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ

    }
    rc5.dataOK = 0; // ñáðàñûâàåì ôëàã

    }

    }

    }

    ОтветитьУдалить
  106. while(1)
    {
    if (rc5.dataOK) { // если получены данные с ПДУ
    if (rc5.command==1) {
    // программа по нажатию 1
    }
    else if (rc5.command==2) {
    // программа по нажатию 2
    }
    }
    }

    ОтветитьУдалить
  107. спасибо, а саму программку и сброс флага где записать?

    ОтветитьУдалить
  108. Подскажите пожалуйста, как можно сократить запись задержки, чтобы не под каждой строкой ее писать?

    #include "avr/io.h"
    #include "avr/interrupt.h"
    #include "avr/delay.h"
    #include "rc5.h"
    #include "main.h"

    int main (void)
    {
    PORTB = 0b00000000; DDRB = 0b00000000;
    PORTC = 0b00000000; DDRC = 0b11111111;
    PORTD = 0b00000000; DDRD = 0b11111111; // òóò ñâåòîäèîäû

    Rc5_SetRx(); // èíèöèàëèçèðóåì òàéìåð 1

    sei(); // ãëîáàëüíî ðàçðåøàåì ïðåðûâàíèÿ

    while(1)
    {
    if (rc5.dataOK) { // åñëè ïîëó÷åíû äàííûå ñ ÏÄÓ
    if (rc5.command==1)
    {
    // ïðîãðàììà ïî íàæàòèþ 1
    PORTD = 0; // òóøèì âñå ñâåòîäèîäû
    sbi(PORTD, 0); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTD, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTD, 2); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTD, 3); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC,0b00011111); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC, 0b00111111); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC, 0b01111111); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC, 0b11111111); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ

    }

    rc5.dataOK = 0; // ñáðàñûâàåì ôëàã
    }


    else if (rc5.command==2) {
    // ïðîãðàììà ïî íàæàòèþ 2

    PORTD = 0; // òóøèì âñå ñâåòîäèîäû
    sbi(PORTD, 0); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTD, 1); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTD, 2); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTD, 3); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC,0b00011111); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC, 0b00111111); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC, 0b01111111); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ
    sbi(PORTC, 0b11111111); // çàæèãàåì ñâåòîäèîä, ñîîòâåòñòâóþùèé êîììàíäå ñ ÏÄÓ
    _delay_ms(500); //çàäåðæêà 500 ìñ

    }

    rc5.dataOK = 0; // ñáðàñûâàåì ôëàã
    }

    }

    ОтветитьУдалить
  109. и последнее.
    У меня выдает ошибку, но не пойму чего от меня надо:
    c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/ld.exe: rc5.elf section .text will not fit in region text
    c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/ld.exe: region text overflowed by 608 bytes
    make: *** [rc5.elf] Error 1
    Build failed with 2 errors and 0 warnings...

    ОтветитьУдалить
  110. через функцию или define

    ОтветитьУдалить
  111. думаю, что проблемы с кодировкой. Установите ANSI

    ОтветитьУдалить
  112. а где поменять кодировку?
    не могу ее найти...

    ОтветитьУдалить
  113. Наверно, где то в настройках редактора. Но у меня всегда изначально была установлена кодировка ANSI, менять ее никогда не приходилось

    ОтветитьУдалить
  114. спасибо, буду еще искать

    ОтветитьУдалить
  115. Нашел проблему!
    В пути к папке проекта была папка с русским наименованием.
    Как только перенес проект в корень диска - ошибки пропали.

    ОтветитьУдалить
  116. Подскажите пожалуйста, почему так происходит?
    Я увеличиваю размер программы, соответственно вижу, что увеличивается объем файлов: main.c, Makefil, а после компиляции файл rc5.hex остается с прежним весом.

    ОтветитьУдалить
  117. это сложно сказать. Makefile практически не влияет на размер (кроме некоторых опций), но в этом проекте он не используется (генерируется автоматом). А hex меняется, но не значительно. напишите в коде volatile int ttt[1000] и увидите, как увеличится hex

    ОтветитьУдалить
  118. Пробовал установить volatile int ttt[1000] в разных участках кода, но на размер hex это не повлияло.
    К стати, а что за файл .elf ? Он тоже не меняет свой размер.
    А файлы rc5.cci и rc5.hci вообще у меня не формируются.

    ОтветитьУдалить
  119. об elf почитайте в инете. А в проекте есть еще какие то hex файлы?

    ОтветитьУдалить
  120. сегодня постараюсь проверить на работоспособность программку.

    ОтветитьУдалить
  121. для code vizion avr,как этот код переделать?

    ОтветитьУдалить
  122. хз, я с ним не работал

    ОтветитьУдалить
  123. а вы в каком компилировали?

    ОтветитьУдалить
  124. AVR Studio 4 в связке с тулчейном

    ОтветитьУдалить
  125. а еще не подскажите avr studio выдает такую ошибку,,make: Makefile: No such file or directory,в чем может быть дело?

    ОтветитьУдалить
  126. возможно, в пути находятся не латинские символы.
    Пишите через Reply, иначе буду удалять.

    ОтветитьУдалить
  127. подскажитьте пожалуйста avr studio дает такую ошибку,код копирую

    ОтветитьУдалить
  128. вот что пишет ../priem.c:1:17: fatal error: rc5.h: No such file or directory

    ОтветитьУдалить
  129. возможно, в пути есть не латинские символы. Пишите через REply, иначе буду удалять

    ОтветитьУдалить
  130. как понять в пути не латинские символы?

    ОтветитьУдалить
  131. по какому пути лежит папка с проектом?

    ОтветитьУдалить
  132. папка с проектом лежит в локальном диске D ,AVR STUDIO4? а куда лучше положить?

    ОтветитьУдалить
  133. Скиньте архив с проектом.
    На счет reply - последнее предупреждение, далее добавляю в блэклист

    ОтветитьУдалить
  134. https://mail.yandex.ru/neo2/#disk/disk/ вот здесь архив посмотрите что там может быть не так

    ОтветитьУдалить
  135. програмирую hex файлом тоже от микроконтролера молчание

    ОтветитьУдалить
  136. програмирую hex файлом микроконтролер малчит

    ОтветитьУдалить
  137. дайте хотя бы какие то файлы с вашим проектом. Я не экстрасенс.

    ОтветитьУдалить
  138. https://mail.yandex.ru/neo2/#disk/disk/ вот здесь лежат файлы

    ОтветитьУдалить
  139. мне нужны файлы, а не ссылка на яндекс диск

    ОтветитьУдалить
  140. [code]http://speedy.sh/UBbeV/makros.rar[/code]

    ОтветитьУдалить
  141. кибермастер,как вам отправить файлы,тут только по ссылке

    ОтветитьУдалить
  142. Добрый вечер.Вот бьюсь над одной проблемой,есть код,который включает/выключает канал 1-4,в зависимости от нажатой кнопки на пульте 1-4:

    #include
    #include
    #include
    #include "rc5.h"
    #include "main.h"

    int main (void)
    {
    PORTB = 0b00000000; DDRB = 0b00000000;
    PORTC = 0b00000000; DDRC = 0b00000000;
    PORTD = 0b00000000; DDRD = 0b11111111; // тут светодиоды

    Rc5_SetRx(); // инициализируем таймер 1

    sei(); // глобально разрешаем прерывания

    while(1)
    {
    if (rc5.dataOK) // если получены данные с ПДУ
    {
    if (rc5.command==1) // если это кнопка 1
    {
    if (CheckBit(PIND, 0)) cbi(PORTD, 0); //если канал 1 включен, выключаем
    else sbi(PORTD, 0); // если канал 1 выключен, включаем
    }
    if (rc5.command==2) // если это кнопка 2
    {
    if (CheckBit(PIND, 1)) cbi(PORTD, 1); //если канал 2 включен, выключаем
    else sbi(PORTD, 1); // если канал 2 выключен, включаем
    }
    if (rc5.command==3) // если это кнопка 3
    {
    if (CheckBit(PIND, 2)) cbi(PORTD, 2); //если канал 3 включен, выключаем
    else sbi(PORTD, 2); // если канал 3 выключен, включаем
    }
    if (rc5.command==4) // если это кнопка 4
    {
    if (CheckBit(PIND, 3)) cbi(PORTD, 3); //если канал 4 включен, выключаем
    else sbi(PORTD, 3); // если канал 4 выключен, включаем
    }
    _delay_ms(700); //задержка 700 мс
    rc5.dataOK = 0; // сбрасываем флаг
    }
    }
    }

    Все бы хорошо,но вот если нажатую кнопку пульта "передержать" соответствующий канал включается/выключается.А хотелось чтобы канал включился,и контролер ждал отпускания кнопки пульта,а уже потом обрабатывал следующее нажатие.
    Пробовал вставлять

    ...
    _delay_ms(700); //задержка 700 мс
    rc5.dataOK = 0; // сбрасываем флаг

    while (rc5.dataOK) ;//ждем отпускания кнопки

    Результат нулевой,канал вкл/выкл.
    Я начинающий прошу не судить строго если чего не так.

    ОтветитьУдалить
  143. сделайте задержку не 700 мс, а, к примеру, 1500

    ОтветитьУдалить
  144. кибермастер объясните мне пожалуйсто почему у меня авр студии все проекты компилируются ,а вот именно этот нет,что я не так делаю? хекс файл на отладочной плате работает,в чем может быть причина?

    ОтветитьУдалить
  145. какие ошибки показывает?

    ОтветитьУдалить
  146. не существующая деректива "rc-5" и main.h

    ОтветитьУдалить
  147. ../c.c:3:17: fatal error: rc5.h: No such file or directory

    ОтветитьУдалить
  148. выше 2 человека задавали этот вопрос

    ОтветитьУдалить
  149. а толчейн он туда же устанавливается,просто у меня все на диске d папок с русским названием нигде нет,а ошибка все равно вылазиит,у вас какая авр студия?

    ОтветитьУдалить
  150. тулчейн последний. Попробуйте добавить в опции коомпилятора __PROG_TYPES_COMPAT__

    ОтветитьУдалить
  151. нет не идет,незнаю что ей надо,все программы компилирует а эту не хочет.

    ОтветитьУдалить
  152. Кибермастер как вот это по другому прописать? #include "rc5.h"
    #include "main.h" и sbi.

    ОтветитьУдалить
  153. Strideman
    14.09.2013 at 3:33 дп · Ответ
    Спасибо заработало. Тогда не получилось. Всё так же сделал. Может та проблема повлияла.
    Может кому понадобится:
    настройки под 16мГц

    в rc5.h :
    #define RC5_T 111 //((F_CPU/PRESCALER/1000)*1.778) //хотя я думаю ничего страшного что получилось 111,125

    в rc5.с
    TCCR1B = _BV(CS12) | _BV(ICNC1); //Предделитель: 256

    На делителе 1024 не получилось.

    Вот перещитал на 16 МГц ,предделитель на 8

    // RC5_T нужно расчитать вручную (особенности компилятора)
    #define RC5_T 3556 //((F_CPU/PRESCALER/1000)*1.778)
    #define FAULT_TIME_RC5 RC5_T*17 // не должно быть более 65535

    Получается целое число,и главное работает в "метале" - проверенно.

    ОтветитьУдалить
  154. Kibermaster, я читал полностью все комментарии, но вопросов все же есть. Вы говорите что пульт передает цифру в посылке команды, а как сделать чтоб реагировал не на цифровые клавиши а на другие к примеру ON/OFF MUTE и т.д. У меня есть сомнение, привожу пример. Есть пульт первый от телевизора и второй тоже от другого телевизора, если скажем что оба пульта работают на устройстве при нажатии клавиш, значит МК думает что принимает один и тот же сигнал с обоих пульта, но в реальности эти сигналы не одинаковы же, потому что первый телевизор не принимает сигнал от второго. Объясните пожалуйста.

    ОтветитьУдалить
  155. На счет кнопок MUTE и т.д., они тоже передают числовое значение (до 127 по-моему).
    Если поставить 2 одинаковых телевизора, у которых будут одинаковые пульты (с одинаковыми кодировками), то при нажатии кнопки на 1 пульте будут реагировать оба телевизора.

    ОтветитьУдалить
  156. Про телевизоры Вы не поняли наверное, но я только что читал про работу rc5 из других материалов. Пульт передает 14 бит, 2 бита стартовые 3-и дежурный и дальше 5 битов определены стандартом для разных устройств (тв, магнитофон и тд), а вот последние 6 бит отвечают за кнопки. Теперь я так думаю что, при приеме сигналов с разных пультов из разных устройств 5 бит могут быть разными, но последние 6 бит у всех одинаковы, я правильно понял?

    ОтветитьУдалить
  157. и еще, как привязать код только к одному пульту. чтоб другие пульты не реагировали.

    ОтветитьУдалить
  158. в структуре rc5 есть system и command, первый отвечает за тип команды (для телика, проигрывателя и т.д.)

    ОтветитьУдалить
  159. Один пользователь написал в комментариях что хочет портировать из AVR studio в CodeVision, у него получился? Я тоже хочу перевести, мой проект уже написан на нем, теперь хочу добавить ИК прием.

    ОтветитьУдалить
  160. это к нему вопрос)))))

    ОтветитьУдалить
  161. кибермастер подскажите как в этой программе зделать что бы при нажатии кнопки 1 диод горел при отпускании тух


    #include
    #include
    #include

    // Временные пределы
    #define Tmin 40 // длинный промежуток
    #define Tmax 68
    #define TminK 22 // короткий промежуток
    #define TmaxK 34

    unsigned char sct_bit = 0; // Счетчик битов RC5
    unsigned char RC5_buffer [14]; // Буфер RC5
    unsigned char centre = 0; // Флаг центра
    unsigned char not_korr = 0; // Флаг попадания в промежутки
    unsigned char Timer = 0; // число в счетчике таймера
    unsigned char command = 0; // переменная для команды
    char s = 0;

    // Функция очистки буфера
    void rc5_cl_buf(void)
    {
    unsigned char i = 0;
    for (i=0; i<14; i++)
    {
    RC5_buffer = 0;
    }
    }

    // функция остановки таймера
    void rc5_ti_stop(void)
    {
    GICR = 0x00;
    TCCR0 = 0x00;
    TCNT0 = 0;
    sct_bit = 0;
    }

    // Обработчик прерывния по переполнению Т0
    ISR (TIMER0_OVF_vect)
    {
    rc5_ti_stop(); //останавливаем таймер
    rc5_cl_buf(); //очищаем буфер
    GICR |= (1 << INT0); //разрешаем прерывания по входу INT0
    GIFR |= (1 << INTF0); //сбрасываем флаг прерывания (если произошло)
    }

    // Обработчик внешнего прерывания INT0
    ISR(INT0_vect)
    {
    Timer = TCNT0; // запоминаем значение счетчика
    TCNT0 = 0; // обнуляем счетчик
    not_korr = 1;

    if(sct_bit==0)
    {
    TCCR0 |= (1 << CS02); // запускаем таймер (31.250 KHz)
    RC5_buffer [sct_bit] = !(PIND&(1 < TminK)&&(Timer < TmaxK))
    {
    if (centre)
    {
    centre = 0;
    not_korr = 0;
    }
    else
    {
    centre = 1;
    RC5_buffer [sct_bit] = !(PIND&(1 < Tmin)&&(Timer < Tmax))
    {
    RC5_buffer [sct_bit] = !(PIND&(1 << PD2));
    sct_bit++;
    not_korr = 0;
    }

    if (not_korr == 1)
    { // если не попали ни в один из промежутков то
    rc5_ti_stop(); // останавливаем таймер
    rc5_cl_buf(); // очищаем буфер
    }

    if (sct_bit == 14)
    { // если бит последний то
    rc5_ti_stop(); // останавливаем таймер

    // Формируем код команды
    command = (RC5_buffer [8] << 5)|(RC5_buffer [9] << 4)|
    (RC5_buffer [10] << 3 )|(RC5_buffer [11] << 2)|
    (RC5_buffer [12] < 1)
    s = 0;

    }
    GICR |= (1 << INT0); // разрешаем прерывания по входу INT0
    GIFR |= (1 << INTF0); // сбрасываем флаг прерывания по входу INT0
    }
    }

    int main(void)
    {
    DDRB = 0xFF; // выход
    PORTB = 0x00;
    DDRD &= ~(1 << PD2); // вход ИК
    PORTD = 0x00;

    TIMSK |= (1 << TOIE0); // разрешение прерывания по таймеру0

    GICR |= (1 << INT0); // разрешаем прерывания по входу INT0
    MCUCR |= (1 << ISC00); // прерывание по любому фронту
    GIFR |= (1 << INTF0); // сбрасываем флаг прерывания

    sei(); // глобально разрешаем прерывания

    while(1)
    {
    if(s == 1)
    PORTB |= (1 << PB0); // Включаем светодиод
    if(s == 0)
    PORTB &= ~(1 << PB0); // Выключаем светодиод
    }
    }

    ОтветитьУдалить
  162. Ссылка на файлы не работает.

    ОтветитьУдалить
  163. день добрый. какую функцию выполняет CheckBit? из перевода ясно, что проверка бита, а что он проверяет и как реализовать если мне нужно включить несколько каналов.

    if (rc5.command==1)
    {
    if (CheckBit(PINC, 0)) //это с одной командой
    {
    cbi(PORTC, 0);
    }
    else sbi(PORTC,0)
    }
    //////////////////////////////////////////////////////////////////////

    if (rc5.command==1)
    {
    if (CheckBit(PINC, 0)) //а как быть с несколькими портами? перечислять через запятую?
    {
    cbi(PORTA, 0);
    cbi(PORTB, 1);
    cbi(PORTC, 2);
    cbi(PORTD, 3); ...

    ОтветитьУдалить
  164. Можно включать по отдельности.
    CheckBit(reg, b) - проверить бит регистра.
    sbi - установить бит регистра.
    cbi - сбросить бит регистра.

    ОтветитьУдалить
  165. Здравствуйте, Кибермастер! Подскажите, пожалуйста, как реализовать следующий эффект. При нажатии кнопки 1, включается цикл с первой программой, при нажатии 2 - цикл второй программы и т.д. Я никак не могу выйти из цикла и перейти к следующей программе. Какое должно быть условие? И как определить код кнопки Power на пульте, чтобы можно было всю гирлянду просто потушить.

    #include "delay.h"
    #include "rc5.h"
    #include "main.h"

    void main (void)

    {
    PORTB = 0b00000000; DDRB = 0b00000000; // тут светодиоды и на РВ7 ИК-порт
    PORTC = 0b00000000; DDRC = 0b00000000;
    PORTD = 0b00000000; DDRD = 0b11111100; // тут светодиоды
    Rc5_SetRx();

    #asm ("sei")

    while(1)
    {
    if (rc5.dataOK) { // если получены данные с ПДУ
    if (rc5.command==1) { // программа по нажатию 1
    while (1) {
    PORTD=0b00000100;
    delay_ms(500);
    PORTD=0b00001000;
    delay_ms(500);
    PORTD=0b00000100;
    delay_ms(500);

    };

    }
    else if (rc5.command==2) { // программа по нажатию 2
    while (1) {
    PORTD=0b00001100;
    delay_ms(500);
    PORTD=0b00011000;
    delay_ms(500);
    PORTD=0b00010100;
    delay_ms(500);
    };
    }
    else if (rc5.command==3) { // программа по нажатию 3
    while (1) {
    PORTB=0b00000000;
    PORTD=0b00000100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b00001100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b00011100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b00111100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b01111100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b11111100;
    delay_ms(100);
    PORTB=0b00000001;
    PORTD=0b11111100;
    delay_ms(100);
    PORTB=0b00000011;
    PORTD=0b11111100;
    delay_ms(100);
    };
    }


    delay_ms(700);
    rc5.dataOK = 0;
    }

    }
    }

    ОтветитьУдалить
  166. while(1)
    {
    if (rc5.dataOK) {
    rc5.dataOK = 0;

    switch (rc5.command) {
    case 1: while (rc5.dataOK==0) {
    // программа по нажатию 1
    } break;
    case 2: while (rc5.dataOK==0) {
    // программа по нажатию 2
    } break;
    // и т.д.
    }
    }
    }

    Код кнопки power - 12

    ОтветитьУдалить
  167. Здорово! Получилось! А то я уже все операторы цикла перебрал с различными условиями и результат = 0.
    А возможно ли после того как кнопкой power я потушил гирлянду, повторным нажатием на power включить гирлянду с того же case, на котором она была выключена?

    ОтветитьУдалить
  168. Сделайте переменную, в которую будет записываться последний кейс, после включения перед switch устанавливайте значение этой переменной в rc5.command

    ОтветитьУдалить
  169. Спасибо, сейчас поэкспериментирую.

    ОтветитьУдалить
  170. Подскажите, а какой оператор присваивания применить к переменной, чтобы записывалось значение последнего кейса?

    ОтветитьУдалить
  171. =. Вопрос сильно ламерский.

    ОтветитьУдалить
  172. я имел в виду, как указать, что это именно последний кейс, который работал до выключения

    ОтветитьУдалить
  173. при входе в каждый кейс перед while записывайте в нужную переменную значение с rc5.command

    ОтветитьУдалить
  174. Здравствуйте, Kibermaster!

    Уже много дней провел над решением своей задачи. Перечитывал Лебедева и Белова, пересмотрел массу обучающих роликов, но все же результат отрицательный.
    Я не понял подсказок, которые вы мне дали.

    Задача заключается в том, чтобы кнопкой power потушить гирлянду, а повторным нажатием на power включить гирлянду с того же case, на котором она была выключена?
    Чтобы программа продолжила работу после отключения питания я решил воспользоваться EEPROM.
    В ходе экспериментов наблюдал изменение EEPROM, но при подаче питания включения программы не происходит.
    Где у меня ошибки?

    #include "delay.h"
    #include "rc5.h"
    #include "main.h"

    eeprom char Canal_eep;
    unsigned char d;

    void main (void)

    {
    PORTB = 0b00000000; DDRB = 0b00000000; // тут светодиоды и на РВ7 ИК-порт
    PORTC = 0b00000000; DDRC = 0b00000000;
    PORTD = 0b00000000; DDRD = 0b11111100; // тут светодиоды
    Rc5_SetRx();


    d = Canal_eep;

    #asm ("sei")

    while(1)
    {

    if (rc5.dataOK) {
    rc5.dataOK = 0;


    Canal_eep = d;

    switch (rc5.command) {
    case 1:
    d = rc5.command;
    while (rc5.dataOK==0) { // программа по нажатию 1
    PORTD=0b00000100;
    delay_ms(500);
    PORTD=0b00001000;
    delay_ms(500);
    PORTD=0b00000100;
    delay_ms(500);
    } break;

    case 2:
    d = rc5.command;
    while (rc5.dataOK==0) { // программа по нажатию 2
    PORTD=0b00001100;
    delay_ms(500);
    PORTD=0b00011000;
    delay_ms(500);
    PORTD=0b00010100;
    delay_ms(500);
    } break;

    case 3:
    d = rc5.command;
    while (rc5.dataOK==0) { // программа по нажатию 3
    PORTB=0b00000000;
    PORTD=0b00000100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b00001100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b00011100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b00111100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b01111100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b11111100;
    delay_ms(100);
    PORTB=0b00000001;
    PORTD=0b11111100;
    delay_ms(100);
    PORTB=0b00000011;
    PORTD=0b11111100;
    delay_ms(100);
    } break;

    }
    }

    }


    delay_ms(500);
    rc5.dataOK = 0;
    }

    ОтветитьУдалить
  175. Тоесть, вам нужно сохранять последнее состояние даже после того, как будет полностью отключено питание микроконтроллера?

    ОтветитьУдалить
  176. Да, верно. Поэтому я и решил использовать EEPROM. Но, что-то не так. Смотрел различные ролики, пытался повторить, но видимо что-то упустил.

    ОтветитьУдалить
  177. int lastCommand = 1; // последняя полученая комманда. Счиитываем её с eeprom
    int state = 0; // состояние
    while(1)
    {
    if (rc5.dataOK) {
    rc5.dataOK = 0;

    if (rc5.command == 12) { // нажатие кнопки POWER
    if (state) { // если гирлянда включена
    state = 0;
    /// тушим гирлянду и сохраняем lastCommand в eeprom
    }
    else {
    state = 1;

    rc5.command = lastCommand;
    }
    }

    if (state) // если включено
    switch (rc5.command) {
    case 1: while (rc5.dataOK==0) {
    lastCommand = rc5.command; // сохраняем последнее нажатие
    // программа по нажатию 1
    } break;
    case 2: while (rc5.dataOK==0) {
    lastCommand = rc5.command; // сохраняем последнее нажатие
    // программа по нажатию 2
    } break;
    // и т.д.
    }
    }
    }

    ОтветитьУдалить
  178. Спасибо, сейчас буду испытывать.

    ОтветитьУдалить
  179. Есть ошибка Error: E:\Projects AVR\RC5_new\main.c(17): must declare first in block, ругается на

    int lastCommand = 1; // последняя полученая комманда. Счиитываем её с eeprom
    int state = 0; // состояние

    lastCommand и state где надо объявить, в файле mail.c или в структоре rc5.h

    ОтветитьУдалить
  180. Kibermaster, прости... не хватает моих скудных знаний.
    Куда я только не пытался уже поставить эти строки кода:
    int lastCommand = 1; // последняя полученая комманда. Счиитываем её с eeprom
    int state = 0; // состояние

    ругательства сплошные. То case1 включается при нажатии на POWER, то вообще не реагирует. При этом ошибок не выдает.
    Помоги пожалуйста.

    ОтветитьУдалить
  181. Добрый день, Kibermaster!
    Что я не так делаю? Срабатывание от кнопки POWER не постоянное (иногда надо дважды нажать, чтобы произошло переключение программы или вызов программы после отключения питания). И не удается включить последнюю исполняемую программу после подачи питания (т.е. не задействую кнопку POWER, подать питание и сразу включилась бы последняя программа).

    #include "delay.h"
    #include "rc5.h"
    #include "main.h"

    eeprom int d_eep;

    int lastCommand = 1; // последняя полученая комманда. Счиитываем её с eeprom
    int state = 0; // состояние

    void main (void)

    {
    PORTB = 0b00000000; DDRB = 0b00000000; // светодиоды и на РВ7 ИК-порт
    PORTC = 0b00000000; DDRC = 0b00000000; // светодиоды
    PORTD = 0b00000000; DDRD = 0b11111100; // светодиоды
    Rc5_SetRx();

    lastCommand = d_eep;

    #asm ("sei")

    while(1)
    {
    if (rc5.dataOK) {
    rc5.dataOK = 0;

    if (rc5.command == 12) { // нажатие кнопки POWER
    if (state) { // если гирлянда включена
    state = 0;
    PORTD=0b00000000;
    delay_ms(40);
    d_eep = lastCommand; /// тушим гирлянду и сохраняем lastCommand в eeprom
    }
    else {
    state = 1;
    rc5.command = lastCommand;
    }
    }
    if (state) // если включено

    switch (rc5.command) {
    case 1: while (rc5.dataOK==0) { // программа по нажатию 1
    lastCommand = rc5.command; // сохраняем последнее нажатие
    d_eep = lastCommand;
    PORTD=0b00000100;
    delay_ms(500);
    PORTD=0b00001000;
    delay_ms(500);
    PORTD=0b00000100;
    delay_ms(500);
    } break;

    case 2: while (rc5.dataOK==0) {
    lastCommand = rc5.command; // сохраняем последнее нажатие
    d_eep = lastCommand;
    PORTD=0b00001100;
    delay_ms(500);
    PORTD=0b00011000;
    delay_ms(500);
    PORTD=0b00010100;
    delay_ms(500);
    } break;

    case 3: while (rc5.dataOK==0) {
    lastCommand = rc5.command; // сохраняем последнее нажатие
    d_eep = lastCommand;
    PORTB=0b00000000;
    PORTD=0b00000100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b00001100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b00011100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b00111100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b01111100;
    delay_ms(100);
    PORTB=0b00000000;
    PORTD=0b11111100;
    delay_ms(100);
    PORTB=0b00000001;
    PORTD=0b11111100;
    delay_ms(100);
    PORTB=0b00000011;
    PORTD=0b11111100;
    delay_ms(100);
    } break;
    }
    }
    }

    delay_ms(700);
    rc5.dataOK = 0;
    }

    ОтветитьУдалить
  182. можно ли эту прошивку с некоторыми переделками закинуть на atmega 16a ножки и всё остальное вроде подходят?

    ОтветитьУдалить
  183. Можно. По сути, просто перекомпилируй под мегу16. Подключение к тем же пинам.

    ОтветитьУдалить
  184. ещё вопрос,это можно сразу в atmel studio перекомпилировать или код нужно менять?

    ОтветитьУдалить
  185. нет разницы какой ик-приёмник использовать?у меня TL1838 VS1838B 38 кГц

    ОтветитьУдалить
  186. просто перекомпилировать.

    ОтветитьУдалить
  187. Ресет обязательно подтягивать к +. А то что-то не хочет работать. Прошил хексом из папки дебаг.

    ОтветитьУдалить
  188. Не обязательно, но очень желаетльно

    ОтветитьУдалить

Отправить комментарий

Популярные сообщения из этого блога

STM32F4. Обновление прошивки с карты памяти (Bootloader SD)

Работа с шиной 1-wire. Подключение термодатчика DS18B20 к AVR