|
Прием данных на Атмеге, Как правильно это организовать |
|
|
|
Nov 19 2008, 09:26
|
Частый гость
 
Группа: Участник
Сообщений: 145
Регистрация: 11-01-08
Пользователь №: 34 001

|
Здрастье, есть у меня такая проблема. Атмега, и приемник на 433Мгц ну от сигналки. Вот на ножку чипа приходит сигнал с приемника. Подскажите как выглядеть будет программа что бы просто записать принятые данные в виде единиц и нулей. Пакет приходит так: " Вся передача опирается на элемнтарный отрезок времени названный Те и равный обычно 400мкс. (документацией нормирован разброс от 280мкс до 620мкс). Итак передаваемый пакет: Он состоит из преамбулы (длиться 23Те, и нужна для того, чтоб оторвать приемник сиги от сладостного прослушивания помех), за ней следует заголовок пакета (header) – равен 10Те, и нужен для того чтоб проц в сиге смог определить длительность Те у принимаемого пакета данных… Затем идут собственно данные (66 бит или 198Те), и наконец Guard Time – время для того чтобы сига переварила принятое (39Те). Теперь о передаче данных.. бит передается за время равное 3Те.. В течении 1-го Те передается обязательно высокий уровень (красная часть), 2-е Те это собственно значение передаваемого бита (только инвертированное, те лог1 = низкий уровень, а лог0 соответственно = высокий уровень) – синяя часть.. И наконец в течении 3-го Те передается обязательный низкий уровень (зеленая часть).. " ВОТ! хочется попроще и оптимальный прием пакета
Эскизы прикрепленных изображений
|
|
|
|
|
Nov 19 2008, 09:56
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Vny4ek @ Nov 19 2008, 13:26)  Здрастье, есть у меня такая проблема... Проблема у Вас какая - не хочется программировать? Есть два варианта: 1. легкий : подсказываю - можно обнаружить начало передачи по тайм-ауту, использовать таймер в режиме захвата, записать все интервалы переходов в массив и их спокойненько обработать после приема посылки. 2. жесткий: вообще-то у меня и исходники есть, на которые я потратил некоторое время...
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Nov 19 2008, 11:03
|
Местный
  
Группа: Свой
Сообщений: 342
Регистрация: 21-06-04
Пользователь №: 85

