avr codevision 问题在 nRF24L01+ MODULE 中获得确认或 TX_DS 标志

Posted

技术标签:

【中文标题】avr codevision 问题在 nRF24L01+ MODULE 中获得确认或 TX_DS 标志【英文标题】:avr codevision issue getting acknowledge or TX_DS flag in nRF24L01+ MODULE 【发布时间】:2017-01-14 18:49:38 【问题描述】:

我正在尝试使用通过 spi 连接到 atmega8s 的两个 nRF24L01 无线电模块进行通信。

我所能做的就是写一些nRF的寄存器,但是不能发送数据。当我读取无线电状态寄存器时,它返回十进制 14,有时返回 0,有时返回十进制 30。

这是我的 atmega8 代码:

#include <mega8.h>
#include <C:\cvavr\BIN\nRF24L01\nrf24l012.h>
#include <stdio.h>
#include <pcf8576d.h>

#define    _CH 1            // Channel 0..125
#define    _Address_Width 5    // 3..5
#define _Buffer_Size 32 // 1..32


// Declare your global variables here
unsigned char global_var=0;

void NRF24L01_Receive(char Buf[_Buffer_Size]) 
    NRF24L01_CE_HIGH;
    delay_us(130);

    while ((NRF24L01_Get_Status() & _RX_DR) != _RX_DR);

    NRF24L01_CE_LOW;

    NRF24L01_Read_RX_Buf(Buf, _Buffer_Size);
    NRF24L01_Clear_Interrupts();



void NRF24L01_Send(char* Buf) 
    NRF24L01_Write_TX_Buf(Buf, _Buffer_Size);

    NRF24L01_RF_TX();

    while ((NRF24L01_Get_Status() & _TX_DS) != _TX_DS) ;

    NRF24L01_Clear_Interrupts();



// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)

    char buffer[32];
    char state = NRF24L01_Get_Status(); 
    lcd_erase();
    lcd_printf("INT ");
    lcd_print(state);
    if(state==0) NRF24L01_Read_RX_Buf(buffer,32);
    lcd_print(buffer[0]); 
    delay_ms(100);

    NRF24L01_Clear_Interrupts();


// SPI interrupt service routine
interrupt [SPI_STC] void spi_isr(void)







void main(void)

    // Declare your local variables here
    char i;
    unsigned char bffr[5];
    unsigned char Buf[_Buffer_Size];
    unsigned char Data[5]=3,9,5,8,4;
    unsigned char Address_p0[_Address_Width] =  0xf0,0xf0,0xf0,0xf0,0xe1  ; 
    unsigned char Address_p1[_Address_Width] =  0xf0,0xf0,0xf0,0xf0,0xd2  ; 
    unsigned char Address_p2[1]=0xc3;
    unsigned char Address_p3[1]=0xc4;
    unsigned char Address_p4[1]=0xc5;
    unsigned char Address_p5[1]=0xc6;
    spi_int1_init();    
    TWI_init_master();

    delay_ms(300); 
    lcd_erase();
    lcd_printf("start");
    delay_ms(1200);

    NRF24L01_Init(_TX_MODE, _CH, _1Mbps, Address_p0, _Address_Width, _Buffer_Size);
    NRF24L01_WriteReg(W_REGISTER | EN_RXADDR,0x03);
    NRF24L01_Set_RX_Pipe (0,Address_p0,_Address_Width, _Buffer_Size);
    NRF24L01_Set_RX_Pipe (1,Address_p1,_Address_Width, _Buffer_Size); 
    NRF24L01_Set_TX_Address(Address_p0,_Address_Width);
    NRF24L01_Set_RX_Pipe (2,Address_p2,1,0); 
    NRF24L01_Set_RX_Pipe (3,Address_p3,1,0);
    NRF24L01_Set_RX_Pipe (4,Address_p4,1,0);
    NRF24L01_Set_RX_Pipe (5,Address_p5,1,0);
    NRF24L01_WriteReg(W_REGISTER | EN_AA,0X3F);
    NRF24L01_WriteReg(W_REGISTER | EN_RXADDR,0x03);
    NRF24L01_WriteReg(W_REGISTER | RF_CH, 0x0c); 
    NRF24L01_WriteReg(W_REGISTER | RF_SETUP,0X03);
    NRF24L01_WriteReg(W_REGISTER | CONFIG,0X0E);
    NRF24L01_WriteReg(W_REGISTER | SETUP_RETR,0X28);


    global_var = NRF24L01_Get_Status();
    //global_var=SPI(234);
    lcd_erase();
    lcd_print(global_var);
    delay_ms(1000);
    global_var = NRF24L01_ReadReg(CONFIG);
    lcd_erase();
    lcd_print(global_var);
    delay_ms(1000);

    lcd_erase();
    NRF24L01_ReadRegBuf(TX_ADDR,bffr,5);
    for(i=0;i<5;i++)
        lcd_print(bffr[i]);
    delay_ms(1000);

    global_var = NRF24L01_ReadReg(FIFO_STATUS);
    lcd_erase();
    lcd_printf("ffo ");
    lcd_print(global_var);  
    delay_ms(1000);

    NRF24L01_Send(Data);  
    global_var = NRF24L01_Get_Status();
    lcd_erase();
    lcd_print(global_var);  
    delay_ms(1000);

    global_var = NRF24L01_ReadReg(FIFO_STATUS);
    lcd_erase();
    lcd_printf("mioh ");
    lcd_print(global_var);  
    delay_ms(1000);

    while (1);

