Работа с SPI

Nonsens
Offline
Зарегистрирован: 19.09.2013

1) Поясните пожалуйста физический смысл " фазы синхронизиции (CPHA)" в функции  SPI.setDataMode библиотеки SPI.

2) Какой режим выбрать для модуля NRF24L01  для функции SPI.setDataMode  ?

3) Согласно описанию "функция  SPI.transfer()  Передает один байт по шине SPI, используется как для прием, так и для передачи данных", то есть ведущее устройство посылает байт  в буфер передачи (есть такой в функции?) и одновременно считывает байт из буфера приема? В связи с этим :

===3.1) Как распознать ситуацию когда буфер приема пуст?  Обычно в Си возвращаемое значение -1, а  как в Ардуино?  ===3.2) Как корректно поступить, если передавать в SPI ничего не требуется, а читать принятое нужно ?

 

 

 

 

maksim
Offline
Зарегистрирован: 12.02.2012

1.

 

2. 

SPI.setDataMode(SPI_MODE0);

 

3.1

      Обычно это NULL. Чем СИ отличается от "Ардуино"? Никак, "буфер" - это регистр размером в 1 байт.

 

3.2 

byte buf = SPI.transfer(0xff);

 

axill
Offline
Зарегистрирован: 05.09.2011

Nonsens пишет:

 Как корректно поступить, если передавать в SPI ничего не требуется, а читать принятое нужно ?

ну если так то ведомое устройство должно поддерживать режим передачи "ничего", что то типа пустой команды например

SPI работает только сразу на две стороны - прием и сразу передача, но бывают устройства (например сдвиговые ригистры) у которых либо вход либо выход не подключается к МК и например когда мы записываем данные 74HC595 на входе мы получаем никому не нужный муссор который просто игнорируем

Nonsens
Offline
Зарегистрирован: 19.09.2013

спасибо ответившим, ардуино только начал изучать, поэтому не обижайтесь пожалуйста на подробные распросы, мне нужно это знать

maksim пишет:
2. SPI.setDataMode(SPI_MODE0);

3.1       Обычно это NULL. Чем СИ отличается от "Ардуино"? Никак, "буфер" - это регистр размером в 1 байт.

3.2  byte buf = SPI.transfer(0xff);

3. Если не секрет, из какого документа Nordic взяли режим SPI_MODE0 ?

3.1 NULL определен в ардуино как 0L  или  -1L ?

3.2 однако  байт 0xff наряду с другими значениями также используется для передачи информации, SPI.transfer(0xff); как быть ? PS: описание функций http://arduino.ru/Reference/Library/SPI/setDataMode не слишком подробное, где посмотреть расширенное ?

axill пишет:
Nonsens пишет:
Как корректно поступить, если передавать в SPI ничего не требуется, а читать принятое нужно ?
ну если так то ведомое устройство должно поддерживать режим передачи "ничего", что то типа пустой команды например
пока не вижу такой пустой команды у NRF24L01 (ведомое устройство)

Можете плодсказать такую команду?

 

 

 

axill
Offline
Зарегистрирован: 05.09.2011

Nonsens пишет:

Можете плодсказать такую команду?

кто сказал, что она там должна быть? используйте готовую библиотеку для NRF24 или читайте даташит на этот чип, там есть ответы на все вопросы

maksim
Offline
Зарегистрирован: 12.02.2012

Кстати, у NRF24 есть такая команда:

#define NOP 0xFF

И еще 0xFF это и есть -1 для signed byte, char.

Nonsens
Offline
Зарегистрирован: 19.09.2013

maksim пишет:
Кстати, у NRF24 есть такая команда:

#define NOP 0xFF 

И еще 0xFF это и есть -1 для signed byte, char.

oxFF тоже нужен как данные,  что делать?

 

axill пишет:
Nonsens пишет:
Можете плодсказать такую команду?

кто сказал, что она там должна быть? используйте готовую библиотеку для NRF24 или читайте даташит на этот чип, там есть ответы на все вопросы

не смог найти эту библиотеку, дайте пожалуйста ссылку

maksim
Offline
Зарегистрирован: 12.02.2012

Nonsens пишет:

oxFF тоже нужен как данные,  что делать?

вешаться

Nonsens пишет:

не смог найти эту библиотеку, дайте пожалуйста ссылку

https://github.com/maniacbug/RF24/

trembo
trembo аватар
Онлайн
Зарегистрирован: 08.04.2011

Nonsens пишет:

oxFF тоже нужен как данные,  что делать?