|
Идея такая. Настраиваешь вход с радиоканала на прерывание по перепаду, неважно с нуля в единицу или наоборот. Настраиваешь таймер, лучше 16 битный, чтобы он постоянно по циклу считал. При изменении уровня на линии проц попадает в прерывание PCINT. Первым делом считываешь показание таймера, а сам таймер обнуляешь. Конечно в первом перепаде показания таймера от балды. Но вот во втором, ты уже попадешь в PCINT и таймер покажет длину импульса. Все есть длина импульса, осталось проверить наш это импульс или нет, т.е. ширина импульса скажем больше 0.5Te и меньше 1.5Te. Ведь преамбула с определенной частотойю, ширина импульса Te, верно? Далее если скажем есть 10 попаданий в размеры преамбулы, проц принимает решение, что идет преамбула. Все устанавливаем флаг, я в преамбуле. Далее, если слишком большая пауза, проц определяет срыв преамбулы, сбрасывается флаг преамбулы, проц опять в ожидании пакета. Если с преамбулой все ОК, проц ждет заголовок пакета. Как я понял заголовок пакета это пауза 10 Te. Т.е. при очередном PCINT в таймере лежит значение 10 Te. Проверяем что это значение в пределах 9Te и 11Te. Если да, значит пришел заголовок. Проц сбрасывает флаг преамбулы и устанавливает флаг приема данных. Теперь попадая в прерывание PCINT проц будет по этому флагу знать, что может быть длина импульса Te, а может быть 2Te, ведь это режим приема данных. Ну и все, теперь осталось проверять какая длительность после перепада из 0 в 1. Если =2Te значит пришел бит "0", если = Te пришел бит "1". Конечно после "0" будет перепад из 1 в 0 = Te, а после "1" перепад из 1 в 0 = 2Te, их проверяем и пропускаем, ждем перепада из 0 в 1. Если же очередная длительность больше 3Te, или меньше 0.5Te значит это помеха или срыв пакета, проц уходит опять на начало, в ожидание новой преамбулы нового пакета. Единственное замечание, без цифрового осциллографа это будет очень трудно сделать. Исходников не жалко, но там совсем другой протокол, скорее запутает. Начинай писать прямо свое по вышеописанному алгоритму. Сработает точно.
|
|
|
|
|
Apr 29 2009, 14:59
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Vny4ek @ Apr 29 2009, 16:39)  to:xemul да я видел апноут, причем принять пакет с ним у меня успешно получается, но там не считается насколько мне известно точно время одного TE, а мне это важно т.к. он может отличаться, да и опять же цель самому (пусть и кривовато) разобраться и научиться. Считается. Te = Th/10. Цитата И что значит не углублятся в прерывания? Можно ли мою задачу решить без использования таковых? ну например используя оператор if (PINA.0==1) {запуск отсчета счтиающего длительность импульса} или я не прав? без прерываний тут не обойтись? Достаточно прерывания от 8-битного таймера. Для ловли хидера настраиваете таймер на интервал TE_MIN/2, ждете -\____/ -, удовлетворяющий допускам на Th (по каждому прерыванию таймера if(!PINA.0) Th += TE_MIN/2; else Th = 0;), вычисляете Te. Дальше можно по аппноту, но лучше переложить аппнот на использование прерываний.
|
|
|
|
|
May 4 2009, 04:57
|
Частый гость
 
Группа: Участник
Сообщений: 145
Регистрация: 11-01-08
Пользователь №: 34 001