这是我的 nrf24l012.h

#include <delay.h>
#include <C:\cvavr\BIN\nRF24L01\nrf24l011.h>  


/*
 * SPI pins:
 * MOSI: DDB3
 * MISO: DDB4
 * SCK : DDB5
 * CSN : DDB2
 * CE   : DDB1
 */
 void spi_int1_init(void)
 // Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=Out Bit4=In Bit3=Out Bit2=Out Bit1=In Bit0=In 
DDRB=(0<<DDB7) | (0<<DDB6) | (1<<DDB5) | (0<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=0 Bit4=T Bit3=0 Bit2=0 Bit1=T Bit0=T 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);


// External Interrupt(s) initialization
// INT0: Off
// INT1: On
// INT1 Mode: Falling Edge
GICR|=(1<<INT1) | (0<<INT0);
MCUCR=(1<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
GIFR=(1<<INTF1) | (0<<INTF0);


// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2000.000 kHz
// SPI Clock Phase: Cycle Start
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=(1<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
SPSR=(0<<SPI2X);

// Clear the SPI interrupt flag
#asm
    in   r30,spsr
    in   r30,spdr
#endasm


// Global enable interrupts
#asm("sei")
 

//Function to send and receive data for both master and slave
unsigned char SPI(unsigned char data)


    // Load data into the buffer
    SPDR = data;

    //Wait until transmission complete
    while(!(SPSR & (1<<SPIF) )); 

    SPSR = (1<<SPIF);      
    // Return received data
    return(SPDR);




/* CE is set to output */

#define NRF24L01_CE_OUT       DDRB  |= (1<<DDB1) ;
#define NRF24L01_CE_HIGH      PORTB |= (1<<DDB1) ;
#define NRF24L01_CE_LOW       PORTB &= ~(1<<DDB1);
#define NRF24L01_CSN_HIGH     PORTB |= (1<<DDB2) ;
#define NRF24L01_CSN_LOW      PORTB &= ~(1<<DDB2);

/**
 Read a register

 @param Reg Register to read

 @return Registry Value
*/
char NRF24L01_ReadReg(char Reg) 
    char Result;

    NRF24L01_CSN_LOW;
    SPI(Reg);
    Result = SPI(NOP);    // "NOP"  in here just roles as a dummy data byte  nothing more.
    NRF24L01_CSN_HIGH;

    return Result;


/**
 Returns the STATUS register and then modify a register

 @param Reg Register to change
 @param Value New value

 @return STATUS Register
*/
char NRF24L01_WriteReg(char Reg, char Value) 
    char Result;

    NRF24L01_CSN_LOW;
    Result = SPI(Reg);
    SPI(Value);
    NRF24L01_CSN_HIGH;

    return Result;


/**
 Returns the STATUS register and then read "n" registers

 @param Reg Register to read
 @param Buf Pointer to a buffer
 @param Size Buffer Size

 @return STATUS Register
*/
char NRF24L01_ReadRegBuf(char Reg, char *Buf, int Size) 
    int i;
    char Result;

    NRF24L01_CSN_LOW;
    Result = SPI(Reg);

    for (i = 0; i < Size; i++) 
        Buf[i] = SPI(NOP);
    

    NRF24L01_CSN_HIGH;

    return Result;


/**
 Returns the STATUS register and then write "n" registers

 @param Reg Registers to change
 @param Buf Pointer to a buffer
 @param Size Buffer Size

 @return STATUS Register
*/
char NRF24L01_WriteRegBuf(char Reg, char *Buf, int Size) 
    int i;
    char Result;

    NRF24L01_CSN_LOW;
    Result = SPI(Reg);

    for (i = 0; i < Size; i++) 
        SPI(Buf[i]);
    
    NRF24L01_CSN_HIGH;

    return Result;


/**
 Returns the STATUS register

 @return STATUS Register
*/
char NRF24L01_Get_Status(void) 
    char Result;

    NRF24L01_CSN_LOW;
    Result = SPI(NOP);
    NRF24L01_CSN_HIGH;

    return Result;


/**
 Returns the carrier signal in RX mode (high when detected)

 @return CD
*/
char NRF24L01_Get_CD(void) 
    return (NRF24L01_ReadReg(CD) & 1);


/**
 Select power mode

 @param Mode = _POWER_DOWN, _POWER_UP

 @see _POWER_DOWN
 @see _POWER_UP

*/
void NRF24L01_Set_Power(char Mode) 
    char Result;

    Result = NRF24L01_ReadReg(CONFIG) & 0b01111101; // Read Conf. Reg. AND Clear bit 1 (PWR_UP) and 7 (Reserved)
    NRF24L01_WriteReg(W_REGISTER | CONFIG, Result | Mode);


/**
 Select the radio channel

 @param CH = 0..125

*/
void NRF24L01_Set_CH(char CH) 
    NRF24L01_WriteReg(W_REGISTER | RF_CH, (CH & 0b01111111)); // Clear bit 8


/**
 Select Enhanced ShockBurst ON/OFF

 Disable this functionality to be compatible with nRF2401

 @param Mode = _ShockBurst_ON, _ShockBurst_OFF

 @see _ShockBurst_ON
 @see _ShockBurst_OFF

*/
void NRF24L01_Set_ShockBurst(char Mode) 
    NRF24L01_WriteReg(W_REGISTER | SETUP_RETR, Mode);
    NRF24L01_WriteReg(W_REGISTER | EN_AA, Mode);


/**
 Select the address width

 @param Width = 3..5
*/
void NRF24L01_Set_Address_Width(char Width) 
    NRF24L01_WriteReg(W_REGISTER | SETUP_AW, (Width - 2));  //  orginal was (Width & 3) -2)  but is incorrect


/**
 Select mode receiver or transmitter

 @param Device_Mode = _TX_MODE, _RX_MODE

 @see _TX_MODE
 @see _RX_MODE
*/
void NRF24L01_Set_Device_Mode(char Device_Mode) 
    char Result;

    Result = NRF24L01_ReadReg(CONFIG) & 0b01111110; // Read Conf. Reg. AND Clear bit 0 (PRIM_RX) and 7 (Reserved)
    NRF24L01_WriteReg(W_REGISTER | CONFIG, Result | Device_Mode);


/**
 Enables and configures the pipe receiving the data

 @param PipeNum Number of pipe
 @param Address Address
 @param AddressSize Address size
 @param PayloadSize Buffer size, data receiver

*/
void NRF24L01_Set_RX_Pipe(char PipeNum, char *Address, int AddressSize, char PayloadSize) 
    char Result;

    Result = NRF24L01_ReadReg(EN_RXADDR);
    NRF24L01_WriteReg(W_REGISTER | EN_RXADDR, Result | (1 << PipeNum));

    NRF24L01_WriteReg(W_REGISTER | (RX_PW_P0 + PipeNum), PayloadSize);
    NRF24L01_WriteRegBuf(W_REGISTER | (RX_ADDR_P0 + PipeNum), Address, AddressSize);


/**
 Disable all pipes
*/
void NRF24L01_Disable_All_Pipes(void) 
    NRF24L01_WriteReg(W_REGISTER | EN_RXADDR, 0);



/** Returns the STATUS register and then clear all interrupts
 *
 * @return STATUS Register
 */
char NRF24L01_Clear_Interrupts(void) 
    return NRF24L01_WriteReg(W_REGISTER | STATUS, _RX_DR | _TX_DS | _MAX_RT);


/**
 Sets the direction of transmission

 @param Address Address
 @param Size Address size 3..5

*/
void NRF24L01_Set_TX_Address(char *Address, int Size) 
    NRF24L01_WriteRegBuf(W_REGISTER | TX_ADDR, Address, Size);


/**
 Empty the transmit buffer

*/
void NRF24L01_Flush_TX(void) 
    NRF24L01_CSN_LOW;
    SPI(FLUSH_TX);
    NRF24L01_CSN_HIGH;


/**
 Empty the receive buffer
*/
void NRF24L01_Flush_RX(void) 
    NRF24L01_CSN_LOW;
    SPI(FLUSH_RX);
    NRF24L01_CSN_HIGH;


/**
 Initializes the device
 @param Device_Mode = _TX_MODE, _RX_MODE
 @param CH = 0..125
 @param DataRate = _1Mbps, _2Mbps
 @param Address Address
 @param Address_Width Width direction: 3..5
 @param Size_Payload Data buffer size

 @see _TX_MODE
 @see _RX_MODE
 @see _1Mbps
 @see _2Mbps
*/
void NRF24L01_Init(char Device_Mode, char CH, char DataRate,
        char *Address, char Address_Width, char Size_Payload) 

    NRF24L01_CE_OUT; // Set Port DIR out

    // Enable Enhanced ShockBurst....._ShockBurst_OFF
    NRF24L01_Set_ShockBurst(_ShockBurst_ON);

    // RF output power in TX mode = 0dBm (Max.)
    // Set LNA gain
    NRF24L01_WriteReg(W_REGISTER | RF_SETUP, 0b00000111 | DataRate);

    NRF24L01_Set_Address_Width(Address_Width);

    NRF24L01_Set_RX_Pipe(0, Address, Address_Width, Size_Payload);

    NRF24L01_Set_CH(CH);

    NRF24L01_Set_TX_Address(Address, Address_Width); // Set Transmit address

    // Bits 4..6: Reflect interrupts as active low on the IRQ pin
    // Bit 3: Enable CRC
    // Bit 2: CRC 1 Byte
    // Bit 1: Power Up
    NRF24L01_WriteReg(W_REGISTER | CONFIG, 0b00001010 | Device_Mode);

    delay_us(1500);


/**
 Turn on transmitter, and transmits the data loaded into the buffer
*/
void NRF24L01_RF_TX(void) 
    NRF24L01_CE_LOW;
    NRF24L01_CE_HIGH;
    delay_us(10);
    NRF24L01_CE_LOW;


/**
 Writes the buffer of data transmission

 @param Buf Buffer with data to send
 @param Size Buffer size

*/
void NRF24L01_Write_TX_Buf(char *Buf, int Size) 
    NRF24L01_WriteRegBuf(W_REGISTER | W_TX_PAYLOAD, Buf, Size);


/**
 Read the data reception buffer

 @param Buf Buffer with data received
 @param Size Buffer size

*/
void NRF24L01_Read_RX_Buf(char *Buf, int Size) 
    NRF24L01_ReadRegBuf(R_RX_PAYLOAD, Buf, Size);

我不明白是什么问题.. 请帮帮我谢谢?!

这里是 nrf24l01+.h 定义

/*
 * @author
 * Copyright (C) 2012 Luis R. Hilario http://www.luisdigital.com
 *
 */

// Bits

/**
 * Data Ready RX FIFO interrupt
 */
#define _RX_DR (1<<6)

/**
 * Data Sent TX FIFO interrupt
 */
#define _TX_DS (1<<5)

/**
 * Maximum number of TX retransmits interrupt
 */
#define _MAX_RT (1<<4)

/** Power Down mode
 *
 * Minimal current consumption, SPI can be activated
 *
 * @see NRF24L01_Set_Power(char Mode)
 */
#define _POWER_DOWN    0

/** Power Up mode
 *
 * Standby-I mode
 *
 * @see NRF24L01_Set_Power(char Mode)
 */
#define _POWER_UP    (1<<1)

/** Mode radio transmitter
 *
 * @see NRF24L01_Set_Device_Mode(char Device_Mode)
 * @see NRF24L01_Init(char Device_Mode, char CH, char DataRate,
        char *Address, char Address_Width, char Size_Payload)
 */
#define _TX_MODE    0

/** Mode radio receiver
 *
 * @see NRF24L01_Set_Device_Mode(char Device_Mode)
 * @see NRF24L01_Init(char Device_Mode, char CH, char DataRate,
        char *Address, char Address_Width, char Size_Payload)
 */
#define _RX_MODE    1

/**  Air data rate = 1 Mbps
 *
 *
 * @see NRF24L01_Init(char Device_Mode, char CH, char DataRate,
        char *Address, char Address_Width, char Size_Payload)
 */
#define    _1Mbps    0

/** Air data rate = 2 Mbps
 *
 * @see NRF24L01_Init(char Device_Mode, char CH, char DataRate,
        char *Address, char Address_Width, char Size_Payload)
 */
#define    _2Mbps    (1<<3)

/** Enable ShockBurst

 Automatic Retransmission (Up to 1 Re-Transmit on fail of AA)

 Auto Acknowledgment (data pipe 0)

 @see NRF24L01_Set_ShockBurst(char Mode)
 */
#define _ShockBurst_ON 1

/** Disable ShockBurst
 *
 @see NRF24L01_Set_ShockBurst(char Mode)
 */
#define _ShockBurst_OFF 0


// REGISTERS
#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

// COMMANDS
#define R_REGISTER            0x00
#define W_REGISTER            0x20
#define R_RX_PAYLOAD        0x61
#define W_TX_PAYLOAD        0xA0
#define FLUSH_TX              0xE1
#define FLUSH_RX             0xE2
#define REUSE_TX_PL          0xE3
#define ACTIVATE            0x50
#define R_RX_PL_WID         0x60
#define W_ACK_PAYLOAD        0xA8
#define W_TX_PAYLOAD_NOACK    0x58
#define NOP                 0xFF

/*
 * SPI functions for NRF24L01
 */
char NRF24L01_ReadReg(char Reg);
char NRF24L01_WriteReg(char Reg, char Value);
char NRF24L01_ReadRegBuf(char Reg, char *Buf, int Size);
char NRF24L01_WriteRegBuf(char Reg, char *Buf, int Size);

/*
 * NRF24L01 functions
 */
char NRF24L01_Get_Status(void);
char NRF24L01_Get_CD(void);
void NRF24L01_Set_Power(char Mode);
void NRF24L01_Set_CH(char CH);
void NRF24L01_Set_ShockBurst(char Mode);
void NRF24L01_Set_Address_Width(char Width);
void NRF24L01_Set_Device_Mode(char Device_Mode);
void NRF24L01_Set_RX_Pipe(char PipeNum, char *Address, int AddressSize, char PayloadSize);
void NRF24L01_Disable_All_Pipes(void);
char NRF24L01_Clear_Interrupts(void);
void NRF24L01_Set_TX_Address(char *Address, int Size);
void NRF24L01_Flush_TX(void);
void NRF24L01_Flush_RX(void);
void NRF24L01_Init(char Device_Mode, char CH, char DataRate,
        char *Address, char Address_Width, char Size_Payload);
void NRF24L01_RF_TX(void);
void NRF24L01_Write_TX_Buf(char *Buf, int Size);
void NRF24L01_Read_RX_Buf(char *Buf, int Size);

【问题讨论】:

问题太长,无法回答。它应该尽可能短,并且仍然可以证明问题。此外,您需要说明您希望代码做什么,以及它正在做什么。 在 .h 文件中定义函数是一种不好的风格。它们应该位于 .c 文件中,但这不会导致您的问题。似乎理解状态寄存器所需的一些定义在 nrf24l011.h 中。请将该文件添加到您的问题中。 我添加了 nrf24l011.h 文件..代码将传输数据到另一个处于 rx 模式的 nrf 模块,当 IRQ 引脚上的中断发生时,它会读取状态寄存器 【参考方案1】:

你好朋友们,我成功地得到了它,我能够通过 nrf24l01+ 模块将数据发送到另一个 nrf24l01+ 模块为此我使用 ATMEGA16A 作为 TX 和 ATmega8a 作为 RX(接收器)控制器: 我使用了一些好人编写的此链接中的代码,它运行良好,但我需要更改 som i/o 端口以与接收器模块的 Atmega8 兼容。 当我将我的最后一个代码与这个代码进行比较时,我了解到我更改了 rx 和 tx 地址,并且在此代码中(运行良好)没有任何与模块地址相关的更改并保留其默认值.. 所以我的错是错误地操作地址..

这里是代码的链接效果很好..

更新:当我重新访问我的代码以查看有什么问题时,我了解整个问题来自 nrf24l01.h 文件,该文件错误地声明了一个函数,它使用 W_REGISTER 发送 W_TX_PAYLOAD ORing,而 nrf 中不存在这样的地址,所以整个过程是搞错了。。 错误在于声明: 'NRF24L01_Write_TX_Buf' 函数 排队: NRF24L01_WriteRegBuf(W_REGISTER | W_TX_PAYLOAD,Buf,大小); 虽然这是错误的,必须更正为:

NRF24L01_WriteRegBuf(W_TX_PAYLOAD, Buf, Size); wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

http://www.avrfreaks.net/forum/nrf24l01-problem-communication-failure-cannot-even-read-registers-data-atmega16a

【讨论】:

以上是关于avr codevision 问题在 nRF24L01+ MODULE 中获得确认或 TX_DS 标志的主要内容,如果未能解决你的问题,请参考以下文章

NRF24L01双向无线通信

NRF24L01无线模块的使用

惊呆了!SI24R1可以替代NRF24L01P 而且性能比NRF24L01P还好

关于nRF24L01地址问题

NRF24L01 与 ATtiny 和 Uno 未连接

STM32驱动NRF24L01无线模块