Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить

HOPERF RFM70, особенности работы

Пн янв 09, 2012 21:16:02

Всем привет.

Приобрёл пару трансиверов RFM70.
Интерфейс вроде как SPI, но судя по сведениям из инета, длина слова для SPI может быть разной в различных применениях (где-то 5 бит, где-то 9 и т.д.). Стало быть, встроенный в контроллер SPI-интерфейс использовать нельзя (там ведь буфер 8-битный, коль не путаю), и нужно организовывать всё программно?

Подскажите, кому доводилось работать с этими модулями или подобными им.

Спасибо.

Re: HOPERF RFM70, особенности работы

Пн янв 09, 2012 22:58:29

TripleKill писал(а):Всем привет.

Приобрёл пару трансиверов RFM70.
Интерфейс вроде как SPI, но судя по сведениям из инета, длина слова для SPI может быть разной в различных применениях (где-то 5 бит, где-то 9 и т.д.). Стало быть, встроенный в контроллер SPI-интерфейс использовать нельзя (там ведь буфер 8-битный, коль не путаю), и нужно организовывать всё программно?

Подскажите, кому доводилось работать с этими модулями или подобными им.

Спасибо.


Вот блог http://we.easyelectronics.ru/part/radio ... rfm70.html читай.

Re: HOPERF RFM70, особенности работы

Пт янв 13, 2012 19:59:45

Удалось прочитать хоть что-то, но полностью он не работает. Проблема кроется в линии MOSI, при записи она работает, а вот при вызове процедуры чтения - молчит (а должна вначале переслать адрес регистра, и уже потом молчать). Может, я что-то не так делаю? Код ниже.

Код:
#define CE PORTD.F0
#define CSN PORTD.F1
#define SCK PORTD.F2
#define MOSI PORTB.F0
#define MISO PORTD.F4


sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;

sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;

int tmp;
short flag=0;
unsigned char stat=0;
unsigned char buf=0;
char t=0;
bit b;
char *txt="abcdef";
unsigned char R_Register(unsigned char addr);
unsigned char DummyRead();
unsigned char W_Register(unsigned char addr);
void DummyWrite(unsigned char s1);


void main() {

TRISB=0;
PORTB=0;

TRISD=0b00010000;
PORTD=0;

Lcd_Init();
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);

CE=0;
CSN=1;
SCK=0;

Lcd_out(1,1,"Ready");


delay_ms(2000);


Lcd_Cmd(_LCD_CLEAR);


CSN=0;
MOSI=1;
buf=DummyRead();
CSN=1;

CSN=0;
R_Register(0x04);
buf=DummyRead();
CSN=1;
inttostr(buf,txt);

lcd_out(1,10,txt);
lcd_out(1,1,"SETUP_RETR");

inttostr(stat,txt);

lcd_out(2,10,txt);
lcd_out(2,1,"STATUS");

delay_ms(2000);
Lcd_Cmd(_LCD_CLEAR);
lcd_out(1,1,"Writing...");

CSN=0;
W_Register(0x04);
DummyWrite(0xFF);
CSN=1;

Lcd_Cmd(_LCD_CLEAR);
lcd_out(1,1,"Reading...");

CSN=0;
R_Register(0x04);
buf=DummyRead();
CSN=1;
inttostr(buf,txt);

lcd_out(1,10,txt);
lcd_out(1,1,"SETUP_RETR");

inttostr(stat,txt);

lcd_out(2,10,txt);
lcd_out(2,1,"STATUS");







}

unsigned char DummyRead() {

for (t=1; t<=8; t++) {
SCK=1;
switch (t) {
case 1: buf.F7=MISO; break;
case 2: buf.F6=MISO; break;
case 3: buf.F5=MISO; break;
case 4: buf.F4=MISO; break;
case 5: buf.F3=MISO; break;
case 6: buf.F2=MISO; break;
case 7: buf.F1=MISO; break;
case 8: buf.F0=MISO; break;
};
delay_ms(100);
SCK=0;
delay_ms(100);
};

return buf;

}