|
Вот привожу пример кода, для приема. Насколько мне известно тут длительность задана а не измеряется. CODE #include <mega8.h> #include <stdio.h> #include <delay.h> #include <String.h>
#define TRFreset 0 #define TRFSYNC 1 #define TRFUNO 2 #define TRFZERO 3
#define NBIT 65
#define HIGH_TO -10 #define LOW_TO 10 #define SHORT_HEAD 20 #define LONG_HEAD 45
#define RfIn PIND.4
typedef unsigned char byte;
bit RFFull; bit RFBit; int RFcount; byte Bptr,BitCount,RFstate,Buf[9]; /////////////// receive ///////////////////////////////// interrupt [TIM0_OVF] void timer0_ovf_isr(void) { TCNT0=135; RFBit=RfIn;
if (RFFull) return; ///////////////////////////////////////////////////////// switch(RFstate) { case TRFUNO: if ( RFBit == 0) { RFstate= TRFZERO; } else { RFcount--; if (RFcount < HIGH_TO) RFstate = TRFreset; } break; ////////////////////////////////////////////////////////// case TRFZERO: if (RFBit) { RFstate= TRFUNO; Buf[Bptr] >>= 1; if ( RFcount >= 0) { Buf[Bptr]+=0x80; } RFcount = 0; if ((++BitCount & 7) == 0) Bptr++; if (BitCount == NBIT) { printf("Reseive signal:"); printf("%02X%02X%02X%02X%02X%02X%02X%02X", Buf[0],Buf[1],Buf[2],Buf[3],Buf[4],Buf[5],Buf[6],Buf[7]); printf("\n\r"); RFstate = TRFreset; RFFull = 1; } } else { RFcount++; if ( RFcount >= LOW_TO) { RFstate = TRFSYNC; Bptr = 0; BitCount = 0; } } break; /////////////////////////////////////////////////////////// case TRFSYNC: if ( RFBit) { if ((RFcount < SHORT_HEAD)||(RFcount >= LONG_HEAD)) { RFstate = TRFreset;break; } else { RFcount =0;RFstate= TRFUNO; } } else { RFcount++; } break; ///////////////////////////////////////////////////////////// case TRFreset: default: RFstate = TRFSYNC; RFcount = 0; Bptr = 0; BitCount = 0; break; } // switch ////////////////////////////////////////////////////////////// if(RFFull) { RFstate = TRFreset; RFFull=0; } ///////////////////////////////////////////////////////////// } // receive ////////////////// main //////////////////////////////////// void main(void) { PORTD=0x10; DDRD=0x00;
TCCR0=0x02; TCNT0=0x00;
TIMSK=0x01;
UCSRA=0x00; UCSRB=0x08; UCSRC=0x86; UBRRH=0x00; UBRRL=0x33;
//////////////////////////////////////////////////////////// printf(" WAIT SIGNAL!\n\r"); printf("\n\r"); //////////////////////////////////////////////////////////// #asm("sei") }// main
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
|
May 4 2009, 09:05
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Vny4ek @ May 4 2009, 07:57)  Вот привожу пример кода, для приема. Насколько мне известно тут длительность задана а не измеряется. Осталось вот это: Цитата(rezident) Вы предоставляете свой исходник с комментариями "непоняток". А вообще-то Вам описали алгоритм, и Вы ответили: "я потихоньку начинаю понимать, давайте я начну делать а если Вам не сложно вы поправите и скажете где ошибся" Что же Вы действительно САМИ начали делать, кроме выкладывания чужих исходников?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
May 4 2009, 10:13
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Vny4ek @ May 4 2009, 13:02)  не понятно мне следующее: как отследить изменение уровня, и по этому событию запустить таймер, далее его остановить при переходе уровня из 1 в 0 Я опять процитирую уважаемого rezidentа: "Таймер не нужно запускать по перепаду. Таймер должен всегда работать с (авто)переполнением. Перепад на входе фиксируется в регистре захвата (capture). Беззнаковая разность двух соседних значений, полученных из регистра захвата, дает длительность между фронтами в тактах таймера..." Вот пример запуска постоянно работающего таймера в ATmega32: Код void BackgroundInit() { TCCR0=0; //stop TC0 TCCR0 = 1 << WGM01; // ClearTimertoCompare mode, TC0 top on OCR0 TCNT0 = 0x01; // initial value TC0 OCR0 = 249; // TOP 250 kHz/(249+1)=1 kHz TIMSK = TIMSK & ~(1 << TOIE0) | (1 << OCIE0); TIFR |= (1 << OCF0) | (1 << TOV0); } Добавьте инициализацию схем захвата.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 7 2009, 14:09
|
Частый гость
 
Группа: Участник
Сообщений: 145
Регистрация: 11-01-08
Пользователь №: 34 001

|
Здраствуйте, я разбираюсь с одним кодом, задача такая: Получить код от приемника в формате кейлог, и по событию отправить его же (отправка кода происходит при полностью полученном коде), дальше хочу научиться записывать в ячейки полученные коды, для сравнения, но пока передача не проходит, смотрю осцилографом, а передаются только нули (вижу по однотипным импульсам в теле пакета) подскажите в чем дело? CODE #include <mega8.h> //#include <my_lcd.c> #include <stdio.h> #include <delay.h> #include <String.h>
#define TRFreset 0 #define TRFSYNC 1 #define TRFUNO 2 #define TRFZERO 3
#define NBIT 65 #define TE 400 #define HIGH_TO -10 #define LOW_TO 10 #define SHORT_HEAD 20 #define LONG_HEAD 45 #define RFOut PORTC.7 #define RfIn PINB.0 #define Btn PINB.2 typedef unsigned char byte; typedef signed int sbyte; typedef signed long word; #pragma warn- //директива для инициаизации еепрома eeprom byte EprBuf0 [65]; eeprom byte EprBuf1 [65]; eeprom byte EprBuf2 [65];
eeprom byte eep_ring; #pragma warn+ //директива для инициаизации еепрома
byte i; bit RFFull; bit RFBit; int RFcount; byte Bptr,BitCount,RFstate,Buf[9];
void Transmit(byte*b,byte u) { byte g=0,j=0,counts; { for(;u>0;u--) counts = b[9]; for (i = 0; i < 12; i ++) //преамбула { RFOut = 1; delay_us(TE); RFOut = 0; delay_us(TE); } delay_ms(4); // хедер for (i=0;i<8;i++) // цыкл вывода байтов { g = b[i]; // считаем буфер for (j=0;j<8;j++) // цикл вывода битов в байте { RFOut = 1; // вывод бита delay_us(TE); if (g&1) RFOut = 0; delay_us(TE); RFOut = 0; delay_us(TE); g >>= 1; } }
delay_ms(10); // гуард тайм } //end for u } //end Transmi
/////////////// receive ///////////////////////////////// interrupt [TIM0_OVF] void timer0_ovf_isr(void) { TCNT0=135; RFBit=RfIn;
if (RFFull) return; ///////////////////////////////////////////////////////// switch(RFstate) { case TRFUNO: if ( RFBit == 0) { RFstate= TRFZERO; } else { RFcount--; if (RFcount < HIGH_TO) RFstate = TRFreset; } break; ////////////////////////////////////////////////////////// case TRFZERO: if (RFBit) { RFstate= TRFUNO; Buf[Bptr] >>= 1; if ( RFcount >= 0) { Buf[Bptr]+=0x80; } RFcount = 0; if ((++BitCount & 7) == 0) Bptr++; if (BitCount == NBIT) { printf("Reseive signal:"); printf("%02X%02X%02X%02X%02X%02X%02X%02X", Buf[0],Buf[1],Buf[2],Buf[3],Buf[4],Buf[5],Buf[6],Buf[7]); printf("\n\r"); Transmit(Buf,1); RFstate = TRFreset; RFFull = 1; } } else { RFcount++; if ( RFcount >= LOW_TO) { RFstate = TRFSYNC; Bptr = 0; BitCount = 0; } } break; /////////////////////////////////////////////////////////// case TRFSYNC: if ( RFBit) { if ((RFcount < SHORT_HEAD)||(RFcount >= LONG_HEAD)) { RFstate = TRFreset;break; } else { RFcount =0;RFstate= TRFUNO; } } else { RFcount++; } break; ///////////////////////////////////////////////////////////// case TRFreset: default: RFstate = TRFSYNC; RFcount = 0; Bptr = 0; BitCount = 0; break; } // switch ////////////////////////////////////////////////////////////// if(RFFull) { RFstate = TRFreset; RFFull=0; } ///////////////////////////////////////////////////////////// } // receive ////////////////// main ////////////////////////////////////
void main(void) {
PORTD=0x10; DDRD=0x00; PORTB=0x00; DDRB=0x00; PORTC=0x7F; DDRC=0xFF; TCCR0=0x02; TCNT0=0x00;
TIMSK=0x01;
UCSRA=0x00; UCSRB=0x08; UCSRC=0x86; UBRRH=0x00; UBRRL=0x33;
//////////////////////////////////////////////////////////// printf(" WAIT SIGNAL!\n\r"); printf("\n\r"); //////////////////////////////////////////////////////////// #asm("sei") }// main
Причина редактирования: [codebox], хотя нужно использовать приложения
|
|
|
|
|
Jun 8 2009, 09:03
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
1. В main нет зацикливания в конце 2. printf в обработчик прерывания не ставят 3. Передачу с задержками внутри тоже не рекомендуется ставить в обработчик прерывания 4. Непонятно предназначение конструкции for(;u>0;u--) counts = b[9]; в начале функции передачи 5. SM в прерывании не смотрел - на первый взгляд нечто монстрообразное (хоть бы коментарии написал  )
|
|
|
|
|
Jun 8 2009, 09:14
|
Частый гость
 
Группа: Участник
Сообщений: 145
Регистрация: 11-01-08
Пользователь №: 34 001

|
да я взял уже работающий пример, прием работает корректно, в УАРТ выводит коды, но вот по сути после того как принят последний бит, должна сразу стартовать передача, это происходит, но передаются нули. Я думаю может нужно, принятое в какойнибудь временный буфер присваивать, а уже от туда отправлять? Или действительно может дело в пункте 3. Я если честно до сих пор не понял доконца некоторых элементов этого кода, содраны с официальных аппноутов вроде.
|
|
|
|
|
Jun 28 2009, 15:34
|
Частый гость
 
Группа: Участник
Сообщений: 145
Регистрация: 11-01-08
Пользователь №: 34 001

|
Здравствуйте, подскажите плиз. Вообщем я пытаюсь принять сигнал с приемника, ну там есть элементы логическое 1=400мкс а 0=800мкс, ну хочу данные принять и пакет еще приходит с преамбулой (12шт логических 1 затем пауза 4милисекунд) мне важно что бы знать в какой фазе сейчас прием. Я покажу элемент кода, откоментируйти плиз что я не так делаю Код while (1) { if (PINA.0==0) { i=0; s=0; }; for (i=0;PINA.0==1;i++) { delay_us(1); s=i; }; printf("Dlitelnost ____|---|____="); printf("%u",s); printf("\n\r");
}; Подаю в протеусе сигнал где первый импульс, как и последующие имеет длинну около 400-800мкс, но в уарт выводятся значения произвольные от 1до 100, что я делаю не так? Если запускаю генератор достаточно медленный на 50милисекунд например он показывает длинну, а вот реальный пакет отправляю через audio генератор, не хочет. знаю что правильно организовать прием по перрыванию, но пока освоить не могу, их хорошо.
|
|
|
|
|
Jun 29 2009, 18:17
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Блин. Во что лень делает.... Первый пост ноябрь 2008, на дворе конец июня 2009. 7 месяцев!!!!!! 1) Возьмите себя в руки (максимум день). 2) Почитайте не примеры, а документацию на выбранный вами камень. (максимум 2 дня). 3) Перечитайте ответы спецов по данной теме. (пол дня) 3) Выкиньте чужое и напишите своё. Но чтобы вы понимали что там написано. (Максимум неделя)
|
|
|
|
|
Jun 30 2009, 05:49
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581

