Ajout initial depuis le projet sonde
This commit is contained in:
parent
a75b521dce
commit
410d7b7395
5 changed files with 575 additions and 0 deletions
125
nRF24L01.h
Normal file
125
nRF24L01.h
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use, copy,
|
||||||
|
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Memory Map */
|
||||||
|
#define CONFIG 0x00
|
||||||
|
#define EN_AA 0x01
|
||||||
|
#define EN_RXADDR 0x02
|
||||||
|
#define SETUP_AW 0x03
|
||||||
|
#define SETUP_RETR 0x04
|
||||||
|
#define RF_CH 0x05
|
||||||
|
#define RF_SETUP 0x06
|
||||||
|
#define STATUS 0x07
|
||||||
|
#define OBSERVE_TX 0x08
|
||||||
|
#define CD 0x09
|
||||||
|
#define RX_ADDR_P0 0x0A
|
||||||
|
#define RX_ADDR_P1 0x0B
|
||||||
|
#define RX_ADDR_P2 0x0C
|
||||||
|
#define RX_ADDR_P3 0x0D
|
||||||
|
#define RX_ADDR_P4 0x0E
|
||||||
|
#define RX_ADDR_P5 0x0F
|
||||||
|
#define TX_ADDR 0x10
|
||||||
|
#define RX_PW_P0 0x11
|
||||||
|
#define RX_PW_P1 0x12
|
||||||
|
#define RX_PW_P2 0x13
|
||||||
|
#define RX_PW_P3 0x14
|
||||||
|
#define RX_PW_P4 0x15
|
||||||
|
#define RX_PW_P5 0x16
|
||||||
|
#define FIFO_STATUS 0x17
|
||||||
|
#define DYNPD 0x1C
|
||||||
|
#define FEATURE 0x1D
|
||||||
|
|
||||||
|
/* Bit Mnemonics */
|
||||||
|
#define MASK_RX_DR 6
|
||||||
|
#define MASK_TX_DS 5
|
||||||
|
#define MASK_MAX_RT 4
|
||||||
|
#define EN_CRC 3
|
||||||
|
#define CRCO 2
|
||||||
|
#define PWR_UP 1
|
||||||
|
#define PRIM_RX 0
|
||||||
|
#define ENAA_P5 5
|
||||||
|
#define ENAA_P4 4
|
||||||
|
#define ENAA_P3 3
|
||||||
|
#define ENAA_P2 2
|
||||||
|
#define ENAA_P1 1
|
||||||
|
#define ENAA_P0 0
|
||||||
|
#define ERX_P5 5
|
||||||
|
#define ERX_P4 4
|
||||||
|
#define ERX_P3 3
|
||||||
|
#define ERX_P2 2
|
||||||
|
#define ERX_P1 1
|
||||||
|
#define ERX_P0 0
|
||||||
|
#define AW 0
|
||||||
|
#define ARD 4
|
||||||
|
#define ARC 0
|
||||||
|
#define PLL_LOCK 4
|
||||||
|
#define RF_DR 3
|
||||||
|
#define RF_PWR 6
|
||||||
|
#define RX_DR 6
|
||||||
|
#define TX_DS 5
|
||||||
|
#define MAX_RT 4
|
||||||
|
#define RX_P_NO 1
|
||||||
|
#define TX_FULL 0
|
||||||
|
#define PLOS_CNT 4
|
||||||
|
#define ARC_CNT 0
|
||||||
|
#define TX_REUSE 6
|
||||||
|
#define FIFO_FULL 5
|
||||||
|
#define TX_EMPTY 4
|
||||||
|
#define RX_FULL 1
|
||||||
|
#define RX_EMPTY 0
|
||||||
|
#define DPL_P5 5
|
||||||
|
#define DPL_P4 4
|
||||||
|
#define DPL_P3 3
|
||||||
|
#define DPL_P2 2
|
||||||
|
#define DPL_P1 1
|
||||||
|
#define DPL_P0 0
|
||||||
|
#define EN_DPL 2
|
||||||
|
#define EN_ACK_PAY 1
|
||||||
|
#define EN_DYN_ACK 0
|
||||||
|
|
||||||
|
/* Instruction Mnemonics */
|
||||||
|
#define R_REGISTER 0x00
|
||||||
|
#define W_REGISTER 0x20
|
||||||
|
#define REGISTER_MASK 0x1F
|
||||||
|
#define ACTIVATE 0x50
|
||||||
|
#define R_RX_PL_WID 0x60
|
||||||
|
#define R_RX_PAYLOAD 0x61
|
||||||
|
#define W_TX_PAYLOAD 0xA0
|
||||||
|
#define W_ACK_PAYLOAD 0xA8
|
||||||
|
#define FLUSH_TX 0xE1
|
||||||
|
#define FLUSH_RX 0xE2
|
||||||
|
#define REUSE_TX_PL 0xE3
|
||||||
|
#define NOP 0xFF
|
||||||
|
|
||||||
|
/* Non-P omissions */
|
||||||
|
#define LNA_HCURR 0
|
||||||
|
|
||||||
|
/* P model memory Map */
|
||||||
|
#define RPD 0x09
|
||||||
|
|
||||||
|
/* P model bit Mnemonics */
|
||||||
|
#define RF_DR_LOW 5
|
||||||
|
#define RF_DR_HIGH 3
|
||||||
|
#define RF_PWR_LOW 1
|
||||||
|
#define RF_PWR_HIGH 2
|
||||||
270
rf24.c
Normal file
270
rf24.c
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
|
||||||
|
#include "rf24.h"
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t PTX=0;
|
||||||
|
uint8_t rf24_CONFIG = _BV(EN_CRC) | _BV(CRCO);
|
||||||
|
uint8_t rf24_EN_AA = 0x3F; //ENAA_P0 - ENAA_P5
|
||||||
|
uint8_t rf24_EN_RXADDR = _BV(ERX_P0)|_BV(ERX_P1);
|
||||||
|
uint8_t rf24_SETUP_AW = 0x03; // 5 bytes addresses
|
||||||
|
uint8_t rf24_SETUP_RETR = 0x03;
|
||||||
|
uint8_t rf24_RF_CH = 0x02; // Channel
|
||||||
|
uint8_t rf24_RF_SETUP = _BV(RF_DR_HIGH) | _BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH);
|
||||||
|
uint8_t rf24_FEATURE = 0;
|
||||||
|
uint8_t rf24_DYNPD= 0;
|
||||||
|
uint8_t rf24_RX_PW[6] = { 32,32,0,0,0,0 };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void inline rf24_ceHi(){
|
||||||
|
//CE_PIN_PORT |= _BV(CE_PIN_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline rf24_ceLow(){
|
||||||
|
//CE_PIN_PORT &= ~_BV(CE_PIN_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline rf24_csnHi(){
|
||||||
|
CSN_PIN_PORT |= _BV(CSN_PIN_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline rf24_csnLow(){
|
||||||
|
CSN_PIN_PORT &= ~_BV(CSN_PIN_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rf24_init()
|
||||||
|
{
|
||||||
|
//CE_PIN_DDR |= _BV(CE_PIN_BIT);
|
||||||
|
CSN_PIN_DDR |= _BV(CSN_PIN_BIT);
|
||||||
|
|
||||||
|
rf24_ceLow();
|
||||||
|
rf24_csnHi();
|
||||||
|
|
||||||
|
// Initialize spi module
|
||||||
|
spi_begin();
|
||||||
|
_delay_ms(2);
|
||||||
|
rf24_configure();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void inline rf24_transferSync(uint8_t *dataout,uint8_t *datain,uint8_t len){
|
||||||
|
uint8_t i;
|
||||||
|
for(i = 0;i < len;i++){
|
||||||
|
datain[i] = spi_transfer(dataout[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline rf24_transmitSync(uint8_t *dataout,uint8_t len){
|
||||||
|
uint8_t i;
|
||||||
|
for(i = 0;i < len;i++){
|
||||||
|
spi_transfer(dataout[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline rf24_configRegister(uint8_t reg, uint8_t value)
|
||||||
|
// Clocks only one byte into the given MiRF register
|
||||||
|
{
|
||||||
|
rf24_csnLow();
|
||||||
|
spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
|
||||||
|
spi_transfer(value);
|
||||||
|
rf24_csnHi();
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline rf24_readRegister(uint8_t reg, uint8_t * value, uint8_t len)
|
||||||
|
// Reads an array of bytes from the given start position in the MiRF registers.
|
||||||
|
{
|
||||||
|
rf24_csnLow();
|
||||||
|
spi_transfer(R_REGISTER | (REGISTER_MASK & reg));
|
||||||
|
rf24_transferSync(value,value,len);
|
||||||
|
rf24_csnHi();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void inline rf24_writeRegister(uint8_t reg, uint8_t * value, uint8_t len)
|
||||||
|
// Writes an array of bytes into inte the MiRF registers.
|
||||||
|
{
|
||||||
|
rf24_csnLow();
|
||||||
|
spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
|
||||||
|
rf24_transmitSync(value,len);
|
||||||
|
rf24_csnHi();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rf24_getData(uint8_t * data,uint8_t len)
|
||||||
|
{
|
||||||
|
rf24_csnLow(); // Pull down chip select
|
||||||
|
spi_transfer( R_RX_PAYLOAD ); // Send cmd to read rx payload
|
||||||
|
rf24_transferSync(data,data,len); // Read payload
|
||||||
|
rf24_csnHi(); // Pull up chip select
|
||||||
|
// NVI: per product spec, p 67, note c:
|
||||||
|
// "The RX_DR IRQ is asserted by a new packet arrival event. The procedure
|
||||||
|
// for handling this interrupt should be: 1) read payload through SPI,
|
||||||
|
// 2) clear RX_DR IRQ, 3) read FIFO_STATUS to check if there are more
|
||||||
|
// payloads available in RX FIFO, 4) if there are more data in RX FIFO,
|
||||||
|
// repeat from step 1)."
|
||||||
|
// So if we're going to clear RX_DR here, we need to check the RX FIFO
|
||||||
|
// in the dataReady() function
|
||||||
|
rf24_configRegister(STATUS,(1<<RX_DR)); // Reset status register
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t rf24_getDataDL(uint8_t * data,uint8_t len)
|
||||||
|
// Reads payload bytes into data array
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t to_read;
|
||||||
|
|
||||||
|
rf24_csnLow(); // Pull down chip select
|
||||||
|
spi_transfer( R_RX_PL_WID ); // Send cmd to read rx payload len
|
||||||
|
to_read = spi_transfer(0); // Read payload
|
||||||
|
rf24_csnHi(); // Pull up chip select
|
||||||
|
|
||||||
|
if(len>to_read && to_read>0 ) len=to_read;
|
||||||
|
|
||||||
|
rf24_csnLow(); // Pull down chip select
|
||||||
|
spi_transfer( R_RX_PAYLOAD ); // Send cmd to read rx payload
|
||||||
|
rf24_transferSync(data,data,len); // Read payload
|
||||||
|
|
||||||
|
if(to_read!=len){
|
||||||
|
to_read-=len;
|
||||||
|
while((to_read--)>0) // read remaining
|
||||||
|
spi_transfer(0);
|
||||||
|
}
|
||||||
|
rf24_csnHi(); // Pull up chip select
|
||||||
|
// NVI: per product spec, p 67, note c:
|
||||||
|
// "The RX_DR IRQ is asserted by a new packet arrival event. The procedure
|
||||||
|
// for handling this interrupt should be: 1) read payload through SPI,
|
||||||
|
// 2) clear RX_DR IRQ, 3) read FIFO_STATUS to check if there are more
|
||||||
|
// payloads available in RX FIFO, 4) if there are more data in RX FIFO,
|
||||||
|
// repeat from step 1)."
|
||||||
|
// So if we're going to clear RX_DR here, we need to check the RX FIFO
|
||||||
|
// in the dataReady() function
|
||||||
|
rf24_configRegister(STATUS,(1<<RX_DR)); // Reset status register
|
||||||
|
return to_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t inline rf24_dataReady()
|
||||||
|
// Checks if data is available for reading
|
||||||
|
{
|
||||||
|
// See note in getData() function - just checking RX_DR isn't good enough
|
||||||
|
uint8_t status = rf24_getStatus();
|
||||||
|
|
||||||
|
// We can short circuit on RX_DR, but if it's not set, we still need
|
||||||
|
// to check the FIFO for any pending packets
|
||||||
|
if ( status & (1 << RX_DR) ) return 1;
|
||||||
|
return !rf24_rxFifoEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t inline rf24_rxFifoEmpty(){
|
||||||
|
uint8_t fifoStatus;
|
||||||
|
|
||||||
|
rf24_readRegister(FIFO_STATUS,&fifoStatus,sizeof(fifoStatus));
|
||||||
|
return (fifoStatus & (1 << RX_EMPTY));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rf24_send(uint8_t * value,uint8_t len)
|
||||||
|
// Sends a data package to the default address. Be sure to send the correct
|
||||||
|
// amount of bytes as configured as payload on the receiver.
|
||||||
|
{
|
||||||
|
uint8_t status;
|
||||||
|
status = rf24_getStatus();
|
||||||
|
|
||||||
|
if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
|
||||||
|
rf24_configRegister(STATUS,(1 << TX_DS) | (1 << MAX_RT));
|
||||||
|
}
|
||||||
|
|
||||||
|
rf24_ceLow();
|
||||||
|
|
||||||
|
rf24_powerUpTx(); // Set to transmitter mode , Power up
|
||||||
|
|
||||||
|
rf24_csnLow(); // Pull down chip select
|
||||||
|
spi_transfer( FLUSH_TX ); // Write cmd to flush tx fifo
|
||||||
|
rf24_csnHi(); // Pull up chip select
|
||||||
|
|
||||||
|
rf24_csnLow(); // Pull down chip select
|
||||||
|
spi_transfer( W_TX_PAYLOAD ); // Write cmd to write payload
|
||||||
|
rf24_transmitSync(value,len); // Write payload
|
||||||
|
rf24_csnHi(); // Pull up chip select
|
||||||
|
|
||||||
|
rf24_ceHi(); // Start transmission
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t inline rf24_isSending(){
|
||||||
|
uint8_t status;
|
||||||
|
if(PTX){
|
||||||
|
status = rf24_getStatus();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if sending successful (TX_DS) or max retries exceded (MAX_RT).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t inline rf24_getStatus(){
|
||||||
|
uint8_t rv;
|
||||||
|
rf24_csnLow();
|
||||||
|
rv=spi_transfer(NOP);
|
||||||
|
rf24_csnHi();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline rf24_powerUpRx(){
|
||||||
|
PTX = 0;
|
||||||
|
rf24_ceLow();
|
||||||
|
rf24_configRegister(CONFIG, rf24_CONFIG | ( (1<<PWR_UP) | (1<<PRIM_RX) ) );
|
||||||
|
rf24_ceHi();
|
||||||
|
rf24_configRegister(STATUS,(1 << TX_DS) | (1 << MAX_RT));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void inline rf24_flushRx(){
|
||||||
|
rf24_csnLow();
|
||||||
|
spi_transfer( FLUSH_RX );
|
||||||
|
rf24_csnHi();
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline rf24_powerUpTx(){
|
||||||
|
PTX = 1;
|
||||||
|
rf24_configRegister(CONFIG, rf24_CONFIG | ( (1<<PWR_UP) | (0<<PRIM_RX) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline rf24_powerDown(){
|
||||||
|
rf24_ceLow();
|
||||||
|
rf24_configRegister(CONFIG, rf24_CONFIG );
|
||||||
|
}
|
||||||
|
|
||||||
|
void rf24_configure(){
|
||||||
|
uint8_t data;
|
||||||
|
rf24_configRegister(CONFIG,rf24_CONFIG);
|
||||||
|
rf24_configRegister(FEATURE,rf24_FEATURE);
|
||||||
|
// Check Feature register ...
|
||||||
|
rf24_readRegister(FEATURE,&data,1);
|
||||||
|
if(rf24_FEATURE != data){ // ACTIVATE & retry
|
||||||
|
rf24_csnLow();
|
||||||
|
spi_transfer(ACTIVATE);
|
||||||
|
spi_transfer(0x73);
|
||||||
|
rf24_csnHi();
|
||||||
|
rf24_configRegister(FEATURE,rf24_FEATURE);
|
||||||
|
}
|
||||||
|
rf24_configRegister(EN_AA,rf24_EN_AA);
|
||||||
|
rf24_configRegister(EN_RXADDR,rf24_EN_RXADDR);
|
||||||
|
rf24_configRegister(SETUP_AW,rf24_SETUP_AW);
|
||||||
|
rf24_configRegister(SETUP_RETR,rf24_SETUP_RETR);
|
||||||
|
rf24_configRegister(RF_CH,rf24_RF_CH);
|
||||||
|
rf24_configRegister(RF_SETUP,rf24_RF_SETUP);
|
||||||
|
rf24_configRegister(DYNPD,rf24_DYNPD);
|
||||||
|
|
||||||
|
for(int i=0; i<6;i++)
|
||||||
|
rf24_configRegister(RX_PW_P0+i,rf24_RX_PW[i]);
|
||||||
|
|
||||||
|
}
|
||||||
72
rf24.h
Normal file
72
rf24.h
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
#include "nRF24L01.h"
|
||||||
|
#include "spi.h"
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void rf24_init();
|
||||||
|
|
||||||
|
void rf24_configRegister(uint8_t reg, uint8_t value);
|
||||||
|
void rf24_readRegister(uint8_t reg, uint8_t * value, uint8_t len);
|
||||||
|
void rf24_writeRegister(uint8_t reg, uint8_t * value, uint8_t len);
|
||||||
|
|
||||||
|
void rf24_getData(uint8_t * data,uint8_t len);
|
||||||
|
uint8_t rf24_getDataDL(uint8_t * data,uint8_t len);
|
||||||
|
uint8_t rf24_dataReady();
|
||||||
|
uint8_t rf24_rxFifoEmpty();
|
||||||
|
|
||||||
|
|
||||||
|
void rf24_send(uint8_t * value,uint8_t len);
|
||||||
|
uint8_t rf24_isSending();
|
||||||
|
uint8_t rf24_getStatus();
|
||||||
|
|
||||||
|
void rf24_powerUpRx();
|
||||||
|
void rf24_powerUpTx();
|
||||||
|
void rf24_powerDown();
|
||||||
|
void rf24_flushRx();
|
||||||
|
void rf24_configure();
|
||||||
|
|
||||||
|
|
||||||
|
extern uint8_t rf24_CONFIG;
|
||||||
|
extern uint8_t rf24_EN_AA;
|
||||||
|
extern uint8_t rf24_EN_RXADDR;
|
||||||
|
extern uint8_t rf24_SETUP_AW;
|
||||||
|
extern uint8_t rf24_SETUP_RETR;
|
||||||
|
extern uint8_t rf24_RF_CH;
|
||||||
|
extern uint8_t rf24_RF_SETUP;
|
||||||
|
extern uint8_t rf24_FEATURE;
|
||||||
|
extern uint8_t rf24_DYNPD;
|
||||||
|
extern uint8_t rf24_RX_PW[6];
|
||||||
|
|
||||||
|
#if defined (__AVR_ATtiny84__) || defined (__AVR_ATtiny84A__)
|
||||||
|
|
||||||
|
#define CE_PIN_PORT UNDEF
|
||||||
|
#define CE_PIN_DDR UNDEF
|
||||||
|
#define CE_PIN_BIT UNDEF
|
||||||
|
|
||||||
|
#define CSN_PIN_PORT PORTB
|
||||||
|
#define CSN_PIN_DDR DDRB
|
||||||
|
#define CSN_PIN_BIT PB2
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega32U4__)
|
||||||
|
|
||||||
|
#define CE_PIN_PORT PORTD
|
||||||
|
#define CE_PIN_DDR DDRD
|
||||||
|
#define CE_PIN_BIT PD4
|
||||||
|
|
||||||
|
#define CSN_PIN_PORT PORTC
|
||||||
|
#define CSN_PIN_DDR DDRC
|
||||||
|
#define CSN_PIN_BIT PC6
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
79
spi.c
Normal file
79
spi.c
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
#include "spi.h"
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
|
||||||
|
void spi_begin() {
|
||||||
|
#if defined(SPCR)
|
||||||
|
#error to write ...
|
||||||
|
// Set SS to high so a connected chip will be "deselected" by default
|
||||||
|
digitalWrite(SS, HIGH);
|
||||||
|
// When the SS pin is set as OUTPUT, it can be used as
|
||||||
|
// a general purpose output port (it doesn't influence
|
||||||
|
// SPI operations).
|
||||||
|
pinMode(SS, OUTPUT);
|
||||||
|
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
|
||||||
|
// automatically switches to Slave, so the data direction of
|
||||||
|
// the SS pin MUST be kept as OUTPUT.
|
||||||
|
SPCR |= _BV(MSTR);
|
||||||
|
SPCR |= _BV(SPE);
|
||||||
|
// Set direction register for SCK and MOSI pin.
|
||||||
|
// MISO pin automatically overrides to INPUT.
|
||||||
|
// By doing this AFTER enabling SPI, we avoid accidentally
|
||||||
|
// clocking in a single bit since the lines go directly
|
||||||
|
// from "input" to SPI control.
|
||||||
|
// http://code.google.com/p/arduino/issues/detail?id=888
|
||||||
|
pinMode(SCK, OUTPUT);
|
||||||
|
pinMode(MOSI, OUTPUT);
|
||||||
|
#else
|
||||||
|
PRR &= ~(_BV(PRUSI));
|
||||||
|
USICR = _BV(USIWM0);
|
||||||
|
USCK_DDR |= _BV(USCK_BIT); //set the USCK pin as output
|
||||||
|
DO_DDR |= _BV(DO_BIT); //set the DO pin as output
|
||||||
|
DI_DDR &= ~_BV(DI_BIT); //set the DI pin as input
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t spi_transfer(uint8_t b) {
|
||||||
|
#if defined(SPCR)
|
||||||
|
SPDR = b;
|
||||||
|
while (!(SPSR & _BV(SPIF)));
|
||||||
|
return SPDR;
|
||||||
|
#else
|
||||||
|
USIDR = b;
|
||||||
|
USISR = _BV(USIOIF);
|
||||||
|
do {
|
||||||
|
USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
|
||||||
|
// _delay_ms(1);
|
||||||
|
}while ((USISR & _BV(USIOIF)) == 0);
|
||||||
|
return USIDR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_end() {
|
||||||
|
#if defined(SPCR)
|
||||||
|
SPCR &= ~_BV(SPE);
|
||||||
|
#else
|
||||||
|
USICR &= ~(_BV(USIWM1) | _BV(USIWM0));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_setBitOrder(uint8_t bitOrder)
|
||||||
|
{
|
||||||
|
#if defined(SPCR)
|
||||||
|
if(bitOrder == LSBFIRST) {
|
||||||
|
SPCR |= _BV(DORD);
|
||||||
|
} else {
|
||||||
|
SPCR &= ~(_BV(DORD));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_setDataMode(uint8_t mode)
|
||||||
|
{
|
||||||
|
#if defined(SPCR)
|
||||||
|
SPCR = (SPCR & ~SPI_MODE_MASK) | mode;
|
||||||
|
#else
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
29
spi.h
Normal file
29
spi.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef tinySPI_h
|
||||||
|
#define tinySPI_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/atomic.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//SPI data modes
|
||||||
|
#define SPI_MODE0 0x00
|
||||||
|
#define SPI_MODE1 0x04
|
||||||
|
|
||||||
|
void spi_begin(void);
|
||||||
|
void spi_setDataMode(uint8_t spiDataMode);
|
||||||
|
uint8_t spi_transfer(uint8_t spiData);
|
||||||
|
void spi_end(void);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in a new issue