void DummyWrite(unsigned char s1) {
for (t=1; t<=8; t++) {
SCK=1;
switch (t) {
case 1: MOSI=s1.F0; break;
case 2: MOSI=s1.F1; break;
case 3: MOSI=s1.F2; break;
case 4: MOSI=s1.F3; break;
case 5: MOSI=s1.F4; break;
case 6: MOSI=s1.F5; break;
case 7: MOSI=s1.F6; break;
case 8: MOSI=s1.F7; break;
};
delay_ms(100);
SCK=0;
delay_ms(100);
};

}

unsigned char R_Register(unsigned char addr) {
MOSI=0;
SCK=0;
for (t=1; t<=8; t++) {
SCK=1;
switch (t) {
case 1: stat.F7=MISO; break;
case 2: stat.F6=MISO; break;
case 3: stat.F5=MISO; break;
case 4: MOSI=addr.B4; stat.F4=MISO; break;
case 5: MOSI=addr.B3; stat.F3=MISO; break;
case 6: MOSI=addr.B2; stat.F2=MISO; break;
case 7: MOSI=addr.B1; stat.F1=MISO; break;
case 8: MOSI=addr.B0; stat.F0=MISO; break;
};
delay_ms(100);
SCK=0;
delay_ms(100);

return stat;
};

}

unsigned char W_Register(unsigned char addr) {
MOSI=0;
SCK=0;
for (t=1; t<=8; t++) {
SCK=1;
switch (t) {
case 1: stat.F7=MISO; break;
case 2: stat.F6=MISO; break;
case 3: MOSI=1; stat.F5=MISO; break;
case 4: MOSI=addr.F4; stat.F4=MISO; break;
case 5: MOSI=addr.F3; stat.F3=MISO; break;
case 6: MOSI=addr.F2; stat.F2=MISO; break;
case 7: MOSI=addr.F1; stat.F1=MISO; break;
case 8: MOSI=addr.F0; stat.F0=MISO; break;
};
delay_ms(100);
SCK=0;
delay_ms(100);
};

return stat;

}


Задержек везде понатыкано для того, чтобы успевать следить за светодиодами, которыми и проверяется работоспособность.
Все линии работают нормально, кроме MOSI (данные, идущие к модулю). Начальный вариант был без конструкций switch, с побайтовым сдвигом приёмной переменной, но сдвиг этот работает как-то странно, и результат получается неожиданный. В данном варианте программы после первого прочтения получаются данные на экране SETUP_RETR = 28, STATUS = 0. После запси и повторного чтения SETUP_RETR = 28, STATUS = 14, хотя я хотел записать 0xFF в SETUP_RETR. Интересно, что 14 должно содержаться в регистре STATUS с самого начала.

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

P.S. Программа на mikroC.

Re: HOPERF RFM70, особенности работы

Сб янв 14, 2012 13:39:54

Я так понимаю это код для пика? Немного мудреный код, Почему вы не хотите взять пример с сайта производителя? http://www.hoperf.com/pro/rf/24g/RFM70.htm Там 100% рабочий пример, сам проверил, вполне понятный код! Тем более для пика!

Re: HOPERF RFM70, особенности работы

Сб янв 14, 2012 15:16:54

dimka11, примеры я видел. Они вроде под микрочиповский С (или другой?), и, раз уж Вы с ним работали, позвольте поинтересоваться, там есть библиотека для работы с LCD 16x2? В микроСи вывод текста на экран - пара строк, а тут мне не придётся ли по байту конфигурировать и посылать данные на дисплей?

Re: HOPERF RFM70, особенности работы

Вс янв 15, 2012 18:24:13

Разобрался. Напишу тут, может кому-то поможет.
Товарищи, уделяйте внимание мелочам! Дело в том, что бит в модуль защёлкивается по фронту (а не по уровню) сигнала SCK.
В вышеприведённом примере вначале устанавливается SCK=1, затем выводятся данные, что неправильно.
Если исправить в каждом case при записи, например, так: MOSI=s1.F0; SCK=1;, а установку SCK в 1 до конструкции switch убрать, то всё работает.