Пошлите 2 байта:

0xFE и 0x00  означает 0xFE

0xFE и 0x01  означает 0xFF

Простое сложение:  если 0xFE суммируем со следующим байтом и получаем нужный результат

Nonsens
Offline
Зарегистрирован: 19.09.2013

там несколько веток (branch), руководствоваться "master" ?

прочел здесь http://avrproject.ru/publ/kak_podkljuchit/radiomoduli_nrf24l01/2-1-0-92

что nrf24l01 лояльна к 5В на входах , а в другом форуме пишут нельзя подавать 5В, может сделать такой делитель?   R1/(R1+R2)=0,66;  5В*0,66=3,31В

 

 

 

 

Nonsens
Offline
Зарегистрирован: 19.09.2013

trembo пишет:
Nonsens пишет:
oxFF тоже нужен как данные,  что делать?

Пошлите 2 байта:

0xFE и 0x00  означает 0xFE

0xFE и 0x01  означает 0xFF

Простое сложение:  если 0xFE суммируем со следующим байтом и получаем нужный результат

но потеря любого байта не будет обнаружена и напрочь сбивает дальнейший обмен

axill
Offline
Зарегистрирован: 05.09.2011

На форуме несколько тем про NRF24. Практически на все ваши вопросы включая те которые еще не заданы есть ответы. Вы бы их прочитали прежде чем задавать вопросы.

делители никакие не нужны

Nonsens
Offline
Зарегистрирован: 19.09.2013

axill пишет:
На форуме несколько тем про NRF24. Практически на все ваши вопросы включая те которые еще не заданы есть ответы. Вы бы их прочитали прежде чем задавать вопросы.

делители никакие не нужны

1) почитаю, я правильно понял, что из-за особенностей SPI (одновременное чтение и запись) NRF24 при любом считывании будет еще и передавать данные?

2) ok

trembo
trembo аватар
Онлайн
Зарегистрирован: 08.04.2011

Nonsens пишет:

но потеря любого байта не будет обнаружена и напрочь сбивает дальнейший обмен

NRF24   не теряет байты!!!!!!!!!!!!!!!!!! Ни одного!!!!!!!!!!!!!!!

Это не 433 МГц с его простотой...

А если потеряет- это будет обнаружено!!!!!!!!!!!!!

 

Nonsens
Offline
Зарегистрирован: 19.09.2013

trembo пишет:
NRF24   не теряет байты!!!!!!!!!!!!!!!!!! Ни одного!!!!!!!!!!!!!!!  Это не 433 МГц с его простотой...  А если потеряет- это будет обнаружено!!!!!!!!!!!!!

да, согласен,  2,4G не сравним с 433 М, да у NRF24 есть протокол коррекции ошибок и повторов передачи, но время для повтора и длительность помех во времени могут соотноситься по разному  и утверждать "ни одного" я бы не стал. Если будет обнаружено, но не исправлено, это и сесть потеря. Тем, кому нужна более высокая надежность, можно использовать надстройки к этому протоколу, формировать данные в пакеты, считать контрольные суммы и отбрасывать битые. Например, как в modbus.

 

PS: ищу простой проект на NRF24L01, который хочу повторить как начинающий

 

maksim
Offline
Зарегистрирован: 12.02.2012

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

Nonsens пишет:

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

Все это реализовано хардово в NRF24L01.

trembo
trembo аватар
Онлайн
Зарегистрирован: 08.04.2011

Please!

Плохо помню, давно это было, но добавлял LCD keypad shield и бегал по дому смотрел.

Питал клиента с двух 18650 в касетте

Дальность так-себе, в прямой видимости приемлема.

Через пару-тройку стен-перекрытий (дерево-регипс) надо ориентировать приёмопередатчик.

 

server.ino

/**
 * An Mirf example which copies back the data it recives.
 *
 * Pins:
 * Hardware SPI:
 * MISO -> 12
 * MOSI -> 11
 * SCK -> 13
 *
 * Configurable:
 * CE -> 8 15
 * CSN -> 7 16
 *
 */

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

