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 标志的主要内容,如果未能解决你的问题,请参考以下文章