Re: HOPERF RFM70, особенности работы

Вс фев 19, 2012 21:30:05

Как-то я подзабросил это дело, но разобраться всё-таки хочется.
Вопросы с записью-чтением микросхемы я решил, всё читается-пишется.
Теперь встал вопрос о передаче и приёме данных.
Я написал такой код:

Код:
Configure_TX();        //настройка на режим передачи

CSN=0;
R_Register(0x17);
inttostr(DummyRead(),txt);
CSN=1;
Lcd_out(1,10,txt);
Lcd_out(1,1,"FIFO STAT");
delay_ms(3000);                   //читаю состояние буфера передачи и вывожу на экран




CSN=0;
DummyWriteMSB(0b10110000);
DummyWrite(0xFF);
DummyWrite(0x00);
DummyWrite(0xFF);
DummyWrite(0x00);
DummyWrite(0xFF);
CSN=1;                                     //записываю в буфер инфу, которую хочу передать

delay_ms(3000);

CSN=0;
R_Register(0x17);
inttostr(DummyRead(),txt);
CSN=1;
Lcd_out(1,10,txt);
Lcd_out(1,1,"FIFO STAT");      //вновь читаю статус буфера; должен измениться, т.к. есть неотправленные данные

CE=1;         //разрешение работы; должна произойти отправка данных

delay_ms(3000);

CSN=0;
R_Register(0x17);
inttostr(DummyRead(),txt);
CSN=1;
Lcd_out(1,10,txt);
Lcd_out(1,1,"FIFO STAT");  //читаю статус буфера; должен вернуться в прежнее состояние


Проблема со всем этим в том, что изменение состояния буфера не происходит. У кого-нибудь есть мысли, в чём может быть дело? И ещё вопрос: правильно ли организован порядок передачи, т.е. записал данные в буфер, поднял CE - пошла передача?
Да, кстати, в void Configure_TX() содержатся все настройки и параметры, которые по ДШ надо записать в регистры.

Заранее спасибо.

Re: HOPERF RFM70, особенности работы

Вт янв 08, 2013 19:32:54

Привет всем!
Собрал приемник и передатчик с RFM70. Контроллер mega16. Все повторено отсюда
http://projects.web4clans.com/?p=90
Работает но странно. Принимает не то, что отправляется. К примеру отправляется 0x05, а принимается 0xC6. Причем всегда, чтобы не делалось: физический рестарт, разное расстояние между приемником и передатчиком. SPI настроен абсолютно одинаково и там, и там. Проверял уже не один раз.
Можно конечно составить таблицу соответствия если не будет повторений на приемнике, но хочется все таки понять причину.
Может кто-то с подобным сталкивался или есть мысли?
Буду признателен.

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 11:10:50

А там модуль вообще, хоть как-то инициализируется?

Потому как окромя
setMode(1);
setChannel(8);

Никаких явных попыток его инициализации я не заметил.
История о том, что достаточно только добавить воды подать питание и все заработает, хороша конечно, но я от модулей без, хотя бы, частичной инициализации, толку так и не добился.
Поэтому, как на мой взгляд, стоит его все-таки инициализировать по даташиту.

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 12:27:31

Не RFM70 идеализируется.
Там функция Begin(); инициализирует и SPI и RFM70. Да и передача с приемом то идут. Выключил передатчик нет приема, включил передатчик пошел прием.
Попробовал разные каналы. Безуспешно.
Ткнулся осциллографом на ножки RFM70: а на MISO страшный завал фронтов. Поставил минимально возможную частоту SPI (fCLK/64) фронта чистые, но проблему это не устранило.
Все равно приемник принимает только когда передает передатчик но не то.

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 13:48:05

Точно. Проморгал Begin.
Тогда второй вопрос - а запитано все как?

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 13:57:45

