adc 0 24 ноября, 2008 Опубликовано 24 ноября, 2008 · Жалоба Здравствуйте! Сразу хочу извинится за дублирование темы, но вопрос как мне кажется относится к двум веткам: к радиопередатчикам и программированию. Прошу помочь с вопросом программирования радиомодулей RFM12. Кто подключал и использовал, поделитесь инфой о "граблях". Бьюсь несколько дней, данные от модуля к модулю не передать. Запись в регистры проходит нормально (управляю тестовой частотой на CLK). Инициализацию делаю по документации на чип. Пытаюсь послать байт, приемник не принимает. Заранее спасибо за советы! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DiMomite 0 24 ноября, 2008 Опубликовано 24 ноября, 2008 · Жалоба Если подключал к AVR пользуясь примером от производителя, то там ошибка в инициализации, кажется, приемника. Ниже прикладываю проверенный пример работы взятый уже не помню где. rfm12b.zip rfm12b_and_avr__quick_start.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adc 0 25 ноября, 2008 Опубликовано 25 ноября, 2008 · Жалоба Если подключал к AVR пользуясь примером от производителя, то там ошибка в инициализации, кажется, приемника. Спасибо! Внимательно все изучаю. Если Вас не затруднит... вспомните точнее где ошибка. Перепробовал разные варианты инициализации.. все глухо.. -----> :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DiMomite 0 25 ноября, 2008 Опубликовано 25 ноября, 2008 · Жалоба В приложенной выше pdf-ке это место даже выделено на странице 4 во втором листинге writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC (bug was here) а в родном документе от hoperf (приложил к посту ниже) на странице 20 в инициализации приемника есть такая строчка RFXX_WRT_CMD(0x8239);//!er,!ebb,ET,ES,EX,!eb,!ew,DC , причем, в инициализации передатчика на странице 14 эта строчка такая же, что явно указывает на ошибку. В примере для PIC этой ошибки нет. Я ее обнаружил когда пример не заработал и начал проверять секцию инициализации модуля. Тот пример, что я привел выше, запустился на макете сразу без всяких проблем. Попробуй с ним. Если будут проблемы, то надо проверять железо. И еще. В примере от производителя используется программная реализация SPI. Проверял и с аппаратной в режиме mode0 (CPOL=0, CPHA=0). Частота должна быть не выше 10МГц(частота кварца на модуле)/4=2,5МГц. Я использовал 20/16=1,25МГц. RF12B_code.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adc 0 26 ноября, 2008 Опубликовано 26 ноября, 2008 · Жалоба Тот пример, что я привел выше, запустился на макете сразу без всяких проблем. Попробуй с ним. Если будут проблемы, то надо проверять железо. Большое СПАСИБО! Все заработало. :a14: Была путаница в инициализации и плюс к этому, не использовал выход IRQ. Понадеялся на временные паузы между посылками. В инициализации есть такая строчка: writeCmd(0xCED4); //SYNC=2DD4ЃG Непонятно, ведь такого регистра нет (CE)?! Модуль у меня был на 433МГц. Вот моя инициализация , может кому пригодится: ;приемник send_rf12 $80D7 send_rf12 $8299 send_rf12 $A640 send_rf12 $C647 send_rf12 $94a0 send_rf12 $C2AC send_rf12 $CA81 send_rf12 $Ced4 send_rf12 $C483 send_rf12 $9850 send_rf12 $CC17 send_rf12 $E000 send_rf12 $C800 send_rf12 $C040 ;передатчик send_rf12 $80D7 send_rf12 $8239 send_rf12 $a640 send_rf12 $c647 send_rf12 $94a0 send_rf12 $c2ac send_rf12 $ca81 send_rf12 $CED4 send_rf12 $C483 send_rf12 $9850 send_rf12 $CC17 send_rf12 $E000 send_rf12 $C800 send_rf12 $C040 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DiMomite 0 26 ноября, 2008 Опубликовано 26 ноября, 2008 · Жалоба В инициализации есть такая строчка: writeCmd(0xCED4); //SYNC=2DD4 Непонятно, ведь такого регистра нет (CE)?! Я так понял, что это "Synchron pattern Command" , описывается сразу после "FIFO and Reset Mode Command" . Командой writeCmd(0xCED4); задается, что в качестве нулевого байта будет использоваться 0xD4. Модуль может использовать в качестве синхронизирующей последовательности либо 1, либо 2 байта. Второй (Byte1) всегда равен 0x2D и включается битом sp в команде "FIFO and Reset Mode Command ", а первый (Byte0) можно задать самостоятельно как раз командой 0xCEхх. Сам я это не проверял, использую рекомендованное значение, так что прокомментировать не могу. И еще. Тут http://radio.delanet.ru/content/view/571/46/ можно скачать генераторы кода инициализации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 10 мая, 2009 Опубликовано 10 мая, 2009 · Жалоба Может мне кто поможет? Собрал два девайса MCU+RFM12BP, написал программу, конфигурации приемника/передатчика стянул отсюда но не работает. Не работает - это в смысле приемник не принимает (по RS232 приходят данные из "эфира" постоянно нули) Вот что сейчас есть: 1. Функции при работе непосредственно с RFM12BP #define RF12_IRQ PINB.4 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #define SCK 1 // SPI clock #define SDO PINB.3 // SPI Data output (RFM12B side) // приемник МЦУ #define SDI 2 // SPI Data input (RFM12B side) // передатчик МЦУ #define HI(x) PORTB |= (1<<(x)) #define LO(x) PORTB &= ~(1<<(x)) #define WAIT_NIRQ_LOW() while(PINB.4) delay_us(20) //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! uint8 RX_TX_STATE; // 0-ни в каком состоянии // 1-в состоянии приемника; // 2- в состоянии передатчика uint16 writeCmd(uint16 cmd) { uint8 i; uint16 recv; recv = 0; LO(SCK); for(i=0; i<16; i++) { if(cmd & 0x8000) { HI(SDI); } else { LO(SDI); } HI(SCK); recv<<=1; if(SDO) { recv|=0x0001; } LO(SCK); cmd<<=1; } return recv; } void RF12_RX_Init_() { writeCmd(0x80E7); //EL,EF,868band,12.0pF writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC writeCmd(0xA640); //freq select writeCmd(0xC647); //4.8kbps writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR writeCmd(0xCED4); //SYNC=2DD4; writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN writeCmd(0x9850); //!mp,90kHz,MAX OUT writeCmd(0xCC17); //!OB1,!OB0, LPX,!ddy,DDIT,BW0 writeCmd(0xE000); //NOT USE writeCmd(0xC800); //NOT USE writeCmd(0xC040); //1.66MHz,2.2V } void RF12_TX_Init_() { writeCmd(0x80E7); //EL,EF,868band,12.0pF writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC writeCmd(0xA640); //frequency select writeCmd(0xC647); //4.8kbps writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR writeCmd(0xCED4); //SYNC=2DD4ЃG writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN writeCmd(0x9850); //!mp,90kHz,MAX OUT writeCmd(0xCC17); //OB1ЃCOB0, LPX,ЃIddyЃCDDITЃCBW0 writeCmd(0xE000); //NOT USE writeCmd(0xC800); //NOT USE writeCmd(0xC040); //1.66MHz,2.2V } void FIFOReset_() { writeCmd(0xCA81); writeCmd(0xCA83); } void RF12_SEND_(uint8 DATA) { WAIT_NIRQ_LOW(); writeCmd(0xB800 + DATA); } uint8 RF12_RECV_(void) { uint16 data; WAIT_NIRQ_LOW(); writeCmd(0x0000); data = writeCmd(0xB000); return (data & 0x00FF); } 2. По RS232 я задаю кто будет приёмником а кто передатчиком. Вот краткий пример: #define RX_ON PORTB |= (1<<7) #define RX_OFF PORTB &= (uint8) ~(1<<7) #define TX_ON PORTB |= (1<<6) #define TX_OFF PORTB &= (uint8) ~(1<<6) ........................... case (7): { RX_TX_STATE=2; // Задаем состояние передатчика RX_OFF; TX_ON; RF12_TX_Init_(); } break; case (8): { RX_TX_STATE=1; // Задаем состояние приемника TX_OFF; RX_ON; RF12_RX_Init_(); } break; ......................... 3. ВОт что делаю в основном цикле main while (1) { if(RX_TX_STATE==2) { // Если в состоянии передатчика //RF12_SEND(0xAD); writeCmd(0x0000); RF12_SEND_(0xAA); // PREAMBLE RF12_SEND_(0xAA); RF12_SEND_(0xAA); RF12_SEND_(0x2D); // SYNC RF12_SEND_(0xD4); for(i=0; i<16; i++) RF12_SEND_(0x30+i); RF12_SEND_(0xAA); // DUMMY BYTES RF12_SEND_(0xAA); RF12_SEND_(0xAA); delay_ms(50); } else if (RX_TX_STATE==1) { // Если в состоянии приемника for (i=0; i<16; i++) { data = RF12_RECV_(); USART_Transmit_Package((1<<5) | 2,data,0); delay_ms(10); } FIFOReset_(); delay_ms(100); } else if (RX_TX_STATE==0) { } } Парюсь уже третий день и понять не могу что неправильно. Схемотехника проверена - все соединения прозвонены. Помогите плиз кто на этом уже собаку сьел!!! От безысходности уже взял фукцию долбить SPI "вручную" нежели аппаратными средствами SPI. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DiMomite 0 10 мая, 2009 Опубликовано 10 мая, 2009 · Жалоба Скорее всего ошибка в функции приема: uint8 RF12_RECV_(void) { uint16 data; WAIT_NIRQ_LOW(); writeCmd(0x0000); data = writeCmd(0xB000); return (data & 0x00FF); } Потому что WAIT_NIRQ_LOW(); используется только при передаче. В документе, который я приложил во втором сообщении в этой тебе как раз это и описано на странице 6 сверху. Если очень сильно нужно работать с приемником по прерываниям, то надо использовать вывод FFIT/DCLK (сам не проверял, потому что нашел другой более подходящий для меня способ, о котором ниже). Если не изменяет память, то у меня тоже шли постоянные 0x00 когда я делал с WAIT_NIRQ_LOW(); В том же документе для приемника приведен такой код: unsigned char rfRecv() { unsigned int data; while(1) { data = writeCmd(0x0000); if ( (data&0x8000) ) { data = writeCmd(0xB000); return (data&0x00FF); } } } Объясню это словами: для того что бы знать принят байт или нет, в модуль надо писать пустое слово 0x0000, и смотреть установлен ли в принятом слове старший байт. Но мне этот метод не понравился из-за достаточно большой длительности. Однако, если учесть, что радиомодуль передает данные старшим битом вперед, то можно просто смотреть на уровень сигнала на ножке MISO микроконтроллера предварительно выбрав модуль и опустив уровень на ножке MOSI. (Этот метод показан на странице 25 родного даташита на микросхему RF12B). Кроме того я таким образом еще и проверял наличие данных для приема в основном цикле основной программы: опускаем CS, опускаем MOSI, если на ножке MISO высокий уровень, то можно принимать данные. Прилагаю свой вариант работы с модулем взятый из своего проекта. Код точно рабочий. Если где поудалял из файлов нужные #define, пиши, добавлю. Хотя повторюсь, что если требуется максимальная скорость обнаружения принятых данных, то нужно выделить для прерываний от приемника отдельный вывод. RFM12B.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 11 мая, 2009 Опубликовано 11 мая, 2009 · Жалоба DiMomite Спасибо что откликнулись. На счет while(1) {...} в функции приемника - мне это не понравилось т.к. если ничего не приходит то контроллер уходит в ступор. А чтобы не уходил надо на Прием выделять некоторое кол-во времени - например заводить переменную i и считать её кол-во. Вот например: uint8 RF12_RECV_(void) { uint16 data; uint16 i; i=0; while(1) { data = writeCmd(0x0000); i++; if ( (data&0x8000) ) { data = writeCmd(0xB000); return (data & 0x00FF); } else if (i==0xFFFF) return(0); } } У меня еще был CS притянут к GND через 10к. Кинул CS на МЦУ чтобы долбить вручную. В общем даже если убрать из приемника WAIT_NIRQ_LOW(); (в чем вы абсолютно правы - это нужно только для передатчика) и сделать CS то результат всё равно тот же - приёма нет. Ох видать либо где-то глупая ошибка либо один из RFM12BP битый. Кстати чтобы исключить последнее как можно точно проверить живой там кристалл или нет? Осциллографа нет - так бы по управлял выходной частотой модуля меняя делитель. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 11 мая, 2009 Опубликовано 11 мая, 2009 (изменено) · Жалоба Еще что интересно, если в "чистый" (неконфигурируемый) RFM12BP отослать 0x0000 то вывод IRQ становиться в 1. К чему бы это? Изменено 11 мая, 2009 пользователем Halfback Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
san822 2 11 мая, 2009 Опубликовано 11 мая, 2009 · Жалоба И еще. Тут http://radio.delanet.ru/content/view/571/46/ можно скачать генераторы кода инициализации. А вот тут говорится о ошибках в доках производителя и дается исправленный вариант. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 15 мая, 2009 Опубликовано 15 мая, 2009 · Жалоба Добился всё-таки обмена по радиоканалу. Но всё же остается вопрос по регистру Receiver Control Command . Как использовать битик Р16 (Interrupt input /VDI)??? В даташите что-то внятного по VDI либо Interrupt input не нашел. И не понятно что в этом случае является для модуля RFM12BP входом а что выходом. Идея в том что по приходу байта хочу вызывать обработчик прерывания. Может кто разьяснить? Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
masterpc 0 24 июля, 2009 Опубликовано 24 июля, 2009 · Жалоба Я также пытаюсь связать два модуля RFM12B, но пока безуспешно. Приемник получает только (0хFF) Привожу код приемника: #define EnableInterrupts() _SEI(); #define DisableInterrupts() _CLI(); #define MAIN_FREQ 7372800 #define SCK 5 // SPI clock B #define SDO 5 // SPI Data output (RFM12B side) D #define SDI 3 // SPI Data input (RFM12B side) B #define CS 4 // SPI SS (chip select) D #define NIRQ 3 // (PORTD) #define WAIT_NIRQ_LOW() while(PIND&(1<<NIRQ)) //#define HI(x) PORTB |= (1<<(x)) //#define LO(x) PORTB &= ~(1<<(x)) #define HI_SCK PORTB |= (1<<5) #define LO_SCK PORTB &= ~(1<<5) #define HI_SDI PORTB |= (1<<3) #define LO_SDI PORTB &= ~(1<<3) #define HI_CS PORTD |= (1<<4) #define LO_CS PORTD &= ~(1<<4) #define LED 4 // B #define LED_OFF() PORTB &= ~(1<<LED) #define LED_ON() PORTB |= (1<<LED) typedef unsigned char byte; #include <ina90.h> #include <iom48.h> void rsInit(void) { UBRR0L = 3;//(MAIN_FREQ / (16 * baud)) - 1; //115200 UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); // 8N1 UCSR0B = (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0); // enable tx and rx and interrupts } void rsSend(unsigned char data) { while( !(UCSR0A & (1<<UDRE0))); UDR0 = data; } /*unsigned char rsRecv() { while( !(UCSR0A & (1<<RXC0))); return UDR0; }*/ void HardwareInit() { PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x00; PORTD=0x00; DDRD=0x00; HI_CS; HI_SDI; LO_SCK; DDRB = (1<<SDI) | (1<<SCK)|(1<<LED); DDRD = (1<<CS); // WDT prescaler __watchdog_reset(); // Start timed equence WDTCSR |= (1<<WDCE) | (1<<WDE); // Set new prescaler(time-out) value = 64K cycles (~0.25 s) WDTCSR = (1<<WDE) | (1<<WDP2) | (1<<WDP0); } void ClearWDT(void){ _WDR(); } unsigned int writeCmd(unsigned int cmd) { unsigned char i; unsigned int recv; recv = 0; LO_SCK; LO_CS; for(i=0; i<16; i++) { if(cmd&0x8000) HI_SDI; else LO_SDI; HI_SCK; recv<<=1; if( PIND&(1<<SDO) ) recv|=0x0001; LO_SCK; cmd<<=1; } HI_CS; return recv; } void FIFOReset() { writeCmd(0xCA81); writeCmd(0xCA83); } /* void waitForData() { unsigned int status; while(1) { status = writeCmd(0x0000); if ( (status&0x8000) ) { return; } } } */ void rfInit() { writeCmd(0x80D7); //EL,EF,433band,12.0pF writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC writeCmd(0xA640); //freq select writeCmd(0xC647); //4.8kbps writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR writeCmd(0xCED4); //SYNC=2DD4; writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN writeCmd(0x9850); //!mp,90kHz,MAX OUT writeCmd(0xCC17); //!OB1,!OB0, LPX,!ddy,DDIT,BW0 writeCmd(0xE000); //NOT USE writeCmd(0xC800); //NOT USE writeCmd(0xC040); //1.66MHz,2.2V } /* unsigned char rfRecv() { unsigned int data; writeCmd(0x0000); data = writeCmd(0xB000); return (data&0x00FF); } */ unsigned char rfRecv() { unsigned int data; while(1) { data = writeCmd(0x0000); if ( (data&0x8000) ) { data = writeCmd(0xB000); return (data&0x00FF); } ClearWDT(); } } int main(void) { unsigned char data, i; HardwareInit(); rfInit(); rsInit(); FIFOReset(); while(1) { LED_ON(); //waitForData(); for (i=0; i<16; i++) { data=0; data = rfRecv(); //if(data==0x00A1)LED_ON(); rsSend(data); } FIFOReset(); LED_OFF(); ClearWDT(); } } и передатчика: #define EnableInterrupts() _SEI(); #define DisableInterrupts() _CLI(); #define SCK 5 // SPI clock B #define SDO 5 // SPI Data output (RFM12B side) D #define SDI 3 // SPI Data input (RFM12B side) B #define CS 4 // SPI SS (chip select) D #define NIRQ 3 // (PORTD) //#define HI(x) PORTB |= (1<<(x)) //#define LO(x) PORTB &= ~(1<<(x)) #define HI_SCK PORTB |= (1<<5) #define LO_SCK PORTB &= ~(1<<5) #define HI_SDI PORTB |= (1<<3) #define LO_SDI PORTB &= ~(1<<3) #define HI_CS PORTD |= (1<<4) #define LO_CS PORTD &= ~(1<<4) #define WAIT_NIRQ_LOW() while(PIND&(1<<NIRQ)) #define LED 4 // B #define LED_OFF() PORTB &= ~(1<<LED) #define LED_ON() PORTB |= (1<<LED) typedef unsigned char byte; #include <ina90.h> #include <iom48.h> void HardwareInit() { PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x00; PORTD=0x00; DDRD=0x00; HI_CS; HI_SDI; LO_SCK; DDRB = (1<<SDI) | (1<<SCK) | (1<<LED); DDRD = (1<<CS); // WDT prescaler __watchdog_reset(); // Start timed equence WDTCSR |= (1<<WDCE) | (1<<WDE); // Set new prescaler(time-out) value = 64K cycles (~0.25 s) WDTCSR = (1<<WDE) | (1<<WDP2) | (1<<WDP0); } void ClearWDT(void){ _WDR(); } unsigned int writeCmd(unsigned int cmd) { unsigned char i; unsigned int recv; recv = 0; LO_SCK; LO_CS; for(i=0; i<16; i++) { if(cmd&0x8000) HI_SDI; else LO_SDI; HI_SCK; recv<<=1; if( PIND&(1<<SDO) ) recv|=0x0001; LO_SCK; cmd<<=1; } HI_CS; return recv; } void rfInit() { writeCmd(0x80D7); //EL,EF,433band,12.0pF writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC writeCmd(0xA640); //frequency select writeCmd(0xC647); //4.8kbps writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR writeCmd(0xCED4); //SYNC=2DD4�G writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN writeCmd(0x9850); //!mp,90kHz,MAX OUT writeCmd(0xCC17); //OB1�COB0, LPX,�Iddy�CDDIT�CBW0 writeCmd(0xE000); //NOT USE writeCmd(0xC800); //NOT USE writeCmd(0xC040); //1.66MHz,2.2V } void rfSend(unsigned char data){ //WAIT_NIRQ_LOW(); while(PIND&(1<<NIRQ))ClearWDT(); writeCmd(0xB800 + data); } int main() { volatile unsigned int i,j; asm("cli"); for(i=0;i<1000;i++)ClearWDT(); for(j=0;j<123;j++); ClearWDT(); ClearWDT(); HardwareInit(); rfInit(); while(1){ LED_ON(); writeCmd(0x0000); rfSend(0xAA); // PREAMBLE rfSend(0xAA); rfSend(0xAA); rfSend(0x2D); // SYNC rfSend(0xD4); for(i=0; i<16; i++) { rfSend(0x30+i); } rfSend(0xAA); // DUMMY BYTES rfSend(0xAA); rfSend(0xAA); LED_OFF(); for(i=0; i<10000; i++)ClearWDT(); for(j=0; j<123; j++); ClearWDT(); } } Код взял из примера, вроде ничего не напутал, проверил схему, подключения, но не нашел где собака порылась. Может кому бросится в глаза где я накуралесил, буду очень признателен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mempfis_ 0 24 июля, 2009 Опубликовано 24 июля, 2009 · Жалоба Расскажу об опыте применения модуля si4421 (аналог rf12). Написано внизу много но всё это фрагменты программы реально работающего устройства. Всё начинается с инициализации. При работе по прерываниям желательно дождаться пока вывод прерываний не установится в 1. Для этого достаточно читать регистр статуса пока не модуль не "отпустит" Пример инициализации (если в настройке регистра бит не указан то он не испрользуется, сами названия как в документации) Исключения составляют регистры FREQSET_CMD и DATARATE_CMD - для них я отдельно расчитываю константы (как - написано в документации). /////////////////////////////////////// void si4421_init(void) { delay_ms(100); while(!(RF12_PIN&(1<<nIRQ))) SPIWriteWord(0x0000); SPIWriteWord(Si4421_CONFIGSET_CMD|(1<<bf0)|(1<<x3));//EL,EF,433band,12.5pF //0x80E7 SPIWriteWord(Si4421_POWERMAN_CMD|(1<<es)|(1<<ex)|(1<<dc)); //er,!ebb,ET,ES,EX,!eb,!ew,DC //SPIWriteWord(Si4421_POWERMAN_CMD|(1<<et)|(1<<es)|(1<<ex)|(1<<dc)); //er,!ebb,ET,ES,EX,!eb,!ew,DC SPIWriteWord(Si4421_FREQSET_CMD + FrequencyTable[default_chanel&0x0f]); SPIWriteWord(Si4421_DATARATE_CMD); //datarate SPIWriteWord(Si4421_RECEIVERCNT_CMD|(1<<p16)|(1<<i2)|(1<<i1)); //VDI,FAST,64kHz,0dBm,-103dBm SPIWriteWord(Si4421_DATAFILTER_CMD|(1<<al)|(1<<f_2)); //AL,!ml,DIG,DQD4 SPIWriteWord(Si4421_FIFO_RESET_CMD|(1<<fi3)/*|(1<<dr)*/); //FIFO8,SYNC,!ff,DR SPIWriteWord(Si4421_SYNCPATT_CMD); //SYNC=2DD4; SPIWriteWord(Si4421_AFC_CMD|(1<<a1)|(1<<oe)|(1<<en)); //@PWR,NO RSTRIC,!st,!fi,OE,EN SPIWriteWord(Si4421_TXCONFIG_CMD|(1<<m1)); //!mp,45kHz,MAX OUT SPIWriteWord(Si4421_PLLSET_CMD|(1<<dly)|(1<<bw0)); //!OB1,!OB0, LPX,!ddy,DDIT,!BW0 SPIWriteWord(Si4421_WTC_CMD);//NOT USE SPIWriteWord(Si4421_LOWDUTYCCL_CMD);//NOT USE SPIWriteWord(Si4421_LBD_CMD);//2,25 V 1 MHz } /////////////////////////////////////// После инициализации модуль готов быть включённым на приём или передачу /////////////////////////////////////// void si4421_on_tx(void) { SPIWriteWord(Si4421_CONFIGSET_CMD|(1<<el)|(1<<bf0)|(1<<x3));//EL,EF,433band,12.5pF //0x80E7 SPIWriteWord(Si4421_POWERMAN_CMD|(1<<et)|(1<<es)|(1<<ex)|(1<<dc)); //er,!ebb,ET,ES,EX,!eb,!ew,DC } /////////////////////////////////////// /////////////////////////////////////// void si4421_on_rx(void) { SPIWriteWord(Si4421_CONFIGSET_CMD|(1<<ef)|(1<<bf0)|(1<<x3));//EL,EF,433band,12.5pF //0x80E7 SPIWriteWord(Si4421_POWERMAN_CMD|(1<<er)|(1<<es)|(1<<ex)|(1<<dc)); //er,!ebb,ET,ES,EX,!eb,!ew,DC si4421_fifo_reset(); } /////////////////////////////////////// При включении на приём я дополнительно сбрасываю фифо чтобы она была готова к приёму данных /////////////////////////////// void si4421_fifo_reset() { SPIWriteWord(Si4421_FIFO_RESET_CMD|(1<<fi3)/*|(1<<dr)*/); SPIWriteWord(Si4421_FIFO_RESET_CMD|(1<<fi3)|(1<<ff)/*|(1<<dr)*/); } ////////////////////////////////////// Таким образом после влючения питания выполняем такие действия void main(void) { //инициализируем мк ................................... //инициализация внешнего прерывания ............................................................ //инициализируем rf12 si4421_init(); si4421_on_tx(); //или si4421_on_rx(); while(1) { //вечный цикл //также сдесь можно вставить опрос регистра статуса чтобы не городить работу по прерываниям if(rf12_flag) { Si4421_handler(); rf12_flag = 0; } } } Этого достаточно чтобы модуль заработал как положено. Теперь собственно по приёму/передаче данных У меня rf12 висит на внешнем прерывании настроенном на срабатывание по заднему фронту В прерывании просто вставляется флаг rf12_flag, обработка идёт в основном цикле Действия при приёме данных ///////////////////////////////////////////// inline unsigned int si4421_read_status(void){return (SPIWriteWord(0x0000));} ///////////////////////////////////////////// ///////////////////////////////////////////// unsigned char si4421_read_fifo() { unsigned int data; data = SPIWriteWord(0xB000); return ( (unsigned char) (data&0x00ff) ); } ///////////////////////////////////////////// #define FFIT 0x8000 //fifo receive preprogrammed number of bits ///////////////////////////////////////////// void Si4421_handler(void) { unsigned int status; unsigned char data; //обязательно читаем статус чтобы сбросить источник прерываний status = si4421_read_status(); //если в фифо есть данные то считываем if(status&FFIT) { data = si4421_read_fifo(); //делаем с данными что хотим например отправляем в уарт putchar(data); } } ///////////////////////////////////////////// Действия при передаче также просты /////////////////////////////////////// void si4421_write_tx(unsigned char byte) { SPIWriteWord(0xB800 | byte); } /////////////////////////////////////// #define RGIT 0x8000 //tx reg ready to receive new byte for transmitt ///////////////////////////////////////////// void Si4421_handler(void) { unsigned int status; unsigned char data; //обязательно читаем статус чтобы сбросить источник прерываний status = si4421_read_status(); //если передающий регистр готов к отправке данных то ложим в него байт if(status&RGIT) { si4421_write_tx(my_data_for_transmitt); } } ///////////////////////////////////////////// У меня лично модуль работает и на приём и на передачу (не одновременно а когда нет данных данных для передачи он всё время в режиме приёма, когда есть данные то переключается на передачу, передаёт и снова переходит в режим приёма). Всё построено на прерывании от модуля, данные для передачи буферизируются в уарт_фифо. При передаче данных данных обязательно необходимо передавать такую последовательность 0xAA; 0xAA; 0xAA; 0x2D; 0xD4; свои данные; 0xAA; 0xAA; 0xAA; Первые три 0xAA для синхронизации передатчика с приёмником 0x2D; 0xD4; синхропоследовательность после которой фифо в модуле начнёт генерировать прерывания по приёму данных Последние три 0xAA нужны чтобы последние байты данных гарантировано передались в эфир а не остались в передающем буффере модуля. Команда сброса фифо позволяет прервать текущий приём и заново фифо будет заполнятся только после приёма новой синхропоследовательности. Если нет желания цеплять модуль на прерывание можно постоянно мониторить регистр статуса чтобы знать что с модулем происходит (когда заполнится фифо, когда передающий регистр будет пуст). Два абсолютно одинаково настроенных модуля но один включённый на приём а второй на передачу будут гарантированно иметь связь друг с другом если передавать последовательность данных как указано выше и соблюсти правило - или в прерывании или остоянно опрашивая регист статуса мониторить готовность передающего регистра или наличие данных в приёмной фифо. Для надёжности в приёмнике после принятия стоповой комбинации (например байт 0x0D) желательно сбрасывать фифо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
masterpc 0 30 июля, 2009 Опубликовано 30 июля, 2009 · Жалоба Спасибо за помощь, все заработало!!! Но к стыду своему добавлю, что причина была в железе -взял платку с другого устройства и не увидел поддяжку с SDO на питание. Но есть в этом и плюсы - разобрался с модулями :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться