Прием команд с пульта дистанционного управления
Обновлено 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
Здравствуйте, а нет ли у Вас кода с таким алгоритмом, нажали на кнопку пульта светик горит, отпустили светик погас(ну очень нужно).
ОтветитьУдалитьтипа так:
ОтветитьУдалитьwhile(1)
{
if (rc5.dataOK) { // если получены данные с ПДУ
sbi(PORTD, 1); // зажигаем светодиод на PORTD.1
rc5.dataOK = 0; // сбрасываем флаг
}
else сbi(PORTD, 1); // если данные не получены, тушим светодиод на PORTD.1
_delay_ms(700);
}
Интересно!
ОтветитьУдалитьПопробую собрать. А фюз биты как выставить в программе AVRDUDE?
их менять не надо, (если применяешь атмегу), прошивка заточена под 1МГц
ОтветитьУдалитьКак я понял, светодиод только один может гореть? А нету у Вас прошивки что б все диоды можно было включить?
ОтветитьУдалитьСпасибо.
PORTD = 0; // тушим все светодиоды
ОтветитьУдалитьsbi(PORTD, rc5.command); // зажигаем светодиод, соответствующий комманде с ПДУ
замени на PORTD = 0xFF;
Подскажите пожалуйста, нужно что бы при нажатии кнопки включался светодиод, по нажатии этой же клавиши второй раз, он выключался, код примерно такой,
ОтветитьУдалить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; // сбрасываем флаг
}
На 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; // сбрасываем флаг
}
}
отлично, получилось спасибо, теперь у меня возникло еще парочка вопросов что такое CheckBit и cbi? и куда лучше поставить задержку между приемами команда, а то лампочка сразу выключается((или не с первого раза включается(
ОтветитьУдалитьа это дефайны такие, чтобы было более удобно писать код.
ОтветитьУдалитьЗадержку лучше ставить в конце бесконечного цикла (while(1))
Здравствуйте, а Вы можете выложить HEX файл с таким алгоритмом:нажали на кнопку пульта светик горит, отпустили светик погас(ну очень нужно).
ОтветитьУдалитьну так я же готовый исходник привел. просто вставь тот текст и скомпилируй
ОтветитьУдалить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
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
А чем скомпилировать?
ОтветитьУдалитькак заставить этот код работать на 8МГц?
ОтветитьУдалитькак я понял в этом месте с погрешностью не более 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%
не получается решить проблему с не стабильностью включения выключения(думал подниму частоту добавлю стабильности)))
что посоветуете?
а что там нестабильного?
ОтветитьУдалитья сразу прошу прощения за свой быдло код))) когда я делаю так(см.код) то отклики не стабильны либо сразу включится и выключится или вкл. но с 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; // сбрасываем флаг
//и так далие перебирая каждый порт
}
}
}
вместо того, чтобы дважды проверять приход данных, нужно просто проверять, какие данные пришли
ОтветитьУдалитьпоявилось время опять вернулся к 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;
}
}
}
просто нужно после выполнения алгоритма по нажатию кнопки (в конце if (rc5.dataOK)) ставить задержку где то на 0,7-1 секунду
ОтветитьУдалитьпрееелестно) работает на 5 балов спасибо) до этого побывал задержки, но ставил не туда))
ОтветитьУдалитьсейчас прикидываю как код покрасивее сделать.
ОтветитьУдалитьВсем привет.
ОтветитьУдалитьЯ в программировании полный 0, поэтому у меня есть немного вопросов.
Спаял на днях вашу схему, и возник вопрос как и чем програмировать.
В интернете нашел ну очень простую схему (даже и не схема :) ) программатора для AVR, так называемая "5 проводков".
И вот вроде запрограммировал мк прошивкой из приложенного фаила (rc5.HEX) , но как привязать ее к пульту?
программировал программой CodeVisionAVR.
Пульт от Горизонта RC5-7.
Подскажите пожалуйста.
А что за кнопка?
ОтветитьУдалитьНа схеме ее нету.
И для чего она?
я про кнопку на пульте
ОтветитьУдалитьда ни как привязывать не надо, просто прошить. После прошивки девайс должен реагировать на нажатие кнопок пульта
ОтветитьУдалитьу меня ни в какую...
ОтветитьУдалитьstruct {
ОтветитьУдалитьunsigned char control_bit;
unsigned char system;
unsigned char command;
unsigned char flag;
unsigned char dataOK;
unsigned char error;
} rc5;
можно поподробнее про это?
Кстати, каким пультом вы пользуетесь? Мой подойдет?
ОтветитьУдалитья просто пришел на базар и попросил пульт rc5:)
ОтветитьУдалить#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; // сбрасываем флаг
}
}
}
это полный код прошивки или только отрывок? Или вообще что это?)
полный код
ОтветитьУдалитьпрошил... ничего не изменилось(
ОтветитьУдалитьа как вы прописали имено кнопки 1-8 (или какие там)?
ОтветитьУдалитьПомогите пожалуйста.
ну при нажатии цифровых кнопок пульт передает цифру, которая написана на кнопке, а МК при приеме включает этот бит на порте МК
ОтветитьУдалитья уже раз 20 пробовал прошить мк... все безуспешно...
ОтветитьУдалитьможет я что-то не так делаю?
можете если вас не затруднит подробно расписать процесс програмирования?
или скажите, куда вам можно написать.
так в инете же куча инфы как заливать прошивку с подробным описанием
ОтветитьУдалитья не так изложил вопрос.
ОтветитьУдалитьАтмега у меня прошивается фаилом rc5.HEX !!! (или нужно кодом,выложенным в теме??? ) выложенным вами.
после программирования нажимаю на кнопки ПДУ и ничего.
такое чувство что пульт не подходит.
перепробывал все пульты которые нашел... ничего.
кстати! программировать отдельно мк, или можно прямо в схеме?
Извените меня, если надоедаю тупыми вопросами... просто программирование это не мое... а вот эта схема позарез нужна...
программировать можно любо как.
ОтветитьУдалитьесли вы прошили нормально, то или ик-приемник нерабочий, или пульт не подходит
ладно... сейчас попробую поменять приемник...
ОтветитьУдалитьпрограмировать нужно фаилом rc5.HEX (выложенным вами) ,или нужно кодом из темы???
ОтветитьУдалитьrc5.HEX
ОтветитьУдалитьприемник проверил - рабочий.
ОтветитьУдалитькак можно проверить подходит пульт или нет?
попробовать его на рабочем устройстве:)
ОтветитьУдалитьон рабочий.
ОтветитьУдалитья спрашивал как проверить подходит пульт к схеме или нет?
ну к схеме подходит пулmт с командами RC5. Если не написано на пульте, то разберите его и посмотрите, какая там стоит микра
ОтветитьУдалитьмикросхема хз какая, залика компаундом (капля так называемая)
ОтветитьУдалитьЗдравствуйте. У меня ИК-приемник SM0038 (приемник телевизора) схема будут работать для него?
ОтветитьУдалитьили только для TSOP1736?
вообще, должен подойти, только распиновку проверьте. И еще частота может отличаться, из-за чего сигнал будет приниматься немного хуже
ОтветитьУдалитьаха спасибо
ОтветитьУдалитьЗдравствуйте. У меня вопрос Atmega8 A сколько раз могу прошить ? 1000 раз или больший?
ОтветитьУдалитьв дш написано, что 10000
ОтветитьУдалитья не мог найти datasheete. значит 10000 раз да . спасибо
ОтветитьУдалитьЗдравствуйте. У меня программатор не прошивает больше 6 кб Ошибка выдают. программатор у меня Chip Blaster а чип Atmega8. Знаю что Atmega8 можно писать программу до 8 кб , а у меня hex файл 7 кб.
ОтветитьУдалитьЧто делать помогите пожалуйста.
hex - это прошивка в текстовом формате, реально она весит, помойму, меньше 1кб. Я думаю, что у вас какие то проблемы с тактированием, ну или с питанием
ОтветитьУдалитьЗдравствуйте.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 мс
}
Правильно ли это?Работает нормально,но иногда замечается нечеткое срабатывание.Я еще бью на пульт,надо покупать заводской...
установите задержку внутрь цикла if (rc5.dataOK), тогда срабатывание будет четким
ОтветитьУдалитьТак я ставил ее в конце цикла if (rc5.dataOK)после последнего rc5.dataOK = 0 - было еще хуже.Может в начале цикла поставить,первым после скобки.
ОтветитьУдалитькогда задержка стоит в цикле while(1), то наличие принятой команды проверяется каждые 700мс, есл иперенести эту задержку в if (rc5.dataOK) (в конец), то наличие принятой команды будет производиться постоянно и когда она появится, то сначала будет выполнение нужных функций, затем, через 700мс девайс будет опять реагировать на комманду с пду
ОтветитьУдалитьа, бля, 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; // сбрасываем флаг
}
}
Я понял Вас конечно.Но я изначально так и сделал с задержкой,при этом при нечетком нажатии светодиод вспыхивал и потухал.Возможно увеличить задержку до 1сек.
ОтветитьУдалитьТа и пульт может давать погрешности,нужен заводской,хотя я делал его для аудиоусилителя - работал отлично.
Ой извените я неувидел предпоследнее сообщение.
ОтветитьУдалитьДа Вы были правы,перепрошил все заработало.Да и флаг надо сбрасывать один раз в конце цикла.
ОтветитьУдалитьБольшое спасибо.
Добрый вечер Kibermaster.
ОтветитьУдалитьПодскажите,а как быть,если я хочу увеличить частоту МК Atmega8 до 8 МГц?
Я так думаю нужно перещитывать RC5_T в файле rc5.h.Но как понять:
// RC5_T нужно расчитать вручную (особенности компилятора)
#define RC5_T 1778 //((F_CPU/PRESCALER/1000)*1.778)
???
частоту поделить на пределитель таймера, поделить на 1000 и все это умножить на 1.778
ОтветитьУдалитьздравствуйте. как получить сигнал от ИК приемника(38 КГц) его data подключен в PB0 у.
ОтветитьУдалитьне знаю как настроит таймеры .
помогите пожалуйста.
за ранние спасибо.
так в статье же все готовое есть
ОтветитьУдалитьЗдравствуйте! Не могли бы Вы привести пример этого кода для CAVR - никак не получается портировать самостоятельно(((((
ОтветитьУдалитьсорри, но я в нем никогда не писал, но на 90% уверен, что код будет тот же
ОтветитьУдалитьздравствуйте. я собрал USB-HID устройство (прошивка под 12МГц внешний кварц).
ОтветитьУдалитьа вашей случей прошивка под 1МГц можно сделать 12МГц.(проверил не роботала )
она будет работать?
мой USB-HID устройство я хотел посмотреть команды пульта.
свой USB-HID устройство не работает 1МГц.
что делать помогите пожалуйста.
в rc5.h сверху 2 макроса, которые надо под свою частоту пересчитать
ОтветитьУдалитья не знаю как будет частоту 12МГц.
ОтветитьУдалитьнапишите пожалуйста.
напишите пожалуйста что меня и значения .
ОтветитьУдалить#define RC5_T 2667
ОтветитьУдалитьа в функции Rc5_SetRx нужно установить делитель на 8:
TCCR1B= _BV(CS11)|_BV(ICNC1);
спасибо вам большое что вы помогайте мне.
ОтветитьУдалитьвсё работает.
Вы очень добрый человек.
как вы расшитовали эта #define RC5_T 2667 ?
меня тоже научите пожалуйста.
за ранние спасибо.
я хотел управлять часы с помощью пулта.
ОтветитьУдалитья не знаю как будет частоту 32768 Гц. (часовой кварц )
научите пожалуйста.
напротив этого макроса есть формула, по которой можно посчитать.
ОтветитьУдалитьспасибо я всё понял значения PRESCALER=8
ОтветитьУдалитьдобрый день, hex в архиве работает, как только я закомпиливаю код в атмел студио 6 работать перестаёт хоть и компилит без ошибок. в чём может быть проблема? я вообще с cvavr работал, может что не так делаю? создаю проект GCC C++ Executable Project потом с боку в solution explorer выбираю Atmegu8 добавляю файлы main.c rc5.c main.h rc5.h в проект и жму Buil All, соданный hex не работает :(
ОтветитьУдалитьлично у меня студия 5 и 6 как то криво работают. Я использую студию 4 и последний тулчейн
ОтветитьУдалитьда, инсталировал 4 версию и заработало. а может вы знаете что сделать чтобы на CVAVR заработало? компилмруя выдаёт 3 таких ошибки http://s21.postimg.org/ntrm55ul3/osybki.png
ОтветитьУдалитьошибки, во первый, из-за того, что обработчики прерывания в CVAVR пишутся не так, как в WinAVR, а во вторых, из-за того, что в этих компиляторах разные макросы для битовых операций, ну и main должен объявлять по-ином, что и указано в ошибках на вашем скрине.
ОтветитьУдалитьint main(void) замените на void main(void)
_BV(CS10) на (1<На счет прерываний - посмотрите в инете, как они должны объявляться в CVAVR.
вот что вычитал в нете, но не доходит как точно нужно переписать это ISR(TIMER1_CAPT_vect) ? :/
ОтветитьУдалитьв CodeVision:
interrupt [прерывание] void adc_isr(void)
{ }
#include
ISR(прерывание_vect)
{ }
В примерах слово "прерывание" нужно заменить на название прерывания из ДатаШита либо из заголовочного файла *.h для используемого МК.
Попробуйте что то типа
ОтветитьУдалитьinterrupt [TIM1_ICMP] void timer1_icmp_isr(void)
ещё больше ошибок стало :D
ОтветитьУдалитьисправил все пред идущие ошибки появилась одна последняя http://s24.postimg.org/4n4eitqgl/posledniaja.png в чём тут может быть проблема?
ОтветитьУдалитьзамените структуру на:
ОтветитьУдалить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;
всё равно тоже самое, не понимаю что за фигня, компилирует без ошибок, а Buil All при создании hex кидает эту ошибку. пробовал вообще удалять куски кода и вообще всё оставляя тот rc5.h и всё равно та ошибка
ОтветитьУдалитьПодтверждаю наблюдение sergejus'a - под AVR Studio 6.1 компилится, но не работает. Буду пробовать под 4-ой...
ОтветитьУдалитьУважаемый Kibermaster, возник следующий вопрос: в доке по rc5 сказано, что часть команд (напр. громкость) передается в виде строки. Правильно ли я понял? И поддерживает ли Ваш код возврат значения этого типа?
ОтветитьУдалитьне строки, а набора импульсов. Фактически, там просто 3 байта
ОтветитьУдалитьМужики. не работает. компилится. но кнопки на пульте жму - не работает.
ОтветитьУдалитькомпилил и под 6.1 авр студио и под 4й. результат один.
у меня вместо 8й меги стоит 32я. порты в функции мейн поменял под свои. мб что менять надо еще в коде?
и ик-приемник стоит 536aa3p. работоспособность проверена.
в чем может быть дело?
если приемник подключили правильно (распиновка не как у TSOP1736)? то советую перекомпилировать в 4 студии
ОтветитьУдалитьприемник подключен правильно проверял его. подключал к int0. работает.
ОтветитьУдалитьв 4й студии компилил результат тот же.
а может дело в пульте? я от телека беру самсунга. aa59-00581a
такой
http://www.displayland.ru/images/pdu/AA59-00581A.jpg
мож он сигналы какие не те посылает?
от самсунга не подойдет, так как там кодировка другая
ОтветитьУдалитьОй. получилось. сначала купил пульт горизонт rc-5 mini. не работало. потом заменил ик-приемник на sm3374. и все заработало) кстати компилил в атмел студио 6.1
ОтветитьУдалитьАвтор, спасибо за статью и подскажите что за чудеса творятся..
ОтветитьУдалитьГлавный код. Вот так не работает (Ваш код):
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.
Спасибо.
И еще вопрос. Можно каким-то чудом сделать это всё на кварце 16 мгц? Может как-то прескейлер настроить.. Пробовал, ничего не вышло.
ОтветитьУдалитьPS. Дефайны пересчитывал..
Получается так:
ОтветитьУдалитьПри нажатии кнопки на пду он отправляет комманду, мк ее принимает и обрабатывает, так как после кода обработки ничего нет, то он сразу же опять реагирует на комманду с пду (при зажатой кнопке она отправляется несколько раз в секунду). Вобщем, после обработки программы сделайте задержку 1 секунду.
в rc5.h переопределить дефайны.
ОтветитьУдалитьСпасибо заработало. Тогда не получилось. Всё так же сделал. Может та проблема повлияла.
ОтветитьУдалитьМожет кому понадобится:
настройки под 16мГц
в rc5.h :
#define RC5_T 111 //((F_CPU/PRESCALER/1000)*1.778) //хотя я думаю ничего страшного что получилось 111,125
в rc5.с
TCCR1B = _BV(CS12) | _BV(ICNC1); //Предделитель: 256
На делителе 1024 не получилось.
Здравствуйте, Kibermaster!
ОтветитьУдалитьКак правильно написать код, чтобы при нажатии на кнопку "1" пульта выполнялась первая программа (несколько комбинаций светодиодов), при нажатии на кнопку "2" - вторая программа...
а то у меня кучу ошибок выдает типа: ../main.c:33: error: lvalue required as left operand of assignment
а что вы написали?
ОтветитьУдалитьто есть?
ОтветитьУдалитья хочу написать программку для гирлянды
ОтветитьУдалитьвы писали, что у вас куча ошибок, откуда они взялись?
ОтветитьУдалитьПишите через reply, иначе буду удалять
не могу кирилицу выставить...
ОтветитьУдалитья только учусь и пытаюсь такой код написать:
#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; // ñáðàñûâàåì ôëàã
}
}
}
while(1)
ОтветитьУдалить{
if (rc5.dataOK) { // если получены данные с ПДУ
if (rc5.command==1) {
// программа по нажатию 1
}
else if (rc5.command==2) {
// программа по нажатию 2
}
}
}
спасибо, а саму программку и сброс флага где записать?
ОтветитьУдалитьПодскажите пожалуйста, как можно сократить запись задержки, чтобы не под каждой строкой ее писать?
ОтветитьУдалить#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; // ñáðàñûâàåì ôëàã
}
}
и последнее.
ОтветитьУдалитьУ меня выдает ошибку, но не пойму чего от меня надо:
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...
через функцию или define
ОтветитьУдалитьдумаю, что проблемы с кодировкой. Установите ANSI
ОтветитьУдалитьа где поменять кодировку?
ОтветитьУдалитьне могу ее найти...
Наверно, где то в настройках редактора. Но у меня всегда изначально была установлена кодировка ANSI, менять ее никогда не приходилось
ОтветитьУдалитьспасибо, буду еще искать
ОтветитьУдалитьНашел проблему!
ОтветитьУдалитьВ пути к папке проекта была папка с русским наименованием.
Как только перенес проект в корень диска - ошибки пропали.
Подскажите пожалуйста, почему так происходит?
ОтветитьУдалитьЯ увеличиваю размер программы, соответственно вижу, что увеличивается объем файлов: main.c, Makefil, а после компиляции файл rc5.hex остается с прежним весом.
это сложно сказать. Makefile практически не влияет на размер (кроме некоторых опций), но в этом проекте он не используется (генерируется автоматом). А hex меняется, но не значительно. напишите в коде volatile int ttt[1000] и увидите, как увеличится hex
ОтветитьУдалитьПробовал установить volatile int ttt[1000] в разных участках кода, но на размер hex это не повлияло.
ОтветитьУдалитьК стати, а что за файл .elf ? Он тоже не меняет свой размер.
А файлы rc5.cci и rc5.hci вообще у меня не формируются.
об elf почитайте в инете. А в проекте есть еще какие то hex файлы?
ОтветитьУдалитьв проекте нет
ОтветитьУдалитьсегодня постараюсь проверить на работоспособность программку.
ОтветитьУдалитьдля code vizion avr,как этот код переделать?
ОтветитьУдалитьхз, я с ним не работал
ОтветитьУдалитьа вы в каком компилировали?
ОтветитьУдалитьAVR Studio 4 в связке с тулчейном
ОтветитьУдалитьа еще не подскажите avr studio выдает такую ошибку,,make: Makefile: No such file or directory,в чем может быть дело?
ОтветитьУдалитьвозможно, в пути находятся не латинские символы.
ОтветитьУдалитьПишите через Reply, иначе буду удалять.
подскажитьте пожалуйста avr studio дает такую ошибку,код копирую
ОтветитьУдалитьвот что пишет ../priem.c:1:17: fatal error: rc5.h: No such file or directory
ОтветитьУдалитьвозможно, в пути есть не латинские символы. Пишите через REply, иначе буду удалять
ОтветитьУдалитьв вашей программе,
ОтветитьУдалитькак понять в пути не латинские символы?
ОтветитьУдалитьпо какому пути лежит папка с проектом?
ОтветитьУдалитьпапка с проектом лежит в локальном диске D ,AVR STUDIO4? а куда лучше положить?
ОтветитьУдалитьСкиньте архив с проектом.
ОтветитьУдалитьНа счет reply - последнее предупреждение, далее добавляю в блэклист
я через него и пишу
ОтветитьУдалитьhttps://mail.yandex.ru/neo2/#disk/disk/ вот здесь архив посмотрите что там может быть не так
ОтветитьУдалитьпрограмирую hex файлом тоже от микроконтролера молчание
ОтветитьУдалитьпрограмирую hex файлом микроконтролер малчит
ОтветитьУдалитьдайте хотя бы какие то файлы с вашим проектом. Я не экстрасенс.
ОтветитьУдалитьhttps://mail.yandex.ru/neo2/#disk/disk/ вот здесь лежат файлы
ОтветитьУдалитьмне нужны файлы, а не ссылка на яндекс диск
ОтветитьУдалитьа как их отправить?
ОтветитьУдалить[code]http://speedy.sh/UBbeV/makros.rar[/code]
ОтветитьУдалитькибермастер,как вам отправить файлы,тут только по ссылке
ОтветитьУдалитьДобрый вечер.Вот бьюсь над одной проблемой,есть код,который включает/выключает канал 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) ;//ждем отпускания кнопки
Результат нулевой,канал вкл/выкл.
Я начинающий прошу не судить строго если чего не так.
сделайте задержку не 700 мс, а, к примеру, 1500
ОтветитьУдалитькибермастер объясните мне пожалуйсто почему у меня авр студии все проекты компилируются ,а вот именно этот нет,что я не так делаю? хекс файл на отладочной плате работает,в чем может быть причина?
ОтветитьУдалитькакие ошибки показывает?
ОтветитьУдалитьне существующая деректива "rc-5" и main.h
ОтветитьУдалить../c.c:3:17: fatal error: rc5.h: No such file or directory
ОтветитьУдалитьвыше 2 человека задавали этот вопрос
ОтветитьУдалитьа толчейн он туда же устанавливается,просто у меня все на диске d папок с русским названием нигде нет,а ошибка все равно вылазиит,у вас какая авр студия?
ОтветитьУдалитьтулчейн последний. Попробуйте добавить в опции коомпилятора __PROG_TYPES_COMPAT__
ОтветитьУдалитьнет не идет,незнаю что ей надо,все программы компилирует а эту не хочет.
ОтветитьУдалитьКибермастер как вот это по другому прописать? #include "rc5.h"
ОтветитьУдалить#include "main.h" и sbi.
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
Получается целое число,и главное работает в "метале" - проверенно.
Kibermaster, я читал полностью все комментарии, но вопросов все же есть. Вы говорите что пульт передает цифру в посылке команды, а как сделать чтоб реагировал не на цифровые клавиши а на другие к примеру ON/OFF MUTE и т.д. У меня есть сомнение, привожу пример. Есть пульт первый от телевизора и второй тоже от другого телевизора, если скажем что оба пульта работают на устройстве при нажатии клавиш, значит МК думает что принимает один и тот же сигнал с обоих пульта, но в реальности эти сигналы не одинаковы же, потому что первый телевизор не принимает сигнал от второго. Объясните пожалуйста.
ОтветитьУдалитьНа счет кнопок MUTE и т.д., они тоже передают числовое значение (до 127 по-моему).
ОтветитьУдалитьЕсли поставить 2 одинаковых телевизора, у которых будут одинаковые пульты (с одинаковыми кодировками), то при нажатии кнопки на 1 пульте будут реагировать оба телевизора.
Про телевизоры Вы не поняли наверное, но я только что читал про работу rc5 из других материалов. Пульт передает 14 бит, 2 бита стартовые 3-и дежурный и дальше 5 битов определены стандартом для разных устройств (тв, магнитофон и тд), а вот последние 6 бит отвечают за кнопки. Теперь я так думаю что, при приеме сигналов с разных пультов из разных устройств 5 бит могут быть разными, но последние 6 бит у всех одинаковы, я правильно понял?
ОтветитьУдалитьи еще, как привязать код только к одному пульту. чтоб другие пульты не реагировали.
ОтветитьУдалитьвозможно.
ОтветитьУдалитьв структуре rc5 есть system и command, первый отвечает за тип команды (для телика, проигрывателя и т.д.)
ОтветитьУдалитьОдин пользователь написал в комментариях что хочет портировать из AVR studio в CodeVision, у него получился? Я тоже хочу перевести, мой проект уже написан на нем, теперь хочу добавить ИК прием.
ОтветитьУдалитьэто к нему вопрос)))))
ОтветитьУдалитькибермастер подскажите как в этой программе зделать что бы при нажатии кнопки 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); // Выключаем светодиод
}
}
Ссылка на файлы не работает.
ОтветитьУдалитьИсправил
ОтветитьУдалитьдень добрый. какую функцию выполняет 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); ...
Можно включать по отдельности.
ОтветитьУдалитьCheckBit(reg, b) - проверить бит регистра.
sbi - установить бит регистра.
cbi - сбросить бит регистра.
Здравствуйте, Кибермастер! Подскажите, пожалуйста, как реализовать следующий эффект. При нажатии кнопки 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;
}
}
}
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
Здорово! Получилось! А то я уже все операторы цикла перебрал с различными условиями и результат = 0.
ОтветитьУдалитьА возможно ли после того как кнопкой power я потушил гирлянду, повторным нажатием на power включить гирлянду с того же case, на котором она была выключена?
Сделайте переменную, в которую будет записываться последний кейс, после включения перед switch устанавливайте значение этой переменной в rc5.command
ОтветитьУдалитьСпасибо, сейчас поэкспериментирую.
ОтветитьУдалитьПодскажите, а какой оператор присваивания применить к переменной, чтобы записывалось значение последнего кейса?
ОтветитьУдалить=. Вопрос сильно ламерский.
ОтветитьУдалитья имел в виду, как указать, что это именно последний кейс, который работал до выключения
ОтветитьУдалитьпросто указать i=case;
ОтветитьУдалитьпри входе в каждый кейс перед while записывайте в нужную переменную значение с rc5.command
ОтветитьУдалитьЗдравствуйте, 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;
}
Тоесть, вам нужно сохранять последнее состояние даже после того, как будет полностью отключено питание микроконтроллера?
ОтветитьУдалитьДа, верно. Поэтому я и решил использовать EEPROM. Но, что-то не так. Смотрел различные ролики, пытался повторить, но видимо что-то упустил.
ОтветитьУдалить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;
// и т.д.
}
}
}
Спасибо, сейчас буду испытывать.
ОтветитьУдалитьЕсть ошибка 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
Kibermaster, прости... не хватает моих скудных знаний.
ОтветитьУдалитьКуда я только не пытался уже поставить эти строки кода:
int lastCommand = 1; // последняя полученая комманда. Счиитываем её с eeprom
int state = 0; // состояние
ругательства сплошные. То case1 включается при нажатии на POWER, то вообще не реагирует. При этом ошибок не выдает.
Помоги пожалуйста.
Добрый день, 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;
}
можно ли эту прошивку с некоторыми переделками закинуть на atmega 16a ножки и всё остальное вроде подходят?
ОтветитьУдалитьМожно. По сути, просто перекомпилируй под мегу16. Подключение к тем же пинам.
ОтветитьУдалитьещё вопрос,это можно сразу в atmel studio перекомпилировать или код нужно менять?
ОтветитьУдалитьнет разницы какой ик-приёмник использовать?у меня TL1838 VS1838B 38 кГц
ОтветитьУдалитьпросто перекомпилировать.
ОтветитьУдалитьподойдет
ОтветитьУдалитьРесет обязательно подтягивать к +. А то что-то не хочет работать. Прошил хексом из папки дебаг.
ОтветитьУдалитьНе обязательно, но очень желаетльно
ОтветитьУдалить