|
Простите что вмешиваюсь, но возникла похожая проблема (надо удаленно помочь человеку победить протокол RF модуля). Модуль от радиосигнализации имеет один сигнальный провод. Никто его в "лицо" не узнает? Хотелось бы узнать, что у него на выходе, иначе буду делать сниффер...
Эскизы прикрепленных изображений
--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
|
|
|
|
|
Jul 27 2009, 05:41
|
Частый гость
 
Группа: Участник
Сообщений: 145
Регистрация: 11-01-08
Пользователь №: 34 001

|
Ребят вот я начал потихоньку тут понимать что происходит, в терминал при подаче пакета выводит значения таймера. Подскажите дальше как правильно обработать, думал вчера целый день не выходит  CODE #include <mega8.h> #include <stdio.h> unsigned long int i,; bit s=0; // External Interrupt 1 service routine interrupt [EXT_INT1] void ext_int1_isr(void) { // Place your code here // Place your code here
i = TCNT1; printf("I="); printf("%u",i); printf("\n\r"); }
// 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: 125,000 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x03; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;
// Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00;
// External Interrupt(s) initialization // INT0: Off // INT1: On // INT1 Mode: Falling Edge GICR|=0x80; MCUCR=0x08; GIFR=0x80;
// Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00;
// 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=0x33;
// Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00;
// Global enable interrupts #asm("sei")
while (1) { // Place your code here }; } Как кстати сделать что бы код в форуме не весь показывался а с прокруткой
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|