Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Atmega8 + timer1 неточный ( дешифровка rc5 сигнала )
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
miXOnIN
Здравствуйте.

Пытаюсь на базе atmega8 + кварц на 12MHz + tsop1736 сделать приёмник ИК диапазона от пультов ДУ.
Спустя сутки гугла сделал вроде-как рабочую программу, но есть огромная проблема, не пойму в чём дело.

И так, теоретическая часть:
Частота МК 12 000 000мгц, на таймере установлен делитель до 1 500 000мгц (1.5кк операций/сек как я понимаю)
В стандарте протокола написано, что длина одного бита 1.8ms, всего 14 битов
Тобишь, чтоб отсчитать 1.8ms ровно, при частоте 1 500 000 счётчик должен досчитать до: 1500000/1000*1.8=2700
Так в программе и сделал, счётчик установлен до 2700, после чего пишу бит, и обнуляю счётчик ожидая следующего бита, и так 14 бит
НО вот тут то и собака зарыта! Он вроде всё норм считает, но биты идут ДАЛЬШЕ 14го! (высчитал прерыванием) между первым и последним прирыванием счётчик успевает досчитать до 26-28, вот и главный вопрос - ПОЧЕМУ ТАК?
ошибка в таймере, слишком быстро считает? или частота резонатора кривая? (эти 2версии маловероятны, ибо я в ручную при ниже частоте отсчитывал и сравнивал кол-во цикла и прошедшего времени), но если он считает с норм скоростью, то почему тогда данные дальше принимаются? проверил 2 пульта ДУ, и там и там одно и то-же, тобишь вариант что это пульт нестандартный не с RC5 скорее всего отпадает

вот код на CVARV (тут + передача инфы с МК по rs232 через uart)

CODE
#include <mega8.h>
#include <stdio.h>

unsigned int bytes[14]={0,0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned int tmp=1;
unsigned int i=0;
unsigned int status=0;

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if(status==1)return;
status=1;
// #asm("cli")
bytes[0]=PIND.2;
TCCR1B=0x0A;
}



// Timer1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
if(tmp<14)bytes[tmp]=PIND.2;
tmp++;
if(tmp>=14){
TCCR1B=0x00; // вырубаем счётчик
TCNT1H=0x00; // сбрасываем часть 1
TCNT1L=0x00; // сбрасываем часть 2
tmp=1;
printf("!%u %u %u %u %u %u %u %u %u %u %u %u %u %u\r",bytes[0],bytes[0],bytes[1],bytes[2],bytes[3],bytes[4],bytes[5],
bytes[6],bytes[7],bytes[8],bytes[9],bytes[10],bytes[11],bytes[12],bytes[13]);
for(i=0;i<14;i++)bytes[i]=0;
status=0;
// #asm("sei")
}
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 1500,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00; // TCCR1B=0x0A; // 1 500 000Hz
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x0A; //1.8ms
OCR1AL=0x8C; //1.8ms
OCR1BH=0x00;
OCR1BL=0x00;


// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Any change
// INT1: Off
GICR|=0x40;
MCUCR=0x01;
GIFR=0x40;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x4D;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// SPI initialization
// SPI disabled
SPCR=0x00;

// TWI initialization
// TWI disabled
TWCR=0x00;

// Global enable interrupts
printf("sei\r");
#asm("sei")

/*
while (1)
{

}
*/
}


п.с. именно в этом примере что щас - этот баг виден в том - что таймер успевает натикать 14 раз, записать эти все биты, оповестить меня об этом, перезапустить всё и часть этого-же кода - запустит прерывание наново чего быть аж никак не должно
ILYAUL
Вот это читали?
miXOnIN
Цитата(ILYAUL @ Aug 31 2012, 19:09) *
Вот это читали?

именно это - нет, но ничего нового или полезного или хотя-бы не много помогающего понять в чём дело - я не увидел, к чему эта ссылка вообще?
Кроме этого хотябы даже косвенно относящегось к моему вопросу чего-либо там не было... с таким-же успехом можно было дать ссылку на вики по RC5


p.s. на данном форуме я новенький, хз, мб у вас так принято, даже не вникая в суть вопроса тыкать в доки в которых нет ничего похожего на ответ, но прошу тогда хотя-бы мне лично так не делать
stfrd
Я бы для начала убедился что пакет именно такой, какой должен быть. Повысьте частоту таймера минимум в 4 раза и снимите форму входного сигнала (сбросьте эти данные на комп по uart). Если формат пакета правильный, значит что-то с частотой тактирования таймера или всего микроконтроллера.
ARV
Цитата(ILYAUL @ Aug 31 2012, 20:09) *
Вот это читали?
а вот это? wink.gif я так и не могу понять, почему все так любят принимать ИК-команды прерываниями...


