Подключение трансивера на CC1101 к Arduino

MAFia
Offline
Зарегистрирован: 26.10.2011

Доброго времени суток! Заказал себе 2 модуля трансивера на базе CC1101 (вот viewitem.eim.ebay.ru/2PCS--Wireless-RF-Transceiver-Module-433Mhz-CC1101-CC1100-/260915767551/item) и немного не понимаю, как их подключить.

1) Модули 3.3в, нужен преобразователь уровней. Можно просто воспользоваться делителем напряжения для линий из дуины в модуль (Slave In, Slave Select, Clock, Vcc) и напрямую подключить линию из модуля в дуину (slave out)?

2)Совсем не понял как посылать и принимать данные, всяческое изменения регистров, SmartRF Studio и прочее далеки от моего понимания :-(

Если кто-нибудь знает как работать с этой штукой (или CC1100, они почти аналогичны), подскажите? Заранее спасибо.

MAFia
Offline
Зарегистрирован: 26.10.2011

Промучился с этой штукой, почти ничего не добился, хотябы подключил и работает (отсылает статус-байты)

Чтобы сконфигурировать ее, получил значения с SmartRF Studio, загнал в массив [адресс][значение]

Чтобы записать, надо "наложить на адресс маску 0х00, а чтобы считать 0х80". Наложить маску - это как. Насколько я понял из даташита, то первый байт отправляемый по СПИ дожен выглядеть так [байт чтения\записи][байт одиночная запись\бурст запись][адресс]. 0-запись, 1 - чтение; 0-1 байт, 1-бурст. Т.о для чтения одного байта надо к его адресу прибавить 0x80, для записи одного - 0x00, для бурст соответсвенно 0xC0 и 0x40.

Вот так я делаю:

\\Конфигурирую ноги дуины и SPI
digitalWrite(SOpin, LOW);
SPI.transfer(0x30); \\reset
\\в цикле 
digitalWrite(SOpin, LOW);
SPI.transfer(RegConfig[0][i]);
SPI.transfer(RegConfig[1][i]);
digitalWrite(SOpin, HIGH);
digitalWrite(SOpin, LOW);
SPI.transfer(0x35); \\передача
digitalWrite(SOpin, HIGH);
digitalWrite(SOpin, LOW);
SPI.transfer(0x3F); 
SPI.transfer(value);
digitalWrite(SOpin, HIGH);

 

 По идее, должен отсылать - но никак, токопотребление не возрастает. ЧТо я неправильно делаю?

MAFia
Offline
Зарегистрирован: 26.10.2011

До сих пор не получил результат. Как бы получается записывать регистры, вроде все понял, но постоянно статус-байт возвращает "TX FIFO has underflowed. Acknowledge with SFTX". Как-то получалось, что возвращалось и режим TX, RX, Fast Tx ready, но редко. В основном  TX FIFO has underflowed.

Ставлю длина пакета фиксированная, 1 байт, Ограничения TX FIFO тоже 1 байт. Даташит утверждает, что Underflowed возникает при кол-ве байт ниже ограничения. Но ведь я записываю туда байты. Пишу:
 

SPI.transfer(0x3F | 0x40);

SPI.transfer(байт);

А все равно underflowed. В чем может быть причина? Я неправильно пишу в регистры?

MAFia
Offline
Зарегистрирован: 26.10.2011

Кажется что-то есть... По прежнему пишет "TX FIFO underflowed", но судя по току (16мА, как раз ток передачи при 0Дб) передача идет. Что немного странно. Идет и с фиксированной, и с переменной длиной пакета.

Код (пока что кривой и отладочный):

#include <SPI.h>
// ================ комманды ===========
#define SRES 0x30
#define SFSTXON 0x31
#define SXOFF 0x32
#define SCAL 0x33
#define SRX 0x34
#define STX 0x35
#define SIDLE 0x36
#define SWOR 0x38
#define SPWD 0x39
#define SFRX 0x3A
#define SFTX 0x3B
#define SWORRST 0x3C
#define SNOP 0x3D
/============ выводы к которым SPI подключен==========
#define MISO 50
#define MOSI 51
#define Clock 52
#define SS 53 //Выбор "раба". Нужно к 0 прижимать
//==============================

void setup(){
//Все понятно. Настройка СПИ и Сериал
 Serial.begin(9600);
 pinMode(50, INPUT); 
 pinMode(51, OUTPUT); 
 pinMode(52, OUTPUT); 
 pinMode(53, OUTPUT); 
 pinMode(49, INPUT);
 SPI.setBitOrder(MSBFIRST);
 SPI.setClockDivider(SPI_CLOCK_DIV8);
 SPI.setDataMode(SPI_MODE0);
 SPI.begin();
 //======================================
Stroble(SRES); //перезагружаем
Stroble(SIDLE);//в ждущий режим
 //========== Настройки ===============
/*  Взяты из Smart RF.
433Mhz, 1.2 kBaud, 16Mhz кварц, модуляция GFSK, фиксированная длина пакета 1 байт 
Вывожу в десятичном виде, чтобы не приписывать "0x" к каждому значению
*/
 byte RegConfig[] = { //50 elements Last adress 49
41,
46,
6,
7,
211,
145,
34, //переменная длина пакета  - 64
4,
1,
0,
0,
12,
0,
16,
167,
98,
37,
131,
19,
34,
248,
98,
7,
48,
24,
29,
28,
199,
0,
176,
135,
107,
251,
182,
16,
233,
42,
0,
31,
65,
0,
89,
127,
63,
136,
49,
9,
0,
4
};
//Пишем в регистры
 for (byte _i=0; _i<=49; _i++){
   digitalWrite(SS,LOW);
   WrReg(_i, RegConfig[_i]);
   digitalWrite(SS,HIGH);
 }
 


Stroble(SIDLE); //Ждущий режим
Stroble(SFTX); //Очищаем буфер 
Stroble(SFSTXON); //Запускаем синтезатор частоты
delay(100);

 //=======================================
}

void loop(){



digitalWrite(SS,LOW);  //Прижимаем ногу к земле
 while(digitalRead(MISO)==HIGH); //Ждем ответа
 delay(1);
 SPI.transfer(0x3F | 0x40); //Комманда на запись в TX FIFO
 SPI.transfer(4); // Данные
 SPI.transfer(2);// Данные
 SPI.transfer(3);// Данные
 SPI.transfer(5);// Данные
 SPI.transfer(6);// Данные
 digitalWrite(SS,HIGH); //Отпускаем ногу
 Serial.println(RdReg(0x3A), DEC); //Выводим кол-во байт в ТХ Фифо
 Status(Stroble(STX)); //Запускаем передачу строблом STX и выводим статус байт. всегда пишет андерфловед
 Serial.println(RdReg(0x3A), DEC); //Опять выводим кол-во байт в ТХ фифо и убеждаемся, что число уменьшилось на число байт в пакете, или 0 - если длина пакета переменная
 delay(1);
 Stroble(SFTX); //Очищаем ТХ фифо. Выкидываем все лишнее
 delay(1);
 Serial.println ("-----------------------"); //ХЗ.
 delay(10);
}
Stroble(SIDLE);  //Ждущий режим
delay(1000);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//Тут расшифровываем статус байт
void Status(byte _ST){
 byte _Val=0;
 _Val = _ST & 240;
 _Val= _Val >> 4;
 _ST= _ST & 14;
 _ST = _ST >> 1;
 Serial.println("============================"); 
 if (_ST == 0) {Serial.println ("IDLE");} 
 if (_ST == 1) {Serial.println ("RX");}
 if (_ST == 2) {Serial.println ("TX");}
 if (_ST == 3) {Serial.println ("Fast TX ready");}
 if (_ST == 4) {Serial.println ("Frequency synthesizer calibration is running");}
 if (_ST == 5) {Serial.println ("PLL is settling");}
 if (_ST == 6) {Serial.println ("RX FIFO has overflowed. Read out any useful data, then flush the FIFO with SFRX"); }
 if (_ST == 7) {Serial.println ("TX FIFO has underflowed. Acknowledge with SFTX"); }
 Serial.print ("bytes available ");
 Serial.println (_Val, DEC);
 Serial.println("============================");
}
//Выполняем команду
byte Stroble (byte _Stroble){
 byte _R;
 digitalWrite(SS,LOW); //ногу к земле
 while(digitalRead(MISO)==HIGH); //Ждем отклик
 delay(1);
 _R = SPI.transfer(_Stroble); //Пишим комманду
 digitalWrite(SS,HIGH); //отпускаем ногу
 return _R;
}
//Пишим в регистры
void WrReg (byte _Adr, byte _Val){
//все аналогично
 digitalWrite(SS,LOW);
 while(digitalRead(MISO)==HIGH);
 delay(1);
 SPI.transfer(_Adr | 0x40); //Пишим адрес и маску бурст записи
 SPI.transfer(_Val); //Пишим значения
 digitalWrite(SS,HIGH);
}
//Читаем с регистра. Только 1 байт пока
byte RdReg(byte _Adr){
  byte _V=0;
  digitalWrite(SS,LOW);
 while(digitalRead(MISO)==HIGH);
 delay(1);
 SPI.transfer(_Adr | 0xC0);
 _V = SPI.transfer(0);
 digitalWrite(SS,HIGH);
 return _V;
}

Странно, я его почти не менял с предыдущего раза. А тут возьми и заработай. Я только не 1 байт стал писать, а МНОГО!

Adekamer
Offline
Зарегистрирован: 13.02.2013

можно узнать чем все закончилось ?

 

relyt
Offline
Зарегистрирован: 11.03.2017

Спасибо за код, помог начать разбираться с таким же устройством. Появились вопросы:

- У CC1101 согласно документации 47 регистров для конфигурирования (address 0 to address 0x2E), вы записываете 50.

- Строки кода 134-136 вообще выполняются когда-либо?

- В цикле перед вызовом WrReg вывод SS  прижимается, внутри WrReg он прижимается еще раз и так же повторно вы его подтягиваете внутри функции и после выхода из нее.

- Вы устанавливаете BURST бит, но при этом используете single access. Смысл?

relyt
Offline
Зарегистрирован: 11.03.2017

Вдруг кому еще интересно - есть резульат! Все попытки пообщаться с устройством через готовую SPI (#include <SPI.h>) библиотеку успехом не увенчались - получаемые данные ничего общего с тем, что ожидалось, не имели. Сегодня решил руками реализовать протокол по даташиту, благо там все элементарно. И вуаля! Девайс отвечает именно теми данными, которые описаны в даташите. Пока реализована только возможность чтения из регистров, но дальше уже все тривиально! Почему не работает стандартный  SPI  посмотрю, как только придет логический анализатор.

//Pins for Arduino NANO
#define CSN 10 //aka SS
#define MOSI 11
#define MISO 12
#define SCK 13

#define READ_SINGLE 0x80
#define WRITE_SINGLE 0x00 // :)

#define SRES 0x30 // Reset chip.
#define SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). If in RX (with CCA):Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround).
#define SCAL 0x33 // Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without setting manual calibration mode (MCSM0.FS_AUTOCAL=0)
#define SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.
#define SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.

byte strobe(byte _cmd, bool _SEND_ONE_BYTE_ONLY) {
&nbsp; digitalWrite(CSN, LOW); &nbsp;
&nbsp; while(digitalRead(MISO) == HIGH); //After pulling CSn, one should always wait for the MISO to go low (CHIP_RDYn), before writing the&nbsp; address&nbsp; header.
&nbsp; for(int _i=7; _i>=0; _i--) {
&nbsp;&nbsp;&nbsp; digitalWrite(MOSI, bitRead(_cmd, _i));
&nbsp;&nbsp;&nbsp; digitalWrite(SCK, HIGH);
&nbsp;&nbsp;&nbsp; digitalWrite(SCK, LOW);
&nbsp; }
&nbsp; digitalWrite(MOSI, LOW);
&nbsp; if (_SEND_ONE_BYTE_ONLY == 1) {
&nbsp;&nbsp;&nbsp; byte _ret = 0;
&nbsp;&nbsp;&nbsp; for(int _i=7; _i>=0; _i--) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; digitalWrite(SCK, HIGH);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitWrite(_ret, _i, digitalRead(MISO));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; digitalWrite(SCK, LOW);
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; digitalWrite(CSN, HIGH);
&nbsp;&nbsp;&nbsp; return _ret;
&nbsp; }
}

byte readSingle(byte _addr) {
&nbsp; return strobe(_addr | READ_SINGLE, 1);
}

byte writeSingle(byte _addr, byte _val) {
&nbsp; strobe(_addr | WRITE_SINGLE, 0);
&nbsp; return strobe(_val, 1);
}

void setup() {
&nbsp; // put your setup code here, to run once:
&nbsp; Serial.begin(115200);
&nbsp; pinMode(CSN, OUTPUT);
&nbsp; pinMode(MOSI, OUTPUT);
&nbsp; pinMode(MISO, INPUT);
&nbsp; pinMode(SCK, OUTPUT);
&nbsp; digitalWrite(CSN, LOW);
&nbsp; digitalWrite(MOSI, LOW);
&nbsp; digitalWrite(SCK, LOW);
&nbsp; digitalWrite(CSN, HIGH);
&nbsp; digitalWrite(CSN, LOW); // Strobe CSn low / high.
&nbsp; delayMicroseconds(10);
&nbsp; digitalWrite(CSN, HIGH); // Hold CSn high for at least 40 μs relative to pulling CSn low
&nbsp; delayMicroseconds(100);
&nbsp; digitalWrite(CSN, LOW); // Pull CSn low and wait for SO to go low (CHIP_RDYn).
&nbsp; while(digitalRead(MISO) == HIGH);
&nbsp; Serial.println("CHIP_RDYn");
&nbsp; Serial.println(strobe(SRES, 1), HEX);//&nbsp; Issue the SRES strobe on the SI line.
&nbsp; // SW reset done.
&nbsp; Serial.println(strobe(SIDLE, 1), HEX);
&nbsp; // TEST
&nbsp; Serial.println(readSingle(0x04), HEX); // Результат 0xD3 - чётко по даташиту!
&nbsp; Serial.println(readSingle(0x03), HEX); // Читаем 0x07
&nbsp; Serial.println(writeSingle(0x03, 15), HEX); //&nbsp; Пишем 15 (0x0F - 1 байт на передачу, 64 на прием)
&nbsp; Serial.println(readSingle(0x03), HEX); //&nbsp; Проверяем, что записалось
}

void loop() {
&nbsp; // put your main code here, to run repeatedly:
&nbsp;
}

UPDATE.

По поводу SPI думаю, что все банально - так делать нельзя просто:

177  SPI.transfer(_Adr | 0x40); //Пишим адрес и маску бурст записи
178  SPI.transfer(_Val); //Пишим значения

Таким образом мы делаем два отдельных посыла, а не один из адреса и значения, поэтому и получаем фигню. Как будет время, перепишу обратно код на использование SPI библиотеки - использование аппаратных возможностей все же лучше, чем софтовая их реализация. Но для понимания работы SPI было интересно. Ваш Капитан Очевидность.

relyt
Offline
Зарегистрирован: 11.03.2017

Короче, я в тупике - сплошной секс слепых в крапиве. Информации куча, но поймать сигнал от беспроводного датчика погодной станции не удается. Все, что я вижу, это скачки RSSI в момент передачи. Прерывание на прием пакета не срабатывает. Оно с какой то радости срабатывает при инициализации. Код ниже. Если кто-то может хоть что-то подсказать, буду рад. И еще - библиотека SPI работать так и отказалась - остался на софт реализации протокола.

// REFERENCE:
// http://www.ti.com.cn/cn/lit/ds/symlink/cc1101.pdf // Low-Power Sub-1GHz RF Transceiver 
// http://www.ti.com/lit/an/swra112b/swra112b.pdf // SPI Access
// http://www.ti.com/lit/an/swra215e/swra215e.pdf // CC110x/CC111xOOK/ASK Register Settings
// http://www.ti.com/lit/an/swra110b/swra110b.pdf // PATABLE Access
// http://www.ti.com/lit/an/swra122c/swra122c.pdf // CC11xx Sensitivity versus Frequency Offset and Crystal Accuracy

//Pins for Arduino NANO
#define CSN 10 //aka SS
#define MOSI 11
#define MISO 12
#define SCK 13
#define INT0 2 // Interrupt pin 2 to GD0

#define READ_SINGLE 0x80
#define WRITE_SINGLE 0x00

#define SRES 0x30 // Reset chip.
#define SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). If in RX (with CCA):Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround). 
#define SCAL 0x33 // Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without setting manual calibration mode (MCSM0.FS_AUTOCAL=0)
#define SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.
#define SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.

// PASTE FROM TI SMARF FR STUDIO APP BELOW // #define @RN@ @<<@0x@AH@ // @Rd@

// Address Config = No address check 
// Base Frequency = 433.919830 
// CRC Autoflush = false 
// CRC Enable = true 
// Carrier Frequency = 433.919830 
// Channel Number = 0 
// Channel Spacing = 25.390625 
// Data Format = Normal mode 
// Data Rate = 4.9963 
// Deviation = 9.521484 
// Device Address = 0 
// Manchester Enable = false 
// Modulation Format = ASK/OOK 
// PA Ramping = false 
// Packet Length = 255 
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word 
// Preamble Count = 4 
// RX Filter BW = 101.562500 
// Sync Word Qualifier Mode = 30/32 sync word bits detected 
// TX Power = 0 
// Whitening = false 
// ---------------------------------------------------
// Packet sniffer stttings for CC1101
// ---------------------------------------------------
#define IOCFG0   0x0002 // GDO0 Output Pin Configuration
#define FIFOTHR  0x0003 // RX FIFO and TX FIFO Thresholds
#define PKTCTRL0 0x0008 // Packet Automation Control
#define FSCTRL1  0x000B // Frequency Synthesizer Control
#define FREQ2    0x000D // Frequency Control Word, High Byte
#define FREQ1    0x000E // Frequency Control Word, Middle Byte
#define FREQ0    0x000F // Frequency Control Word, Low Byte
#define MDMCFG4  0x0010 // Modem Configuration
#define MDMCFG3  0x0011 // Modem Configuration
#define MDMCFG2  0x0012 // Modem Configuration
#define MDMCFG1  0x0013 // Modem Configuration
#define MDMCFG0  0x0014 // Modem Configuration
#define DEVIATN  0x0015 // Modem Deviation Setting
#define MCSM0    0x0018 // Main Radio Control State Machine Configuration
#define FOCCFG   0x0019 // Frequency Offset Compensation Configuration
#define WORCTRL  0x0020 // Wake On Radio Control
#define FREND0   0x0022 // Front End TX Configuration
#define FSCAL3   0x0023 // Frequency Synthesizer Calibration
#define FSCAL2   0x0024 // Frequency Synthesizer Calibration
#define FSCAL1   0x0025 // Frequency Synthesizer Calibration
#define FSCAL0   0x0026 // Frequency Synthesizer Calibration
#define TEST2    0x002C // Various Test Settings
#define TEST1    0x002D // Various Test Settings
#define TEST0    0x002E // Various Test Settings


// END PASTE

#define CHANNR   0x000A // Channel Number 
#define AGCTEST  0x002B 
#define AGCCTRL2 0x001B // AGC Control
#define AGCCTRL1 0x001C // AGC Control
#define AGCCTRL0 0x001D // AGC Control

int channel = 0;
unsigned long start = 0;

byte strobe(byte _cmd, bool _SEND_ONE_BYTE_ONLY) {
  digitalWrite(CSN, LOW);  
  while(digitalRead(MISO) == HIGH); //After pulling CSn, one should always wait for the MISO to go low (CHIP_RDYn), before writing the  address  header.
  for(int _i=7; _i>=0; _i--) { 
    digitalWrite(MOSI, bitRead(_cmd, _i));
    digitalWrite(SCK, HIGH);
    digitalWrite(SCK, LOW);
  }
  digitalWrite(MOSI, LOW);
  if (_SEND_ONE_BYTE_ONLY == 1) {
    byte _ret = 0;
    for(int _i=7; _i>=0; _i--) {
      digitalWrite(SCK, HIGH);
      bitWrite(_ret, _i, digitalRead(MISO));
      digitalWrite(SCK, LOW);
    }
    digitalWrite(CSN, HIGH);
    return _ret; 
  }
}

byte readSingle(byte _addr) {
  return strobe(_addr | READ_SINGLE, 1);
}

byte writeSingle(byte _addr, byte _val) {
  strobe(_addr | WRITE_SINGLE, 0);
  return strobe(_val, 1);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(CSN, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK, OUTPUT);
  pinMode(INT0, INPUT_PULLUP);
  digitalWrite(CSN, LOW);
  digitalWrite(MOSI, LOW);
  digitalWrite(SCK, LOW);
  digitalWrite(CSN, HIGH);
  // do SW reset
  digitalWrite(CSN, LOW); // Strobe CSn low / high. 
  delayMicroseconds(10);
  digitalWrite(CSN, HIGH); // Hold CSn high for at least 40 μs relative to pulling CSn low 
  delayMicroseconds(100);
  digitalWrite(CSN, LOW); // Pull CSn low and wait for SO to go low (CHIP_RDYn).
  while(digitalRead(MISO) == HIGH);
  Serial.println("CHIP_RDYn");
  Serial.println(strobe(SRES, 1), HEX); // Issue the SRES strobe on the SI line.
  // SW reset done.
  Serial.println(strobe(SIDLE, 1), HEX);
  // TEST
  /*
  Serial.println(readSingle(0x04), HEX); // Результат 0xD3 - чётко по даташиту!
  Serial.println(readSingle(0x03), HEX); // Читаем 0x07 
  Serial.println(writeSingle(0x03, 10), HEX); //  Пишем 15 (0x0F - 1 байт на передачу, 64 на прием)
  Serial.println(readSingle(0x03), HEX); //  Проверяем, что записалось
  */
  //Serial.println();
  //Serial.println(strobe(SRX, 1), HEX); // THIS IS WRONG PLACE FOR SRX STROBE IN SKETCH! ...
  //Serial.println(readSingle(0xF5), HEX); // return 0x0D if in RX mode // .. even if here you've got D return

  // PASTE FROM TI SMARF FR STUDIO APP BELOW // writeSingle(@RN@,0x@VH@);@<<@//@Rd@
  
  writeSingle(IOCFG0,0x06);  //GDO0 Output Pin Configuration
  writeSingle(FIFOTHR,0x47); //RX FIFO and TX FIFO Thresholds
  writeSingle(PKTCTRL0,0x05);//Packet Automation Control
  writeSingle(FSCTRL1,0x06); //Frequency Synthesizer Control
  writeSingle(FREQ2,0x10);   //Frequency Control Word, High Byte
  writeSingle(FREQ1,0xB0);   //Frequency Control Word, Middle Byte
  writeSingle(FREQ0,0x71);   //Frequency Control Word, Low Byte
  writeSingle(MDMCFG4,0xC7); //Modem Configuration
  writeSingle(MDMCFG3,0x93); //Modem Configuration
  writeSingle(MDMCFG2,0x33); //Modem Configuration
  writeSingle(MDMCFG1,0x20); //Modem Configuration
  writeSingle(MDMCFG0,0x00); //Modem Configuration
  writeSingle(DEVIATN,0x24); //Modem Deviation Setting
  writeSingle(MCSM0,0x18);   //Main Radio Control State Machine Configuration
  writeSingle(FOCCFG,0x16);  //Frequency Offset Compensation Configuration
  writeSingle(WORCTRL,0xFB); //Wake On Radio Control
  writeSingle(FREND0,0x11);  //Front End TX Configuration
  writeSingle(FSCAL3,0xE9);  //Frequency Synthesizer Calibration
  writeSingle(FSCAL2,0x2A);  //Frequency Synthesizer Calibration
  writeSingle(FSCAL1,0x00);  //Frequency Synthesizer Calibration
  writeSingle(FSCAL0,0x1F);  //Frequency Synthesizer Calibration
  writeSingle(TEST2,0x81);   //Various Test Settings
  writeSingle(TEST1,0x35);   //Various Test Settings
  writeSingle(TEST0,0x09);   //Various Test Settings

  // END PASTE

  // Based on experience using 0x04 00 92 is a good starting point for 100 kHz RX filter BW. // from https://e2e.ti.com/support/wireless_connectivity/low_power_rf_tools/f/15...
  writeSingle(AGCCTRL2, 0x04);
  writeSingle(AGCCTRL1, 0x00);
  writeSingle(AGCCTRL0, 0x92);

  writeSingle(AGCTEST, B10111111); // MINIMUM GAIN! FOR TEST PURPOSES ONLY!
  // AGCTEST[7:6]: LNA1 gain. 00b = max gain, 01b = medium gain, 10b = minimum gain
  // AGCTEST[5:3]: LNA2 gain. 000b = max gain, 111b = min gain
  // AGCTEST[2:0]: Digital gain. 000b = max gain, 111b = min gain

  Serial.println(strobe(SRX, 1), HEX); // THIS IS RIGHT PLACE FOR SRX STROBE!
  Serial.println(readSingle(0xF5), HEX); // return 0x0D if in RX mode // not OK yet - ret 0x08 - CALIBRATE
  delay(1000); // wait... and ask again
  Serial.println(readSingle(0xF5), HEX); // return 0x0D if in RX mode // OK - ret 0x0D - RX
  
  attachInterrupt(0, RX, HIGH);
}

void RX() {
  Serial.println("========================!INT!========================");
  Serial.println(channel);
}

int RSSI_dBm(byte _RSSI) {
  if (_RSSI >= 128) {
    return ((_RSSI-256)/2-74); // If  RSSI_dec ≥ 128 then RSSI_dBm = (RSSI_dec - 256)/2 – RSSI_offset
  }
  else {
    return (_RSSI/2-74); // Else if RSSI_dec < 128 then RSSI_dBm = (RSSI_dec)/2 – RSSI_offset
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  
  
  int p = RSSI_dBm(readSingle(0xF4));
  if ( p > -80) { // значение в -80дБм взято произвольно
    Serial.println(p);
  }
  
  

  if (micros() > 120000000*(channel+1)) { // 2 minutes for scanning
    channel += 1;
    Serial.println(micros());
    Serial.println("NEXT!");
    Serial.println(strobe(SIDLE, 1), HEX);
    Serial.println(writeSingle(CHANNR,channel), HEX);
    Serial.println(strobe(SRX, 1), HEX);
    Serial.println(readSingle(0xF5), HEX); // return 0x0D if in RX mode
    delay(1000);
    Serial.println(readSingle(0xF5), HEX); // return 0x0D if in RX mode
    Serial.println(channel);
  }
  
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

relyt пишет:

По поводу SPI думаю, что все банально - так делать нельзя просто:

177  SPI.transfer(_Adr | 0x40); //Пишим адрес и маску бурст записи
178  SPI.transfer(_Val); //Пишим значения

Таким образом мы делаем два отдельных посыла, а не один из адреса и значения, поэтому и получаем фигню.

Это одно и то же. SPI не предполагает каких либо сигналов между двумя посылами.

Вероятнее всего, Вы просто не угадали с режимом: в SPI масса настроек (скорость, порядок следования битов, фаза синхросигнала, по какому фронту происходит запись и чтение). Коль изучили дэйташит на девайс, сможете понять, какого именно режима он требует, и установить в этот режим SPI контроллер Ардуино.

relyt
Offline
Зарегистрирован: 11.03.2017

Между может и не предполагает, а вот в начале и конце посылки меняется уровень CSN, а этого как раз и не требуется. Настроек у SPI не такая уж и масса, и на первый взгляд там нет того, что требуется. Да и это пока что далеко не первоочередная дазача. Проблема в том, что CC1101  в принципе не хочет делать того, что мне нужно. Вернее, я не знаю, как его заставить - слишком большое количество настроек и нюансов. :(

Пока есть конкретный вопрос - я не понимаю, почему у меня дергается каждый при запуске скетча функция, привязанныя к внешнему прерыванию. В чем причина - не пойму.

relyt
Offline
Зарегистрирован: 11.03.2017

Покурив даташиты (все ссылки на найденную литературу по CC1101  можной найти в самом начале скатча), был найден режим синхронной передачи данных, который выдает сырые полученные данные. Так как данные из эфира он получает постоянно - эфир зашумлен, был сделан своебразный фильтр по уровню принемаемого сигнала - учитывать уровень не менее, чем -60дБм. Значение чисто эмпирическое. Но фигня в том, что данные вылупляются со скоростью 500кбод. Это значение взято с потолка, так как неизвестен ни тип модуляции, ни символьная скорость передачи, ни длина посылов, ни, тем более, используемый протокол. Какая именно используется скорость передачи буду как-то выяснять эксперементально. Без этого пытаться расшифровать полученные данные бесполезно.  Код ниже, опять же - принимаются любые мысли по тому, как упростить задачу.

// REFERENCE:
// http://www.ti.com.cn/cn/lit/ds/symlink/cc1101.pdf // Low-Power Sub-1GHz RF Transceiver 
// http://www.ti.com/lit/an/swra112b/swra112b.pdf // SPI Access
// http://www.ti.com/lit/an/swra215e/swra215e.pdf // CC110x/CC111xOOK/ASK Register Settings
// http://www.ti.com/lit/an/swra110b/swra110b.pdf // PATABLE Access
// http://www.ti.com/lit/an/swra122c/swra122c.pdf // CC11xx Sensitivity versus Frequency Offset and Crystal Accuracy
// http://www.ti.com/lit/an/swra359a/swra359a.pdf // Continuous Data Streaming Applications – Using Serial Synchronous Mode in CC110x and CC2500 Devices
// http://www.ti.com/lit/an/swra316a/swra316a.pdf // Asynchronous Serial Mode for CC1110Fx and CC2510Fx

//Pins for Arduino NANO
#define CSN 10 //aka SS
#define MOSI 11
#define MISO 12
#define SCK 13
#define SERIAL_DATA 2 // Interrupt pin 2 to GDO0 // SERIAL DATA
#define SERIAL_CLOCK 3 // Interrupt pin to GDO1 // SERIAL CLOCK

#define READ_SINGLE 0x80
#define WRITE_SINGLE 0x00

#define SRES 0x30 // Reset chip.
#define SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). If in RX (with CCA):Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround). 
#define SCAL 0x33 // Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without setting manual calibration mode (MCSM0.FS_AUTOCAL=0)
#define SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.
#define SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.
#define MARCSTATE 0xF5 // Main Radio Control State Machine State

// PASTE FROM TI SMARF FR STUDIO APP BELOW // #define @RN@ @<<@0x@AH@ // @Rd@

// Address Config = No address check 
// Base Frequency = 433.919830 
// CRC Autoflush = false 
// CRC Enable = true 
// Carrier Frequency = 433.919830 
// Channel Number = 0 
// Channel Spacing = 25.390625 
// Data Format = Normal mode 
// Data Rate = 4.9963 
// Deviation = 9.521484 
// Device Address = 0 
// Manchester Enable = false 
// Modulation Format = ASK/OOK 
// PA Ramping = false 
// Packet Length = 255 
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word 
// Preamble Count = 4 
// RX Filter BW = 101.562500 
// Sync Word Qualifier Mode = 30/32 sync word bits detected 
// TX Power = 0 
// Whitening = false 
// ---------------------------------------------------
// Packet sniffer stttings for CC1101
// ---------------------------------------------------
#define IOCFG0   0x0002 // GDO0 Output Pin Configuration
#define FIFOTHR  0x0003 // RX FIFO and TX FIFO Thresholds
#define PKTCTRL0 0x0008 // Packet Automation Control
#define FSCTRL1  0x000B // Frequency Synthesizer Control
#define FREQ2    0x000D // Frequency Control Word, High Byte
#define FREQ1    0x000E // Frequency Control Word, Middle Byte
#define FREQ0    0x000F // Frequency Control Word, Low Byte
#define MDMCFG4  0x0010 // Modem Configuration
#define MDMCFG3  0x0011 // Modem Configuration
#define MDMCFG2  0x0012 // Modem Configuration
#define MDMCFG1  0x0013 // Modem Configuration
#define MDMCFG0  0x0014 // Modem Configuration
#define DEVIATN  0x0015 // Modem Deviation Setting
#define MCSM0    0x0018 // Main Radio Control State Machine Configuration
#define FOCCFG   0x0019 // Frequency Offset Compensation Configuration
#define WORCTRL  0x0020 // Wake On Radio Control
#define FREND0   0x0022 // Front End TX Configuration
#define FSCAL3   0x0023 // Frequency Synthesizer Calibration
#define FSCAL2   0x0024 // Frequency Synthesizer Calibration
#define FSCAL1   0x0025 // Frequency Synthesizer Calibration
#define FSCAL0   0x0026 // Frequency Synthesizer Calibration
#define TEST2    0x002C // Various Test Settings
#define TEST1    0x002D // Various Test Settings
#define TEST0    0x002E // Various Test Settings


// END PASTE

#define CHANNR   0x000A // Channel Number 
#define AGCTEST  0x002B 
#define AGCCTRL2 0x001B // AGC Control
#define AGCCTRL1 0x001C // AGC Control
#define AGCCTRL0 0x001D // AGC Control
#define IOCFG1   0x0001 // GDO0 Output Pin Configuration
#define IOCFG2   0x0000 // GDO2 Output Pin Configuration 

int channel = 0;

byte strobe(byte _cmd, bool _SEND_ONE_BYTE_ONLY) {
  digitalWrite(CSN, LOW);  
  while(digitalRead(MISO) == HIGH); //After pulling CSn, one should always wait for the MISO to go low (CHIP_RDYn), before writing the  address  header.
  for(int _i=7; _i>=0; _i--) { 
    digitalWrite(MOSI, bitRead(_cmd, _i));
    digitalWrite(SCK, HIGH);
    digitalWrite(SCK, LOW);
  }
  digitalWrite(MOSI, LOW);
  if (_SEND_ONE_BYTE_ONLY == 1) {
    byte _ret = 0;
    for(int _i=7; _i>=0; _i--) {
      digitalWrite(SCK, HIGH);
      bitWrite(_ret, _i, digitalRead(MISO));
      digitalWrite(SCK, LOW);
    }
    digitalWrite(CSN, HIGH);
    return _ret; 
  }
}

byte readSingle(byte _addr) {
  return strobe(_addr | READ_SINGLE, 1);
}

byte writeSingle(byte _addr, byte _val) {
  strobe(_addr | WRITE_SINGLE, 0);
  return strobe(_val, 1);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(CSN, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK, OUTPUT);
  pinMode(INT0, INPUT);
  pinMode(INT1, INPUT);
  digitalWrite(CSN, LOW);
  digitalWrite(MOSI, LOW);
  digitalWrite(SCK, LOW);
  digitalWrite(CSN, HIGH);
  // do SW reset
  digitalWrite(CSN, LOW); // Strobe CSn low / high. 
  delayMicroseconds(10);
  digitalWrite(CSN, HIGH); // Hold CSn high for at least 40 μs relative to pulling CSn low 
  delayMicroseconds(100);
  digitalWrite(CSN, LOW); // Pull CSn low and wait for SO to go low (CHIP_RDYn).
  while(digitalRead(MISO) == HIGH);
  Serial.println("CHIP_RDYn");
  Serial.println(strobe(SRES, 1), HEX); // Issue the SRES strobe on the SI line.
  // SW reset done.
  Serial.println(strobe(SIDLE, 1), HEX);
  // TEST
  /*
  Serial.println(readSingle(0x04), HEX); // Результат 0xD3 - чётко по даташиту!
  Serial.println(readSingle(0x03), HEX); // Читаем 0x07 
  Serial.println(writeSingle(0x03, 10), HEX); //  Пишем 15 (0x0F - 1 байт на передачу, 64 на прием)
  Serial.println(readSingle(0x03), HEX); //  Проверяем, что записалось
  */
  //Serial.println();
  //Serial.println(strobe(SRX, 1), HEX); // THIS IS WRONG PLACE FOR SRX STROBE IN SKETCH! ...
  //Serial.println(readSingle(0xF5), HEX); // return 0x0D if in RX mode // .. even if here you've got D return

  // PASTE FROM TI SMARF FR STUDIO APP BELOW // writeSingle(@RN@,0x@VH@);@<<@//@Rd@
  
  writeSingle(IOCFG0,0x0C);  //GDO0 Output Pin Configuration
  writeSingle(FIFOTHR,0x47); //RX FIFO and TX FIFO Thresholds
  //writeSingle(PKTCTRL0,0x05);//Packet Automation Control
  writeSingle(PKTCTRL0,0x12); // Sync Mode
  writeSingle(FSCTRL1,0x06); //Frequency Synthesizer Control
  writeSingle(FREQ2,0x10);   //Frequency Control Word, High Byte
  writeSingle(FREQ1,0xB0);   //Frequency Control Word, Middle Byte
  writeSingle(FREQ0,0x71);   //Frequency Control Word, Low Byte
  writeSingle(MDMCFG4,0x0E); //Modem Configuration // CHECK IN CONFIG IN MANUAL!
  writeSingle(MDMCFG3,0x3B); //Modem Configuration // CHECK IN CONFIG IN MANUAL!
  writeSingle(MDMCFG2,0x70); //Modem Configuration // CHECK IN CONFIG IN MANUAL!
  writeSingle(MDMCFG1,0x42); //Modem Configuration // CHECK IN CONFIG IN MANUAL!
  writeSingle(MDMCFG0,0xF8); //Modem Configuration // CHECK IN CONFIG IN MANUAL!
  writeSingle(DEVIATN,0x00); //Modem Deviation Setting
  writeSingle(MCSM0,0x18);   //Main Radio Control State Machine Configuration
  writeSingle(FOCCFG,0x16);  //Frequency Offset Compensation Configuration
  writeSingle(WORCTRL,0xFB); //Wake On Radio Control
  writeSingle(FREND0,0x10);  //Front End TX Configuration
  writeSingle(FSCAL3,0xE9);  //Frequency Synthesizer Calibration
  writeSingle(FSCAL2,0x2A);  //Frequency Synthesizer Calibration
  writeSingle(FSCAL1,0x00);  //Frequency Synthesizer Calibration
  writeSingle(FSCAL0,0x1F);  //Frequency Synthesizer Calibration
  writeSingle(TEST2,0x81);   //Various Test Settings
  writeSingle(TEST1,0x35);   //Various Test Settings
  writeSingle(TEST0,0x09);   //Various Test Settings

  // END PASTE

  writeSingle(IOCFG2,0x0B);
  writeSingle(IOCFG1,0x2E);
  // Based on experience using 0x04 00 92 is a good starting point for 100 kHz RX filter BW. // from https://e2e.ti.com/support/wireless_connectivity/low_power_rf_tools/f/155/t/294295
  writeSingle(AGCCTRL2, 0xC7);
  writeSingle(AGCCTRL1, 0x00);
  writeSingle(AGCCTRL0, 0xB0);

  writeSingle(AGCTEST, B10111111); // MINIMUM GAIN! FOR TEST PURPOSES ONLY!
  // AGCTEST[7:6]: LNA1 gain. 00b = max gain, 01b = medium gain, 10b = minimum gain
  // AGCTEST[5:3]: LNA2 gain. 000b = max gain, 111b = min gain
  // AGCTEST[2:0]: Digital gain. 000b = max gain, 111b = min gain

  Serial.println(strobe(SRX, 1), HEX); // THIS IS RIGHT PLACE FOR SRX STROBE!
  while (readSingle(MARCSTATE) != 0x0D); // Wait for radio to enter RX state
  Serial.println("RX mode");

  attachInterrupt(1, getDataState, HIGH);
}

void getDataState() {
  if (RSSI_dBm(readSingle(0xF4)) > -60) {
    Serial.println(digitalRead(SERIAL_DATA)); 
  }
}

int RSSI_dBm(byte _RSSI) {
  if (_RSSI >= 128) {
    return ((_RSSI-256)/2-74); // If  RSSI_dec ≥ 128 then RSSI_dBm = (RSSI_dec - 256)/2 – RSSI_offset
  }
  else {
    return (_RSSI/2-74); // Else if RSSI_dec < 128 then RSSI_dBm = (RSSI_dec)/2 – RSSI_offset
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  /*
  if (micros() > 120000000*(channel+1)) { // 2 minutes for scanning
    channel += 1;
    Serial.println(micros());
    Serial.println("NEXT!");
    Serial.println(strobe(SIDLE, 1), HEX);
    Serial.println(writeSingle(CHANNR,channel), HEX);
    Serial.println(strobe(SIDLE, 1), HEX);
    Serial.println(strobe(SRX, 1), HEX);
    while (readSingle(MARCSTATE) != 0x0D); // Wait for radio to enter RX state
    Serial.println("RX mode");
    Serial.println(channel);
  }
  */
}

UPD. Метод научного тыка - так себе. Стоило утащить датчик на свое место на балкон, как фильтр в -60 отсек полезный сигнал, а повышение чуствительности приводит к тому, что идет постоянный прием мусора. Надо что-то с этим делать.. А вот что?....

russo
Offline
Зарегистрирован: 20.11.2014

Чтобы боле менее чтото понять в данных сделайте вывод на ногу GPIO2 например, там уже подключаете логанализатор и расшифровываете посылки помех.

Если вы сами не знаете что принимать поэтому такой результат.

 

relyt
Offline
Зарегистрирован: 11.03.2017

С логическим анализатором все стало еще хуже.. )))) Разобрал датчик погодной станции, прицепился к пину data и прицепился к пинам GDO0 и GDO2 девайса.

Наблюдаю следующую картину:

0 - DATA передатчика

1 - GDO2 - Serial Clock CC1101

2 - GDO0 - Serial Data CC1101

Что то я вообще корелляции не наблюдаю.. Кто в  лес, а кто по дрова.. 

russo
Offline
Зарегистрирован: 20.11.2014

Код инициализации выложите СС1101

какая частота и модуляция? Там у СС1101 может быть кварц стоять не точный, поэтому возможны сдвиги по частоте. Нужен приемник для проверки http://phreakerclub.com/1394

http://phreakerclub.com/forum/showthread.php?t=56

 

relyt
Offline
Зарегистрирован: 11.03.2017

Привет! В статье написаны вроде бы очевидные вещи, которые повторяют все из начала даташита девайса. Мне только неясно, откуда автор взял, что "Самое главное что регистры нужно записывать в порядке выдаваемом этой программой, а не как следовало бы из человеческой логики, начиная с нулевого))" - я такую инфу в даташите не видел, а если еще участь, что автор пишет "Задержки взял заведомо очень большие чтоб не читать мануал))" - то есть большая вероятность, что он ошибается.

Мой код можно найти выше в ветке в моих сообшениях. У меня задача just for fun поймать сигнал от погодной станции. Какая частота и модуляция - доподлинно неизвестно. Частота - в районе 433МГц, вчера по косвенным признакам выяснил, что модуляция ASK/OOK. Осталось выяснить символьную скорость, какие значения бит синхронизации и пр. Всеволновый приемник был заказан уже, - жду))). Оптимизм не теряю, думаю, что рано или поздно я эту хрень дожму! ))))