nRF24L01学习(2)
前言
用树莓派和Python搞硬件要求的水平过高,这次换成了单片机和C语言,单片机也是第一次接触,单是学习单片机的运用就花了不少时间,所以这次模块功能的实现,最大的收获就是单片机的学习和了解。
遇到的问题
nRF24L01模块的基本原理和使用基本没有问题了,遇到的问题基本都是与单片机相关的。唯一与nRF24L01模块相关的问题就是“接收端检测到了载波信号但是接收缓冲区里没有数据”,具体体现就是发送端成功后接收端的CD寄存器值为1,STATUS寄存器没有接收中断产生。
最后经过对代码的仔细分析,发现了问题所在。因为大部分寄存器的配置都是借鉴网上的数据,而网上的实验做的都是自带应答的收发,CONFIG寄存器中CRC检验是要使能的。而我为了方便分辨发送端出错还是接收端出错,关闭了自动应答,所以不应该使能CRC检验。CONFIG寄存器的值,接收端从0x0e改为0x02,发送端从0x0f改为0x03,之后就可以正常接收数据了。
十分怀疑上次接收不到数据也是这个原因。
相关代码
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "nrf24l01.h"
#include "stm32f10x_gpio.h"
int main(void)
{
u8 Fifo1_Status0,Fifo1_Status1,Fifo2_Status0,Fifo2_Status1;
int i;
char data[32];
unsigned char RxBuf[5];
unsigned char Addr1[5]={0xE7,0xE7,0xE7,0xE7,0xE7};
unsigned char Addr2[5]={0xE7,0xE7,0xE7,0xE7,0x77};
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,115200); //串口初始化为115200
LED_Init(); //初始化与LED连接的硬件接口
GPIO_nrf_Init();
nRF1_Flush_Tx_Fifo();
nRF2_Flush_Tx_Fifo();
Fifo1_Status0=nRF1_Read_Reg(FIFO_STATUS);
Fifo2_Status0=nRF2_Read_Reg(FIFO_STATUS);
SPI1_SET_CE_LOW();
SPI2_SET_CE_LOW();
nRF1_Init(0x02,0x00,0x03,0x03,0x00,0x0F,0x0F,Addr2,Addr1,5);
nRF2_Init(0x03,0x00,0x03,0x03,0x00,0x0F,0x0F,Addr1,Addr2,5);
for(i=0;i<10000000;i++); //上电1.5ms以上
while(1)
{
nRF1_Check();
nRF2_Check();
SPI1_SET_CE_HIGH();
SPI2_SET_CE_HIGH();
for(i=0;i<100000;i++); //大于130us
if(USART_RX_STA&0x8000)
{
getdata(data);
}
printf("data%d",data[0]);
printf("Fifo1_Status0:%xnrn",Fifo1_Status0);
nRF1_Write_Tx_Payload_Ack(data,32);
Fifo1_Status1=nRF1_Read_Reg(FIFO_STATUS);
printf("Fifo1_Status1:%xnrn",Fifo1_Status1);
for(i=0;i<100000;i++); //大于130us
printf("Fifo2_Status0:%xnrn",Fifo2_Status0);
Fifo2_Status1=nRF2_Read_Reg(FIFO_STATUS);
printf("Fifo2_Status1:%xnrn",Fifo2_Status1);
nRF2_Read_Rx_Payload(RxBuf);
printf("接收到的数据:%snrn",RxBuf);
SPI1_SET_CE_LOW();
SPI2_SET_CE_LOW();
}
}
#ifndef __NRF24L01_H
#define __NRF24L01_H
#include "sys.h"
#include "delay.h"
#include "usart.h"
//nRF24L01操作指令常量
#define NRF_READ_REG 0x00 // 读配置寄存器, 低 5 位为寄存器地址
#define NRF_WRITE_REG 0x20 // 写配置寄存器, 低 5 位为寄存器地址
#define RD_RX_PLOAD 0x61 // 读取 Rx 有效数据, 1-32 字节
#define WR_TX_PLOAD 0xA0 // 写 Tx 有效数据, 1-32 字节
#define FLUSH_TX 0xE1 // 清除 Tx FIFO 寄存器
#define FLUSH_RX 0xE2 // 清除 Rx FIFO 寄存器
#define REUSE_TX_PL 0xE3 // 重新使用上一包数据, CE为高数据包被不断发送
#define R_RX_PL_WID 0x60
#define NOP 0xFF // 用来读取状态寄存器
#define W_ACK_PLOAD 0xA8
#define WR_TX_PLOAD_NACK 0xB0
//nRF24L01寄存器地址
#define CONFIG 0x00
#define EN_AA 0x01 // 使能自动应答功能 Bit0 - 5, 对应通道 0 - 5
#define EN_RXADDR 0x02 // 接收地址允许, Bit0 - 5, 对应通道 0 - 5
#define SETUP_AW 0x03 // 设置地址宽度 ( 所有数据通道 ) : Bit0-1: 00 3字节 01 4字节 10 5字节
#define SETUP_RETR 0x04 // 建立自动重发, Bit0-3: 自动重发计数, Bit4-7: 自动重发延时 250 * x + 86us
#define RF_CH 0x05 // RF 通道, Bit0-6: 工作通道频率
#define RF_SETUP 0x06 // RF 寄存器, Bit3: 传输速度 (0: 1 Mbps, 1: 2 Mbps), Bit1-2: 发射功率, Bit0: 低噪声发大器增益
#define STATUS 0x07 // 状态寄存器, Bit0: RX FIFO 满标志, Bit1-3: 接收数据通道号 (最大: 6 ), Bit4: 达到最多次重发, Bit5: 数据发送完成中断, Bit6: 接收数据中断
#define OBSERVE_TX 0x08 // 发送检测寄存器, Bit4-7: 数据包丢失计数器, Bit0-3: 重发计数器
#define CD 0x09 // 载波检测寄存器, Bit0: 载波检测
#define RX_ADDR_P0 0x0A // 数据通道 0 接收地址, 最大长度 5 个字节, 低字节在前
#define RX_ADDR_P1 0x0B // 数据通道 1 接收地址, 最大长度 5 个字节, 低字节在前
#define RX_ADDR_P2 0x0C // 数据通道 2 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define RX_ADDR_P3 0x0D // 数据通道 3 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define RX_ADDR_P4 0x0E // 数据通道 4 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define RX_ADDR_P5 0x0F // 数据通道 5 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define TX_ADDR 0x10 // 发送地址 (低字节在前), ShockBurstTM 模式下, RX_ADDR_P0 与地址相等
#define RX_PW_P0 0x11 // 接收数据通道 0 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P1 0x12 // 接收数据通道 1 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P2 0x13 // 接收数据通道 2 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P3 0x14 // 接收数据通道 3 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P4 0x15 // 接收数据通道 4 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P5 0x16 // 接收数据通道 5 有效数据宽度 (1-32字节), 设置为 0 则非法
#define FIFO_STATUS 0x17 // FIFO 状态寄存器, Bit0: RX FIFO 寄存器空标志, Bit1 RX FIFO 满标志, Bit2-3 保留
// Bit4 TX FIFO 空标志, Bit5 TX FIFO 满标志, Bit6 1 循环发送上一次数据包, 0 不循环
#define DYNPD 0x1C // 启用动态数据长度, Bit6-7: NULL, Bit5: 启用动态数据长度管道 5
#define FEATRUE 0x1D // 功能寄存器, Bit3-7: 无用,总是为 0, Bit2: 启用动态数据长度, Bit1: 启用 ACK, Bit0: 启用 W_TX_PAYLOAD_NOACK 命令
//发送端引脚配置
#define SPI1_SET_CLK_HIGH() PAout(5) = 1
#define SPI1_SET_CLK_LOW() PAout(5) = 0
#define SPI1_SET_MOSI_HIGH() PAout(7) = 1
#define SPI1_SET_MOSI_LOW() PAout(7) = 0
#define SPI1_GET_MISO PAin(6)
#define SPI1_SET_NSS_HIGH() PAout(4) = 1
#define SPI1_SET_NSS_LOW() PAout(4) = 0
#define SPI1_SET_CE_HIGH() PAout(3) = 1
#define SPI1_SET_CE_LOW() PAout(3) = 0
#define SPI1_GET_IRQ() PAin(2)
//接收端引脚配置
#define SPI2_SET_CLK_HIGH() PBout(13) = 1
#define SPI2_SET_CLK_LOW() PBout(13) = 0
#define SPI2_SET_MOSI_HIGH() PBout(15) = 1
#define SPI2_SET_MOSI_LOW() PBout(15) = 0
#define SPI2_GET_MISO PBin(14)
#define SPI2_SET_NSS_HIGH() PBout(12) = 1
#define SPI2_SET_NSS_LOW() PBout(12) = 0
#define SPI2_SET_CE_HIGH() PCout(6) = 1
#define SPI2_SET_CE_LOW() PCout(6) = 0
#define SPI2_GET_IRQ() PCin(7)
//发送端函数定义
u8 SPI1_Read_Write_Byte(u8 TxByte); //单片机与模块交流单位
u8 nRF1_Read_Reg(u8 Reg_Addr); //读寄存器
void nRF1_Write_Reg(u8 Reg_Addr,u8 dat); //写寄存器
void nRF1_Flush_Tx_Fifo(void); //清空发送缓冲区
void nRF1_Flush_Rx_Fifo(void); //清空接收缓冲区
void nRF1_Reuse_Tx_Payload(void); //重发上一数据包
void nRF1_Write_Tx_Payload_Ack(char *pTxBuf, u8 len);//发送缓冲区写入数据
void nRF1_Write_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len);//地址寄存器的写入
unsigned char nRF1_Read_Top_Fifo_Width( void );//读取接收缓冲区中数据的宽度
void nRF1_Read_Rx_Payload( unsigned char *pRxBuf );//读取接收缓冲区的数据
void nRF1_Set_TxAddr( unsigned char *pAddr, unsigned char len );//配置发送地址
void nRF1_Init(u8 config,u8 en_aa,u8 en_rxaddr,u8 setup_aw,u8 setup_retr,u8 rf_ch,u8 rf_setup,unsigned char *rx_addr_p0,unsigned char *tx_addr,u8 rx_pw_p0);//一次性编辑nRF24L01的所有寄存器
void nRF1_Check(void);//所有寄存器的值的检查
//接收端函数定义(各函数功能同上)
u8 SPI2_Read_Write_Byte(u8 TxByte);
u8 nRF2_Read_Reg(u8 Reg_Addr);
void nRF2_Write_Reg(u8 Reg_Addr,u8 dat);
void nRF2_Flush_Tx_Fifo (void);
void nRF2_Flush_Rx_Fifo(void);
void nRF2_Reuse_Tx_Payload(void);
void nRF2_Write_Tx_Payload_Ack(char *pTxBuf, u8 len);
void nRF2_Write_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len);
unsigned char nRF2_Read_Top_Fifo_Width( void );
void nRF2_Read_Rx_Payload( unsigned char *pRxBuf );
void nRF2_Set_TxAddr( unsigned char *pAddr, unsigned char len );
void nRF2_Init(u8 config,u8 en_aa,u8 en_rxaddr,u8 setup_aw,u8 setup_retr,u8 rf_ch,u8 rf_setup,unsigned char *rx_addr_p0,unsigned char *tx_addr,u8 rx_pw_p0);
void nRF2_Check(void);
#endif
#include "nrf24l01.h"
u8 SPI1_Read_Write_Byte(u8 TxByte)
{
u8 i,j,Data;
SPI1_SET_CLK_LOW();
for(i=0; i<8; i++)
{
/* 发送 */
if(TxByte & 0x80)
SPI1_SET_MOSI_HIGH();// 如果即将要发送的位为 1 则置高IO引脚
else
SPI1_SET_MOSI_LOW(); // 如果即将要发送的位为 0 则置低IO引脚
TxByte <<= 1; // 数据左移一位,先发送的是最高位
SPI1_SET_CLK_HIGH();
for(j=0;j<100;j++); //时延
/* 接收 */
Data <<= 1; // 接收数据左移一位,先接收到的是最高位
if(SPI1_GET_MISO)
Data |= 0x01; // 如果接收时IO引脚为高则认为接收到 1
SPI1_SET_CLK_LOW();
for(j=0;j<100;j++); //时延
}
return Data;
}
u8 nRF1_Read_Reg(u8 Reg_Addr)
{
u8 reg_val;
SPI1_SET_NSS_LOW(); // 片选
SPI1_Read_Write_Byte(Reg_Addr); // 读命令地址
reg_val = SPI1_Read_Write_Byte(0xFF); // 读数据
SPI1_SET_NSS_HIGH();
return reg_val;
}
void nRF1_Write_Reg(u8 Reg_Addr, u8 dat)
{
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte(NRF_WRITE_REG | Reg_Addr);
SPI1_Read_Write_Byte(dat);
SPI1_SET_NSS_HIGH();
}
void nRF1_Flush_Tx_Fifo ( void )
{
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( FLUSH_TX ); // 清空 TX FIFO 命令
SPI1_SET_NSS_HIGH();
}
void nRF1_Flush_Rx_Fifo( void )
{
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( FLUSH_RX ); // 清 RX FIFO 命令
SPI1_SET_NSS_HIGH();
}
void nRF1_Reuse_Tx_Payload( void )
{
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( REUSE_TX_PL ); // 重新使用上一包命令
SPI1_SET_NSS_HIGH();
}
void nRF1_Write_Tx_Payload_Ack(char *pTxBuf, u8 len )
{
u8 btmp;
u8 length = ( len > 32 ) ? 32 : len; // 数据长度超过 32 则只发送 32 个
nRF1_Flush_Tx_Fifo(); // 清 TX FIFO
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( WR_TX_PLOAD ); // 发送命令
for( btmp=0; btmp
SPI1_Read_Write_Byte( *pTxBuf++ ); // 发送数据
SPI1_SET_NSS_HIGH();
}
void nRF1_Write_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len)
{
unsigned char i;
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte(NRF_WRITE_REG | Reg_Addr);
for(i=0; i
SPI1_Read_Write_Byte(*pBuf++);
SPI1_SET_NSS_HIGH();
}
unsigned char nRF1_Read_Top_Fifo_Width( void )
{
unsigned char btmp;
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( R_RX_PL_WID ); // 读 FIFO 中数据宽度命令
btmp =SPI1_Read_Write_Byte( 0xFF ); // 读数据
SPI1_SET_NSS_HIGH();
return btmp;
}
void nRF1_Read_Rx_Payload( unsigned char *pRxBuf )
{
unsigned char Width,i;
Width = nRF1_Read_Top_Fifo_Width( ); // 读接收数据个数
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( RD_RX_PLOAD ); // 读有效数据命令
for( i=0; i
pRxBuf
=SPI1_Read_Write_Byte( 0xFF );// 读数据
SPI1_SET_NSS_HIGH();
nRF1_Flush_Rx_Fifo(); //清空接收缓冲区
}
void nRF1_Set_TxAddr( unsigned char *pAddr, unsigned char len )
{
len = ( len > 5 ) ? 5 : len; // 地址不能大于 5 个字节
nRF1_Write_Buf( TX_ADDR, pAddr, len ); // 写地址
}
nRF24L01学习(2)
前言
用树莓派和Python搞硬件要求的水平过高,这次换成了单片机和C语言,单片机也是第一次接触,单是学习单片机的运用就花了不少时间,所以这次模块功能的实现,最大的收获就是单片机的学习和了解。
遇到的问题
nRF24L01模块的基本原理和使用基本没有问题了,遇到的问题基本都是与单片机相关的。唯一与nRF24L01模块相关的问题就是“接收端检测到了载波信号但是接收缓冲区里没有数据”,具体体现就是发送端成功后接收端的CD寄存器值为1,STATUS寄存器没有接收中断产生。
最后经过对代码的仔细分析,发现了问题所在。因为大部分寄存器的配置都是借鉴网上的数据,而网上的实验做的都是自带应答的收发,CONFIG寄存器中CRC检验是要使能的。而我为了方便分辨发送端出错还是接收端出错,关闭了自动应答,所以不应该使能CRC检验。CONFIG寄存器的值,接收端从0x0e改为0x02,发送端从0x0f改为0x03,之后就可以正常接收数据了。
十分怀疑上次接收不到数据也是这个原因。
相关代码
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "nrf24l01.h"
#include "stm32f10x_gpio.h"
int main(void)
{
u8 Fifo1_Status0,Fifo1_Status1,Fifo2_Status0,Fifo2_Status1;
int i;
char data[32];
unsigned char RxBuf[5];
unsigned char Addr1[5]={0xE7,0xE7,0xE7,0xE7,0xE7};
unsigned char Addr2[5]={0xE7,0xE7,0xE7,0xE7,0x77};
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,115200); //串口初始化为115200
LED_Init(); //初始化与LED连接的硬件接口
GPIO_nrf_Init();
nRF1_Flush_Tx_Fifo();
nRF2_Flush_Tx_Fifo();
Fifo1_Status0=nRF1_Read_Reg(FIFO_STATUS);
Fifo2_Status0=nRF2_Read_Reg(FIFO_STATUS);
SPI1_SET_CE_LOW();
SPI2_SET_CE_LOW();
nRF1_Init(0x02,0x00,0x03,0x03,0x00,0x0F,0x0F,Addr2,Addr1,5);
nRF2_Init(0x03,0x00,0x03,0x03,0x00,0x0F,0x0F,Addr1,Addr2,5);
for(i=0;i<10000000;i++); //上电1.5ms以上
while(1)
{
nRF1_Check();
nRF2_Check();
SPI1_SET_CE_HIGH();
SPI2_SET_CE_HIGH();
for(i=0;i<100000;i++); //大于130us
if(USART_RX_STA&0x8000)
{
getdata(data);
}
printf("data%d",data[0]);
printf("Fifo1_Status0:%xnrn",Fifo1_Status0);
nRF1_Write_Tx_Payload_Ack(data,32);
Fifo1_Status1=nRF1_Read_Reg(FIFO_STATUS);
printf("Fifo1_Status1:%xnrn",Fifo1_Status1);
for(i=0;i<100000;i++); //大于130us
printf("Fifo2_Status0:%xnrn",Fifo2_Status0);
Fifo2_Status1=nRF2_Read_Reg(FIFO_STATUS);
printf("Fifo2_Status1:%xnrn",Fifo2_Status1);
nRF2_Read_Rx_Payload(RxBuf);
printf("接收到的数据:%snrn",RxBuf);
SPI1_SET_CE_LOW();
SPI2_SET_CE_LOW();
}
}
#ifndef __NRF24L01_H
#define __NRF24L01_H
#include "sys.h"
#include "delay.h"
#include "usart.h"
//nRF24L01操作指令常量
#define NRF_READ_REG 0x00 // 读配置寄存器, 低 5 位为寄存器地址
#define NRF_WRITE_REG 0x20 // 写配置寄存器, 低 5 位为寄存器地址
#define RD_RX_PLOAD 0x61 // 读取 Rx 有效数据, 1-32 字节
#define WR_TX_PLOAD 0xA0 // 写 Tx 有效数据, 1-32 字节
#define FLUSH_TX 0xE1 // 清除 Tx FIFO 寄存器
#define FLUSH_RX 0xE2 // 清除 Rx FIFO 寄存器
#define REUSE_TX_PL 0xE3 // 重新使用上一包数据, CE为高数据包被不断发送
#define R_RX_PL_WID 0x60
#define NOP 0xFF // 用来读取状态寄存器
#define W_ACK_PLOAD 0xA8
#define WR_TX_PLOAD_NACK 0xB0
//nRF24L01寄存器地址
#define CONFIG 0x00
#define EN_AA 0x01 // 使能自动应答功能 Bit0 - 5, 对应通道 0 - 5
#define EN_RXADDR 0x02 // 接收地址允许, Bit0 - 5, 对应通道 0 - 5
#define SETUP_AW 0x03 // 设置地址宽度 ( 所有数据通道 ) : Bit0-1: 00 3字节 01 4字节 10 5字节
#define SETUP_RETR 0x04 // 建立自动重发, Bit0-3: 自动重发计数, Bit4-7: 自动重发延时 250 * x + 86us
#define RF_CH 0x05 // RF 通道, Bit0-6: 工作通道频率
#define RF_SETUP 0x06 // RF 寄存器, Bit3: 传输速度 (0: 1 Mbps, 1: 2 Mbps), Bit1-2: 发射功率, Bit0: 低噪声发大器增益
#define STATUS 0x07 // 状态寄存器, Bit0: RX FIFO 满标志, Bit1-3: 接收数据通道号 (最大: 6 ), Bit4: 达到最多次重发, Bit5: 数据发送完成中断, Bit6: 接收数据中断
#define OBSERVE_TX 0x08 // 发送检测寄存器, Bit4-7: 数据包丢失计数器, Bit0-3: 重发计数器
#define CD 0x09 // 载波检测寄存器, Bit0: 载波检测
#define RX_ADDR_P0 0x0A // 数据通道 0 接收地址, 最大长度 5 个字节, 低字节在前
#define RX_ADDR_P1 0x0B // 数据通道 1 接收地址, 最大长度 5 个字节, 低字节在前
#define RX_ADDR_P2 0x0C // 数据通道 2 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define RX_ADDR_P3 0x0D // 数据通道 3 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define RX_ADDR_P4 0x0E // 数据通道 4 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define RX_ADDR_P5 0x0F // 数据通道 5 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define TX_ADDR 0x10 // 发送地址 (低字节在前), ShockBurstTM 模式下, RX_ADDR_P0 与地址相等
#define RX_PW_P0 0x11 // 接收数据通道 0 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P1 0x12 // 接收数据通道 1 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P2 0x13 // 接收数据通道 2 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P3 0x14 // 接收数据通道 3 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P4 0x15 // 接收数据通道 4 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P5 0x16 // 接收数据通道 5 有效数据宽度 (1-32字节), 设置为 0 则非法
#define FIFO_STATUS 0x17 // FIFO 状态寄存器, Bit0: RX FIFO 寄存器空标志, Bit1 RX FIFO 满标志, Bit2-3 保留
// Bit4 TX FIFO 空标志, Bit5 TX FIFO 满标志, Bit6 1 循环发送上一次数据包, 0 不循环
#define DYNPD 0x1C // 启用动态数据长度, Bit6-7: NULL, Bit5: 启用动态数据长度管道 5
#define FEATRUE 0x1D // 功能寄存器, Bit3-7: 无用,总是为 0, Bit2: 启用动态数据长度, Bit1: 启用 ACK, Bit0: 启用 W_TX_PAYLOAD_NOACK 命令
//发送端引脚配置
#define SPI1_SET_CLK_HIGH() PAout(5) = 1
#define SPI1_SET_CLK_LOW() PAout(5) = 0
#define SPI1_SET_MOSI_HIGH() PAout(7) = 1
#define SPI1_SET_MOSI_LOW() PAout(7) = 0
#define SPI1_GET_MISO PAin(6)
#define SPI1_SET_NSS_HIGH() PAout(4) = 1
#define SPI1_SET_NSS_LOW() PAout(4) = 0
#define SPI1_SET_CE_HIGH() PAout(3) = 1
#define SPI1_SET_CE_LOW() PAout(3) = 0
#define SPI1_GET_IRQ() PAin(2)
//接收端引脚配置
#define SPI2_SET_CLK_HIGH() PBout(13) = 1
#define SPI2_SET_CLK_LOW() PBout(13) = 0
#define SPI2_SET_MOSI_HIGH() PBout(15) = 1
#define SPI2_SET_MOSI_LOW() PBout(15) = 0
#define SPI2_GET_MISO PBin(14)
#define SPI2_SET_NSS_HIGH() PBout(12) = 1
#define SPI2_SET_NSS_LOW() PBout(12) = 0
#define SPI2_SET_CE_HIGH() PCout(6) = 1
#define SPI2_SET_CE_LOW() PCout(6) = 0
#define SPI2_GET_IRQ() PCin(7)
//发送端函数定义
u8 SPI1_Read_Write_Byte(u8 TxByte); //单片机与模块交流单位
u8 nRF1_Read_Reg(u8 Reg_Addr); //读寄存器
void nRF1_Write_Reg(u8 Reg_Addr,u8 dat); //写寄存器
void nRF1_Flush_Tx_Fifo(void); //清空发送缓冲区
void nRF1_Flush_Rx_Fifo(void); //清空接收缓冲区
void nRF1_Reuse_Tx_Payload(void); //重发上一数据包
void nRF1_Write_Tx_Payload_Ack(char *pTxBuf, u8 len);//发送缓冲区写入数据
void nRF1_Write_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len);//地址寄存器的写入
unsigned char nRF1_Read_Top_Fifo_Width( void );//读取接收缓冲区中数据的宽度
void nRF1_Read_Rx_Payload( unsigned char *pRxBuf );//读取接收缓冲区的数据
void nRF1_Set_TxAddr( unsigned char *pAddr, unsigned char len );//配置发送地址
void nRF1_Init(u8 config,u8 en_aa,u8 en_rxaddr,u8 setup_aw,u8 setup_retr,u8 rf_ch,u8 rf_setup,unsigned char *rx_addr_p0,unsigned char *tx_addr,u8 rx_pw_p0);//一次性编辑nRF24L01的所有寄存器
void nRF1_Check(void);//所有寄存器的值的检查
//接收端函数定义(各函数功能同上)
u8 SPI2_Read_Write_Byte(u8 TxByte);
u8 nRF2_Read_Reg(u8 Reg_Addr);
void nRF2_Write_Reg(u8 Reg_Addr,u8 dat);
void nRF2_Flush_Tx_Fifo (void);
void nRF2_Flush_Rx_Fifo(void);
void nRF2_Reuse_Tx_Payload(void);
void nRF2_Write_Tx_Payload_Ack(char *pTxBuf, u8 len);
void nRF2_Write_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len);
unsigned char nRF2_Read_Top_Fifo_Width( void );
void nRF2_Read_Rx_Payload( unsigned char *pRxBuf );
void nRF2_Set_TxAddr( unsigned char *pAddr, unsigned char len );
void nRF2_Init(u8 config,u8 en_aa,u8 en_rxaddr,u8 setup_aw,u8 setup_retr,u8 rf_ch,u8 rf_setup,unsigned char *rx_addr_p0,unsigned char *tx_addr,u8 rx_pw_p0);
void nRF2_Check(void);
#endif
#include "nrf24l01.h"
u8 SPI1_Read_Write_Byte(u8 TxByte)
{
u8 i,j,Data;
SPI1_SET_CLK_LOW();
for(i=0; i<8; i++)
{
/* 发送 */
if(TxByte & 0x80)
SPI1_SET_MOSI_HIGH();// 如果即将要发送的位为 1 则置高IO引脚
else
SPI1_SET_MOSI_LOW(); // 如果即将要发送的位为 0 则置低IO引脚
TxByte <<= 1; // 数据左移一位,先发送的是最高位
SPI1_SET_CLK_HIGH();
for(j=0;j<100;j++); //时延
/* 接收 */
Data <<= 1; // 接收数据左移一位,先接收到的是最高位
if(SPI1_GET_MISO)
Data |= 0x01; // 如果接收时IO引脚为高则认为接收到 1
SPI1_SET_CLK_LOW();
for(j=0;j<100;j++); //时延
}
return Data;
}
u8 nRF1_Read_Reg(u8 Reg_Addr)
{
u8 reg_val;
SPI1_SET_NSS_LOW(); // 片选
SPI1_Read_Write_Byte(Reg_Addr); // 读命令地址
reg_val = SPI1_Read_Write_Byte(0xFF); // 读数据
SPI1_SET_NSS_HIGH();
return reg_val;
}
void nRF1_Write_Reg(u8 Reg_Addr, u8 dat)
{
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte(NRF_WRITE_REG | Reg_Addr);
SPI1_Read_Write_Byte(dat);
SPI1_SET_NSS_HIGH();
}
void nRF1_Flush_Tx_Fifo ( void )
{
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( FLUSH_TX ); // 清空 TX FIFO 命令
SPI1_SET_NSS_HIGH();
}
void nRF1_Flush_Rx_Fifo( void )
{
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( FLUSH_RX ); // 清 RX FIFO 命令
SPI1_SET_NSS_HIGH();
}
void nRF1_Reuse_Tx_Payload( void )
{
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( REUSE_TX_PL ); // 重新使用上一包命令
SPI1_SET_NSS_HIGH();
}
void nRF1_Write_Tx_Payload_Ack(char *pTxBuf, u8 len )
{
u8 btmp;
u8 length = ( len > 32 ) ? 32 : len; // 数据长度超过 32 则只发送 32 个
nRF1_Flush_Tx_Fifo(); // 清 TX FIFO
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( WR_TX_PLOAD ); // 发送命令
for( btmp=0; btmp
SPI1_Read_Write_Byte( *pTxBuf++ ); // 发送数据
SPI1_SET_NSS_HIGH();
}
void nRF1_Write_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len)
{
unsigned char i;
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte(NRF_WRITE_REG | Reg_Addr);
for(i=0; i
SPI1_Read_Write_Byte(*pBuf++);
SPI1_SET_NSS_HIGH();
}
unsigned char nRF1_Read_Top_Fifo_Width( void )
{
unsigned char btmp;
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( R_RX_PL_WID ); // 读 FIFO 中数据宽度命令
btmp =SPI1_Read_Write_Byte( 0xFF ); // 读数据
SPI1_SET_NSS_HIGH();
return btmp;
}
void nRF1_Read_Rx_Payload( unsigned char *pRxBuf )
{
unsigned char Width,i;
Width = nRF1_Read_Top_Fifo_Width( ); // 读接收数据个数
SPI1_SET_NSS_LOW();
SPI1_Read_Write_Byte( RD_RX_PLOAD ); // 读有效数据命令
for( i=0; i
pRxBuf=SPI1_Read_Write_Byte( 0xFF );// 读数据
SPI1_SET_NSS_HIGH();
nRF1_Flush_Rx_Fifo(); //清空接收缓冲区
}
void nRF1_Set_TxAddr( unsigned char *pAddr, unsigned char len )
{
len = ( len > 5 ) ? 5 : len; // 地址不能大于 5 个字节
nRF1_Write_Buf( TX_ADDR, pAddr, len ); // 写地址
}
举报