miXOnIN
Цитата(ARV @ Aug 31 2012, 20:48) *
а вот это? wink.gif я так и не могу понять, почему все так любят принимать ИК-команды прерываниями...

ибо это единственный точный метод измерения времени в МК
даже стандартный delay_ms подводить нереально, 500ms длится ~4х сек без резонатора, хорошее оправдание юзать что-то более точное для создания алгоритмов зависящих от десятитысячной доли секунды?

Цитата(stfrd @ Aug 31 2012, 20:23) *
Я бы для начала убедился что пакет именно такой, какой должен быть. Повысьте частоту таймера минимум в 4 раза и снимите форму входного сигнала (сбросьте эти данные на комп по uart). Если формат пакета правильный, значит что-то с частотой тактирования таймера или всего микроконтроллера.


В том-то и дело что я понятия не имею какой ИМЕННО должен быть весь пакет, ибо лишь два стартовые биты это 11 остальное рандом, к тому-же рандом опять-же с единицами...
_Артём_
Цитата(miXOnIN @ Aug 31 2012, 21:45) *
ибо это единственный точный метод измерения времени в МК

Вообще-то (уже давно - с x51), существует ещё более точный способ - захват по изменению состояния входа, далее возможно происходит прерывание или нет (если не нужно).

Цитата(miXOnIN @ Aug 31 2012, 21:45) *
даже стандартный delay_ms

Где он стандартный интересно? В CVAVR? Нашли стандарт...
А может там есть delay_us какай-нибудь?
Или что-то вроде __delay_cycles?

Цитата(miXOnIN @ Aug 31 2012, 21:45) *
delay_ms подводить нереально, 500ms длится ~4х сек без резонатора

Как это вам удаётся?
Настраиваите фузы на 4 МГц, проект на кварц 12 Мгц?

Цитата(miXOnIN @ Aug 31 2012, 21:45) *
В том-то и дело что я понятия не имею какой ИМЕННО должен быть весь пакет, ибо лишь два стартовые биты это 11 остальное рандом, к тому-же рандом опять-же с единицами...

Знакомая ситуация: как-то делали проект для работы с пультом RC-5.
Но потом выяснилось что пульт работает совсем не по RC-5 (так и не узнали что за протокол).
Вышли из ситуации примерно так: нажимали на кнопку, записывали какие длительности перепадов получаются, затем то же проделывали со всеми остальными кнопками.
В результате получили некую эталонную таблицу с которой можно сравнивать поступающий сигнал.
_Pasha
Цитата(_Артём_ @ Aug 31 2012, 23:07) *
Знакомая ситуация: как-то делали проект для работы с пультом RC-5.
Но потом выяснилось что пульт работает совсем не по RC-5 (так и не узнали что за протокол).

a14.gif этта пять, как говорят .
По сути: какая должна быть точность, если у меня на меге8 по прерыванию от TCNT2 на 64мкс в общем, поллинг и всё без сбоев. Код привезти? sm.gif Но РЦ5..
miXOnIN
Цитата(_Артём_ @ Aug 31 2012, 23:07) *
Как это вам удаётся?
Настраиваите фузы на 4 МГц, проект на кварц 12 Мгц?


хм, всё проще чем ты думаешь, идёшь в магаз, покупаешь чистый атмега8, приходишь домой, завариваешь себе чай, тем временем размещая мк на монтажной плате, потом открываешь cvavr, пишешь программу в 5-7 строчек, в основе которой инпортить либу делай, выставить на выход ноги, и могать в итоге лампочкой, при 500 моргает раз в 4-6 сек. о фъюзах или настройке частоты даже и речи не идёт,всё по дефолту...
miXOnIN
Сделал нечто вроде анализатора протокола, это явный бред.........

PIND.2 TCNT1H TCNT1L ch

ch - сколько полных кругов прошло
OCR1AH=0xFF;
OCR1AL=0xFF;
TCCR1B=0x09; // 12 000 000Hz

Это всё результаты на нажатие одной и той-же кнопки...

CODE
0 0 0 0
1 0 6f 0
1 0 21 0
1 b7 e2 0
1 6d 60 0
1 55 e1 0
1 3c 62 0
stop!
0 0 0 0
1 0 6f 0
1 0 21 0
1 b7 e2 0
0 6d 60 0
1 55 e0 0
1 3c 60 0
stop!
0 0 0 0
1 0 6f 0
1 0 21 0
1 b7 e2 0
1 6d 63 0
1 55 e1 0
1 3c 62 0
stop!
0 0 0 0
1 0 6f 0
1 0 24 0
1 b7 e2 0
0 6d 2b 1
1 7b e2 1
stop!
0 0 0 0
1 0 6f 0
1 0 24 0
1 b7 e2 0
0 6d 9b 1
1 6b e3 1
stop!
0 0 0 0
1 0 6f 0
0 0 6b 2
0 6 e2 2
1 6d a2 2
1 24 22 2
1 c a2 2
stop!
_Артём_
Цитата(_Pasha @ Sep 1 2012, 03:51) *
a14.gif этта пять, как говорят .