void setup(){
  Serial.begin(9600);
  
  /*
   * Set the SPI Driver.
   */
  Mirf.csnPin = 16;
  Mirf.cePin = 15;
  Mirf.spi = &MirfHardwareSpi;
  
  /*
   * Setup pins / SPI.
   */
   
  Mirf.init();
  
  /*pin
   * Configure reciving address.
   */
   
  Mirf.setRADDR((byte *)"serv1");
  
  /*
   * Set the payload length to sizeof(unsigned long) the
   * return type of millis().
   *
   * NB: payload on client and server must be the same.
   */
   
  Mirf.payload = sizeof(unsigned long);
  
  /*
   * Write channel and payload config then power up reciver.
   */
   
  Mirf.config();
  
  // trembo Set to 1Mbps 0x07 2Mbps 0x0F 
  //byte rf_setup = 0x0F;
  //Mirf.writeRegister( RF_SETUP, &rf_setup, sizeof(rf_setup) );
 
 
  Serial.println("Listening..."); 
}

void loop(){
  /*
   * A buffer to store the data.
   */
   
  byte data[Mirf.payload];
  
  /*
   * If a packet has been recived.
   *
   * isSending also restores listening mode when it 
   * transitions from true to false.
   */
   
  if(!Mirf.isSending() && Mirf.dataReady()){
    Serial.println("Got packet");
    
    /*
     * Get load the packet into the buffer.
     */
     
    Mirf.getData(data);
    
    /*
     * Set the send address.
     */
     
     
    Mirf.setTADDR((byte *)"clie1");
    
    /*
     * Send the data back to the client.
     */
     
    Mirf.send(data);
    
    /*
     * Wait untill sending has finished
     *
     * NB: isSending returns the chip to receving after returning true.
     */
      
    Serial.println("Reply sent.");
  }
}

client.ino

/**
 * A Mirf example to test the latency between two Ardunio.
 *
 * Pins:
 * Hardware SPI:
 * MISO -> 12
 * MOSI -> 11
 * SCK -> 13
 *
 * Configurable:
 * CE ->15 PIN
 * CSN ->16 PIN
 *
 * Note: To see best case latency comment out all Serial.println
 * statements not displaying the result and load 
 * 'ping_server_interupt' on the server.
 */

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
#define LCDPWMpin  10  //LCD backlight


void setup(){
  //pinMode(LCDPWMpin,OUTPUT);
  analogWrite(LCDPWMpin,28);
  //digitalWrite(LCDPWMpin,HIGH);
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("   Waiting ... ");
  /*
   * Setup pins / SPI.
   */
   
  /* To change CE / CSN Pins:
   * 
   * Mirf.csnPin = 16;
   * Mirf.cePin = 15;
   */
   
  /*
  Mirf.cePin = 7;
  Mirf.csnPin = 8;
  */
  Mirf.csnPin = 16;
  Mirf.cePin = 15;
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  
  /*
   * Configure reciving address.
   */
   
  Mirf.setRADDR((byte *)"clie1");
  
  /*
   * Set the payload length to sizeof(unsigned long) the
   * return type of millis().
   *
   * NB: payload on client and server must be the same.
   */
   
  Mirf.payload = sizeof(unsigned long);
  
  /*
   * Write channel and payload config then power up reciver.
   */
   
  /*
   * To change channel:
   * 
   * Mirf.channel = 10;
   *
   * NB: Make sure channel is legal in your area.
   */
   
  Mirf.config();
  
   // trembo Set to 1Mbps 0x07 2Mbps 0x0F 
  //byte rf_setup = 0x0F;
  //Mirf.writeRegister( RF_SETUP, &rf_setup, sizeof(rf_setup) );
 
  
  Serial.println("Beginning ... "); 
}

void loop(){
  analogWrite(LCDPWMpin,28);
  unsigned long time = millis();
  
  Mirf.setTADDR((byte *)"serv1");
  
  Mirf.send((byte *)&time);
  
  while(Mirf.isSending()){
  }
  Serial.print("Finished sending");
Serial.print("     ");
  delay(10);
  while(!Mirf.dataReady()){
    //Serial.println("Waiting");
    if ( ( millis() - time ) > 1000 ) {
      Serial.println("Timeout on response from server!");
      return;
    }
  }
  
  Mirf.getData((byte *) &time);
  
  unsigned long pingtime=(millis() - time);
  Serial.print("Ping: ");
  
  
 // Serial.println((millis() - time));
 Serial.println(pingtime);
  lcd.clear();
  lcd.print("Ping: ");
  //lcd.print((millis() - time), DEC); 
  lcd.print((pingtime), DEC); 
  lcd.print("  ms ");
  
   lcd.setCursor(0,1);
   lcd.print(" Count ");
  lcd.setCursor(10,1);
    lcd.print(millis()/1000);
    analogWrite(LCDPWMpin,28);
  delay(1000);
  lcd.clear();
}