На входе всего устройства 5В. Далее стоит два крена на 3.3В. Один питает контроллер, второй - RFM70. Сделано это было для того, чтобы 5В при программировании контроллера не попало на питание RFM70. Входа RFM70 5В держат и по даташиту
Power Supply Voltage - max - 3.6 V
Digital input Pin
High level - max - 5.25 V

и где-то на форуме читал.
Можно было mega16 запитать на постоянку от 5В, но я не рискнул.

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 14:05:53

Хрень какая-то тогда.
Я грешным делом подозревал, что контроллер запитан от 5В. При этом, несмотря на заявленную в даташите устойчивость модуля трансивера к 5 вольтам на информационных линиях, у меня часть модулей вела себя неадекватно. Но при питании от 3-х вольтовых источников проблема не проявлялась. Работоспособность сохранялась как минимум до 4-х мегагерц тактирования SPI.

Может по линии MISO подтяжка на порту все-таки не включена?

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 14:12:38

А с этого места поподробнее.
Никаких подтяжек у меня нет.
Когда у меня на больших скоростях SPI были завалы на MISO я ставил 12кОм на +3.3. Но уменьшил скорость SPI и убрал, фронта вроде ничего.

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 14:57:01

Имею в виду встроенную подтяжку на соответствующем порту. Ту, что включается записью единички в соответствующий ноге MISO бит порта, на котором SPI висит. Мне ее вполне было достаточно для нормальной работы модулей.

Datasheet MEGA16 говорит (стр 58):
MISO – Port B, Bit 6
MISO: Master Data input, Slave Data output pin for SPI channel. When the SPI is enabled as a
Master, this pin is configured as an input regardless of the setting of DDB6. When the SPI is
enabled as a Slave, the data direction of this pin is controlled by DDB6. When the pin is forced
by the SPI to be an input, the pull-up can still be controlled by the PORTB6 bit.
-->> подтяжка на порту автоматически не включается.

По логике в куске инициализации SPI нужно заменить:

// chip select to high
PORT_SPI |= (1<<CSN);

на

// chip select to high + MISO Pull-up
PORT_SPI |= (1<<CSN)|(1<<MISO);

Для спокойствия, я бы еще и подтяжку на линии IRQ включил.

Ну или резисторами на VCC подтянуть.

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 15:18:44

Не-е, не помогло. Но все равно спасибо. Зайдем с другой стороны.
Я в приемнике немного изменил код под свои задачи:
Код:
uint8_t i=0;
uint8_t *buffer;
...
i=receivePayload(buffer);
 if (i == 1)
{
   PORTA=*buffer;
}

Как я понял, функция receivePayload() возвращает длину принятого пакета в байтах. Я посылаю 1байт, следовательно его и должен принять. На порту А я прицепил 8 светодиодов, чтобы смотреть что происходит.
По-моему код должен работать.

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 15:20:19

К тому же я MISO и до этого на 3.3В подтягивал выводным 12кОм. Без успеха.

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 15:29:50

Это только в случае, если активирована опция переменной длины пакета, либо длина пакета, для соответствующего pipe выставлена равной 1 байту.
Я, к сожалению, в Си, мягко говоря, слаб. Попытаюсь сейчас исходник покопать - что там немец по умолчанию инициализирует.

Судя по всему - наш немецкий друг использует 32-х байтные пакеты:

//************ Bank0 register initialization commands
const uint8_t PROGMEM RFM70_bank0Init[][2] = {
// address data
// -поскипано мною
{ (0x20|0x11), 0x20 }, //Payload len pipe0 - как раз 32 байта длина пакета для нулевого пайпа.

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 16:39:22

А ни у кого нет примерчиков на asm случаем ?

Re: HOPERF RFM70, особенности работы

Ср янв 09, 2013 17:08:23

Я для себя библиотеки асмовые делал.
Но вот с комментированностью там туго. Потому как "для себя".
Ответить