Вы таки думаете, что это был RC5? А чёрт его теперь знает...


Цитата(miXOnIN @ Sep 1 2012, 10:03) *
хм, всё проще чем ты думаешь, идёшь в магаз, покупаешь чистый атмега8, приходишь домой, завариваешь себе чай, тем временем размещая мк на монтажной плате, потом открываешь cvavr, пишешь программу в 5-7 строчек, в основе которой инпортить либу делай, выставить на выход ноги, и могать в итоге лампочкой, при 500 моргает раз в 4-6 сек. о фъюзах или настройке частоты даже и речи не идёт,всё по дефолту...

А какая частота осцилятора указывается в проекте?
ArtemKAD
Цитата
о фъюзах или настройке частоты даже и речи не идёт,всё по дефолту...

Насколько помню в М8 по дефолту идет 8МГц встроенный RC плюс делитель на 8. Т.е. тактовая ядра 1МГц. Если в проекте стоит 8 по умолчанию, вот оно в 8 раз медленнее и работает...

ЗЫ. Ладно, ошибся, в М8 делителя тактовой еще не было. Там просто переключался один из 4-х RC-генераторов и генератор по умолчанию был 1МГц.
ARV
зря, господа, вы тут мой метод раскритиковали... вам шашечки или ехать? мой метод отлично работает в нескольких моих проектах. именно на _delay_us(), именно на встроенном RC-генераторе. причем даже (о ужас!) при наличии фоновых задач, выполняемых по прерываниям, которые неизбежно искажают программные задержки.

например, лампа настроения на attiny13. даже и не знаю, впихнете ли вы свой алгоритм в 1К кода при наличии одного 8-битного таймера без аппаратного захвата... а мой алгоритм легко туда вошел sm.gif

так что если кому охота продолжать париться с точным измерением временнЫх интервалов - как говорится, попутного ветра в спину! а тем, кто хочет попроще и побыстрее сделать устройство, рекомендую мой алгоритм. если вы будете использовать кварц или для формирования задержек задействуете таймер - мой алгоритм станет работать только лучше, хотя и так хорошо sm.gif

кстати, я и для RC5 придумал примитивнейший алгоритм приема - работает, как ни странно, даже без кварца и с фоновыми прерываниями...
ArtemKAD
Цитата
например, лампа настроения на attiny13. даже и не знаю, впихнете ли вы свой алгоритм в 1К кода при наличии одного 8-битного таймера без аппаратного захвата...

В Т13 минимум два таймера (даже если не дергать WDT) - один просто таймер, а второй - таймер в АЦП. disco.gif
miXOnIN
Цитата(_Артём_ @ Sep 1 2012, 13:44) *
Вы таки думаете, что это был RC5? А чёрт его теперь знает...



А какая частота осцилятора указывается в проекте?

1мгц, по дефолту

Цитата(ArtemKAD @ Sep 1 2012, 14:09) *
Если в проекте стоит 8 по умолчанию, вот оно в 8 раз медленнее и работает...


я не дурак, указываю 1 при создании, через мастера создаю

+ если БЕЗ мастера создавать, тобишь с 0 весь код писать, там вовсе нет параметра как частота мк
ArtemKAD
Цитата
+ если БЕЗ мастера создавать, тобишь с 0 весь код писать, там вовсе нет параметра как частота мк


Если используешь нечто типа delay_ms, то указать частоту ОБЯЗАН. Почти наверняка это #define на основе __delay_cycles в котором через некий макрос (к примеру F_CPU) пересчитывает миллисекунды в такты. При этом F_CPU по умолчанию объявляется и если ее не объявить в проекте будет расчет тактов под частоту которую захотели разработчики макроса...

Что касается Вашей фразы "я не дурак, указываю 1 при создании, через мастера создаю" - это Вам не программа для винды. Бездумное использование макросов о которых Вы мало что знаете для программ работающих на МК,это прямой путь к ошибкам.
ARV
Цитата(ArtemKAD @ Sep 1 2012, 15:26) *
В Т13 минимум два таймера (даже если не дергать WDT) - один просто таймер, а второй - таймер в АЦП. disco.gif
вот за это изобилие периферии я и ценю attiny13 sm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.