本系统用到4个NRF24L01模块,最多可以加到7个NRF24L01(其中一个用作主机另外的六个用作从机)。显示用的是诺基亚的5110,MCU用的是52单片机。经亲测发送和接收都很好。在此给上原理图加程序。
附上成品图
主机代码
可下载到开发板上也可以自己做一个可以串口通信的最小系统或者去掉主机代码中的串口通信部分下载到上图做的板中(记得修改引脚)
#include typedef unsigned char uchar; typedef unsigned char uint; /*****************NRF24L01端口定义*****************************************/ sbit MISO =P0^4; sbit MOSI =P0^3; sbit SCK =P0^2; sbit CE =P0^0; sbit CSN =P0^1; sbit IRQ =P0^5; /*************LCD5110 I/O定义***********************************************/ sbit LCD_RST =P1^4; sbit LCD_CE =P1^3; sbit LCD_DC =P1^2; sbit LCD_SCLK =P1^0; sbit LCD_Din =P1^1; /******************按键****************************************************/ sbit KEY1=P3^6; sbit KEY2=P3^7; /******************发光二极管*********************************************/ sbit led1=P1^6; sbit led2=P1^7; /******************NRF24L01地址宏定义*************************************/ #define TX_ADR_WIDTH 5 // 5 uints TX address width #define RX_ADR_WIDTH 5 // 5 uints RX address width #define TX_PLOAD_WIDTH 20 // 20 uints TX payload #define RX_PLOAD_WIDTH 20 // 20 uints TX payload uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址 uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址0 uint const RX_ADDRESS1[RX_ADR_WIDTH]={0xf1,0xb3,0xb4,0xb5,0xb6}; //接收地址1 uint const RX_ADDRESS2[RX_ADR_WIDTH]={0xcd,0xb3,0xb4,0xb5,0xb6}; //接收地址2 uint const RX_ADDRESS3[RX_ADR_WIDTH]={0xa3,0xb3,0xb4,0xb5,0xb6}; //接收地址 3 uint const RX_ADDRESS4[RX_ADR_WIDTH]={0x0f,0xb3,0xb4,0xb5,0xb6}; //接收地址4 uint const RX_ADDRESS5[RX_ADR_WIDTH]={0x05,0xb3,0xb4,0xb5,0xb6}; //接收地址5 /********************NRF24L01寄存器指令*************************************/ #define READ_REG 0x00 // 读寄存器指令 #define WRITE_REG 0x20 // 写寄存器指令 #define RD_RX_PLOAD 0x61 // 读取接收数据指令 #define WR_TX_PLOAD 0xA0 // 写待发数据指令 #define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令 #define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令 #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令 #define NOP 0xFF // 保留 /**********************SPI(nRF24L01)寄存器地址*******************************/ #define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式 #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 // 频道0接收数据地址 #define RX_ADDR_P1 0x0B // 频道1接收数据地址 #define RX_ADDR_P2 0x0C // 频道2接收数据地址 #define RX_ADDR_P3 0x0D // 频道3接收数据地址 #define RX_ADDR_P4 0x0E // 频道4接收数据地址 #define RX_ADDR_P5 0x0F // 频道5接收数据地址 #define TX_ADDR 0x10 // 发送地址寄存器 #define RX_PW_P0 0x11 // 接收频道0接收数据长度 #define RX_PW_P1 0x12 // 接收频道0接收数据长度 #define RX_PW_P2 0x13 // 接收频道0接收数据长度 #define RX_PW_P3 0x14 // 接收频道0接收数据长度 #define RX_PW_P4 0x15 // 接收频道0接收数据长度 #define RX_PW_P5 0x16 // 接收频道0接收数据长度 #define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置 /******************ASCII数组区**********************************/ code unsigned char font6x8[92][6] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, //数字和字母 { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 } }; /***********标志位**********************************************/ /***************************************************************/ /***************函数声明区*****************************************************************/ void LCD_write_byte(unsigned char dat, unsigned char command); //SPI写入数据函数 void LCD_init(void); //LCD5110初始化函数 void LCD_set_XY(unsigned char X, unsigned char Y); //设置显示指针函数 void LCD_write_char(unsigned char c); //写一个字符到LCD5110 void LCD_clear(void); //LCD初始化函数 void inerDelay_us(unsigned char n); //延时函数 void LCD_write_english_string(unsigned char X,unsigned char Y,char *s); //写字符串到LCD函数 void LCD_write_english_char(unsigned char X,unsigned char Y,unsigned char ch); //写一个字符到LCD函数 void Delay(unsigned int s); //场延时函数 void NRF24L01_init(void); //NRF24L01初始化 uint NRF24L01_SPI_RW(uint uchar); //SPI写入和读出 uchar NRF24L01_SPI_Read(uchar reg); //读寄存器reg void NRF24L01_SetRX_Mode(void); //设置接收模式 uint NRF24L01_SPI_RW_Reg(uchar reg, uchar value); //向寄存器reg中存入数据 uint NRF24L01_SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //读取寄存器reg的数据,存到pBuf中 uint NRF24L01_SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //向寄存器reg中写入数据pBuf unsigned char NRF24L01_RxPacket(unsigned char* rx_buf); //由MCU读取NRF24L01接收到的数据 void NRF24L01_TxPacket(unsigned char * tx_buf,unsigned char xindaoji); //由NRF24L01 发送数据tx_buf void USART_init(void); //串口的初始化 void USART_TxPacket_char(uchar f_data); //通过串口发送一个字节数据函数 void USART_TxPacket_buf(uchar *f_data); //通过串口发送一个字符串的数据函数 /*****************************************************************************************/ /*****************************************长延时*****************************************/ void Delay(unsigned int s) { unsigned int i,j; for(i=0; i<1000; i++); for(j=0; j /***************************NRF2401*******************************************************/ uint bdata sta; //状态标志 sbit RX_DR =sta^6; //接收终端标示 sbit TX_DS =sta^5; //发送中断标志 sbit MAX_RT =sta^4; //重发次数中断标志,当重发次数超过了最发充许的重发次数该中断产生 /*****************************************************************************************/ /****************************************************************************************** /*延时函数 /******************************************************************************************/ void inerDelay_us(unsigned char n) { for(;n>0;n--) _nop_(); } /******************************************************************************************/ /*********************************************************** 函数名称:LCD_write_byte 函数功能:模拟SPI接口时序写数据/命令LCD 入口参数:data :写入的数据; command :写数据/命令选择; 出口参数:无 备 注: ***********************************************************/ void LCD_write_byte(unsigned char dat, unsigned char command) { unsigned char i; LCD_CE = 0; //5110片选有效,允许输入数据 if (command==0) //写命令 LCD_DC = 0; else LCD_DC=1; for(i=0;i<8;i++) //传送8bit数据 { if(dat&0x80) LCD_Din= 1; else LCD_Din = 0; LCD_SCLK = 0; dat = dat << 1; LCD_SCLK = 1; } LCD_CE = 1; //禁止5110 } /*********************************************************** 函数名称:LCD_init 函数功能:5110初始化 入口参数:无 出口参数:无 备 注: ***********************************************************/ void LCD_init(void) { LCD_RST = 0; // 产生一个让LCD复位的低电平脉冲 inerDelay_us(1); LCD_RST = 1; LCD_CE = 0; // 关闭LCD inerDelay_us(1); LCD_CE = 1; // 使能LCD inerDelay_us(1); LCD_write_byte(0x21, 0); // 使用扩展命令设置LCD模式 LCD_write_byte(0xc8, 0); // 设置液晶偏置电压 LCD_write_byte(0x06, 0); // 温度校正 LCD_write_byte(0x13, 0); // 1:48 LCD_write_byte(0x20, 0); // 使用基本命令,V=0,水平寻址 LCD_clear(); // 清屏 LCD_write_byte(0x0c, 0); // 设定显示模式,正常显示 LCD_CE = 0; // 关闭LCD } /*********************************************************** 函数名称:LCD_set_XY 函数功能:设置LCD坐标函数 入口参数:X :0-83 Y :0-5 出口参数:无 备 注: ***********************************************************/ void LCD_set_XY(unsigned char X, unsigned char Y) { LCD_write_byte(0x40 | Y, 0); // column LCD_write_byte(0x80 | X, 0); // row } /*********************************************************** 函数名称:LCD_write_char 函数功能:显示英文字符 入口参数:c : 显示的字符 出口参数:无 备 注: ***********************************************************/ void LCD_write_char(unsigned char c) { unsigned char line; c -= 32; //数组的行号 for (line=0; line<6; line++) LCD_write_byte(font6x8[c][line], 1); } /*------------------------------------------ LCD_clear: LCD清屏函数 编写日期:20080918 --------------------------------------------*/ void LCD_clear(void) { unsigned int i; LCD_write_byte(0x0c, 0); LCD_write_byte(0x80, 0); for (i=0; i<504; i++) LCD_write_byte(0, 1); } /*------------------------------------------------------------------------------- 函数名称:void LCD_write_english_string(unsigned char X,unsigned char Y,char *s) 函数功能:写字符串函数 入口参数:X、Y :位图绘制的起始X、Y坐标; *s :字符串; 出口参数:无 备 注: --------------------------------------------------------------------------------*/ void LCD_write_english_string(unsigned char X,unsigned char Y,char *s) { LCD_set_XY(X,Y); while (*s) { LCD_write_char(*s); s++; } } /*------------------------------------------------------------------------------- 函数名称:void LCD_write_english_string(unsigned char X,unsigned char Y,char *s) 函数功能:写字符串函数 入口参数:X、Y :位图绘制的起始X、Y坐标; *s :字符串; 出口参数:无 备 注: --------------------------------------------------------------------------------*/ void LCD_write_english_char(unsigned char X,unsigned char Y,unsigned char ch) { LCD_set_XY(X,Y); LCD_write_char(ch); } /*********************************************************************************/ /****************************************************************************************/ /*NRF24L01初始化 //***************************************************************************************/ void NRF24L01_init(void) { inerDelay_us(100); CE=0; // 芯片使能 CSN=1; // (Spi disable)SPI 失能,即禁止2401芯片的SPI功能 SCK=0; // 初始化SPI时钟 NRF24L01_SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 设置本地地址 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 设置接收端地址0 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH); // 设置接收端地址1 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_ADDR_P2,RX_ADDRESS2[0]); // 设置接收端地址2 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_ADDR_P3,RX_ADDRESS3[0]); // 设置接收端地址3 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_ADDR_P4,RX_ADDRESS4[0]); // 设置接收端地址4 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_ADDR_P5,RX_ADDRESS5[0]); // 设置接收端地址5 NRF24L01_SPI_RW_Reg(WRITE_REG + EN_AA,0x3f); // 频道0,1,2,3,4,5自动 ACK应答允许 NRF24L01_SPI_RW_Reg(WRITE_REG + EN_RXADDR,0x3f); // 允许接收地址有频道0,1,2,3,4,5,如果需要多频道可以参考Page21 NRF24L01_SPI_RW_Reg(WRITE_REG+SETUP_RETR,0x1a); //设置自动重发的延时和次数,延时大小为4000+86us,次数5次 NRF24L01_SPI_RW_Reg(WRITE_REG + RF_CH,0); // 设置信道工作为2.4GHZ,收发必须一致 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_PW_P0,RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_PW_P2, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_PW_P3, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_PW_P4, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_PW_P5, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节 NRF24L01_SPI_RW_Reg(WRITE_REG + RF_SETUP,0x07); //设置发射速率为2MHZ,发射功率为最大值0dB NRF24L01_SPI_RW_Reg(WRITE_REG+CONFIG,0x0f); //IRQ收发完成中断响应,16为CRC,主接收 } /**************************************************************************************************** /*函数:uint SPI_RW(uint uchar) /*功能:NRF24L01的SPI写时序 /****************************************************************************************************/ uint NRF24L01_SPI_RW(uint uchar) //发送uchar数据,并返回接收到的数据 { uint bit_ctr; //位计数器,用于确定接收或者发送的位数,这里是一个字节即8位 for(bit_ctr=0;bit_ctr<8;bit_ctr++) { MOSI = (uchar & 0x80); // (output 'uchar', MSB to MOSI)输出数据,MSB to MOSI,即先送高位后送低位 uchar = (uchar << 1); // (shift next bit into MSB..)右移一位,准备传送下一个数据 SCK = 1; // (Set SCK high..)设置SCK为高 uchar |= MISO; // (capture current MISO bit )接收24L01传出的数据,他是先先送高位后送低位 SCK = 0; // (..then set SCK low again)拉低SCK时钟产生下降沿,从MSOI送出数据,在下一次SCK为高时读入MISO } return(uchar); // return read uchar } /**************************************************************************************************** /*函数:uchar SPI_Read(uchar reg) /*功能:NRF24L01的SPI时序 /****************************************************************************************************/ uchar NRF24L01_SPI_Read(uchar reg) { uchar reg_val; CSN = 0; // (CSN low, initialize SPI communication...)CSN拉低,启动SPI通信 NRF24L01_SPI_RW(reg); // (Select register to read from..)设置读取的寄存器 reg_val = NRF24L01_SPI_RW(0); // (..then read registervalue)读出寄存器中的数据 CSN = 1; // (CSN high, terminate SPI communication)CSN拉高, 终止SPI通信 return(reg_val); // (return register value)返回接收到的数据 } /****************************************************************************************************/ /*功能:NRF24L01读写寄存器函数 /****************************************************************************************************/ uint NRF24L01_SPI_RW_Reg(uchar reg, uchar value) { uint status; CSN = 0; // (CSN low, init SPI transaction)SCN拉低,启动SPI通信 status = NRF24L01_SPI_RW(reg); // (select register)选择要操作的寄存器 NRF24L01_SPI_RW(value); // (..and write value to it..)向选择的寄存器中写入数据 CSN = 1; // (CSN high again)CSN拉高,终止SPI通信 return(status); // (return nRF24L01 status uchar)返回2401 reg寄存器的状态 } /****************************************************************************************************/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数 /****************************************************************************************************/ uint NRF24L01_SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) { uint status,uchar_ctr; CSN = 0; // Set CSN low, init SPI tranaction status = NRF24L01_SPI_RW(reg); // Select register to write to and read status uchar for(uchar_ctr=0;uchar_ctr /********************************************************************************************************* /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于写数据,reg:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数 /*********************************************************************************************************/ uint NRF24L01_SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) { uint status,uchar_ctr; CSN = 0; //SPI使能 status = NRF24L01_SPI_RW(reg); for(uchar_ctr=0; uchar_ctr /*函数:void SetRX_Mode(void) /*功能:数据接收配置 /****************************************************************************************************/ void NRF24L01_SetRX_Mode(void) { CE=0; //片选使能 NRF24L01_SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收 CE = 1; //片选失能 inerDelay_us(130); } /******************************************************************************************************/ /*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) /*功能:数据读取后放如rx_buf接收缓冲区中 /******************************************************************************************************/ unsigned char NRF24L01_RxPacket(unsigned char* rx_buf) { unsigned char RX_P_NO; //接收通道号 NRF24L01_SetRX_Mode(); Delay(1000); sta=NRF24L01_SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状? RX_P_NO=sta&0x0e; //获取通道号!!!!!!!!!!!!!!! if(RX_DR) // 判断是否接收到数据 { CE = 0; //SPI使能 NRF24L01_SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// (read receive payload from RX_FIFO buffer)从接收缓冲器中读出数据 led2=0; //用发光二极管显示收没收到数据 } NRF24L01_SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清除中断标志 CSN=0; NRF24L01_SPI_RW(FLUSH_RX); //用于清空FIFO !!关键!!防止接收先前的数据! CSN=1; Delay(100); led2=1; return RX_P_NO; //没有接收到数据RX_P_NO则为0x0e即寄存器RX_FIFO为空 } /*********************************************************************************************************** /*函数:void nRF24L01_TxPacket(unsigned char * tx_buf) /*功能:发送 tx_buf中数据 /**********************************************************************************************************/ void NRF24L01_TxPacket(unsigned char * tx_buf,unsigned char xindaoji) { CE=0; //(StandBy I模式)待机 I模式 CSN=0; NRF24L01_SPI_RW(FLUSH_TX); //用于清空FIFO !!关键!!防止发送先前的数据! CSN=1; switch(xindaoji) { case 0: NRF24L01_SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 装载本地地址0 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 装载接收端地址0 break; case 1: NRF24L01_SPI_Write_Buf(WRITE_REG + TX_ADDR, RX_ADDRESS1, TX_ADR_WIDTH); // 装载接收端地址1 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS1, RX_ADR_WIDTH); // 装载接收端地址1 break; case 2: NRF24L01_SPI_Write_Buf(WRITE_REG + TX_ADDR, RX_ADDRESS2, TX_ADR_WIDTH); // 装载接收端地址2 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS2, RX_ADR_WIDTH); // 装载接收端地址2 break; case 3: NRF24L01_SPI_Write_Buf(WRITE_REG + TX_ADDR, RX_ADDRESS3, TX_ADR_WIDTH); // 装载接收端地址3 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS3, RX_ADR_WIDTH); // 装载接收端地址3 break; case 4: NRF24L01_SPI_Write_Buf(WRITE_REG + TX_ADDR, RX_ADDRESS4, TX_ADR_WIDTH); // 装载接收端地址4 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS4, RX_ADR_WIDTH); // 装载接收端地址4 break; case 5: NRF24L01_SPI_Write_Buf(WRITE_REG + TX_ADDR,RX_ADDRESS5, TX_ADR_WIDTH); // 装载接收端地址5 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS5, RX_ADR_WIDTH); // 装载接收端地址5 break; } NRF24L01_SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据 NRF24L01_SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送 CE=1; //置高CE,激发数据发送 inerDelay_us(10); NRF24L01_SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 装载本地地址0 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 装载接收端地址0 } /****************************************************************************************************/ /*********************************************************************************************************** /*函数:void USART_init(void) /*功能:串口的初始化 /**********************************************************************************************************/ void USART_init() { TMOD=0x20; //设置定时器1的工作方式为2 TH1=0xfd; TL1=0xfd; TCON=0x40; //开定时器1 SCON=0x50; //SMOD的设置在PCON寄存器的最高位,SMOD的默认设置为0 IE=0x90; } /*********************************************************************************************************** /*函数:void USART_TxPacket_char(uchar f_data) /*功能:通过串口发送一个字节的函数(即向上位机发送数据) /**********************************************************************************************************/ void USART_TxPacket_char(uchar f_data) { ES=0; SBUF=f_data; while(!TI); TI=0; ES=1; } /*********************************************************************************************************** /*函数:void USART_TxPacket_buf(uchar *f_data) /*功能:通过串口发送字符串的函数(即向上位机发送数据) /**********************************************************************************************************/ void USART_TxPacket_buf(uchar *f_data) { while(*f_data!=0) //判断是不是字符串的结束符 { USART_TxPacket_char(*f_data); //不是传人一个该字节 f_data++; //字符指针向下移一位 } } /***********************************************************************************************************/ void main() { unsigned char TxBuf[TX_PLOAD_WIDTH]=\"answer\";//定义发送的数据数组 unsigned char RxBuf[RX_PLOAD_WIDTH]={0}; //定义接收数据的数组 unsigned char tf=0; //清除显示标志 unsigned char number=0; //记录接收的是第几个发送机 LCD_init(); //5110的初始化 LCD_clear(); //5110的清屏函数 NRF24L01_init(); //NRF24L01的初始化 USART_init(); //串口初始化 LCD_write_english_string(3*6,0,\"acceptor\"); //字符串显示 USART_TxPacket_buf(\" 桂林电子科技大学 \"); USART_TxPacket_buf(\" 三院科协 \"); while(1) { while(1) { number=NRF24L01_RxPacket(RxBuf); number=number>>1; //寄存器STATUS的1-3位中存的才是通道号所有右移1使通道号变为低3位好处理 Delay(1000); switch(number) { case 0: if(RxBuf[0]==0) { LCD_write_english_string(2*6,1,\"0 answer\"); USART_TxPacket_buf(\" 0回答 \"); tf=1; //清除回答模式标志位 } else { LCD_write_english_string(0*6,2,\"jury 0:\"); LCD_write_english_char(7*6,2,' '); LCD_write_english_char(8*6,2,RxBuf[1]+0x30); if(RxBuf[1]==10) { LCD_write_english_char(7*6,2,1+0x30); LCD_write_english_char(8*6,2,0+0x30); USART_TxPacket_buf(\"评委0:10\"); USART_TxPacket_buf(\" \"); } else { USART_TxPacket_buf(\"评委0:\"); USART_TxPacket_char(RxBuf[1]+0x30); USART_TxPacket_buf(\" \"); } } break; case 1: if(RxBuf[0]==0) { LCD_write_english_string(2*6,1,\"1 answer\"); USART_TxPacket_buf(\" 1回答 \"); tf=1; //清除回答模式标志位 } else { LCD_write_english_string(0,3,\"jury 1:\"); LCD_write_english_char(7*6,2,' '); LCD_write_english_char(8*6,3,RxBuf[1]+0x30); if(RxBuf[1]==10) { LCD_write_english_char(7*6,2,1+0x30); LCD_write_english_char(8*6,2,0+0x30); USART_TxPacket_buf(\"评委1:10\"); USART_TxPacket_buf(\" \"); } else { USART_TxPacket_buf(\"评委1:\"); USART_TxPacket_char(RxBuf[1]+0x30); USART_TxPacket_buf(\" \"); } } break; case 2: if(RxBuf[0]==0) { LCD_write_english_string(2*6,1,\"2 answer\"); USART_TxPacket_buf(\" 2回答 \"); tf=1; //清除回答模式标志位 } else { LCD_write_english_string(0*6,4,\"jury 2:\"); LCD_write_english_char(7*6,2,' '); LCD_write_english_char(8*6,4,RxBuf[1]+0x30); if(RxBuf[1]==10) { LCD_write_english_char(7*6,2,1+0x30); LCD_write_english_char(8*6,2,0+0x30); USART_TxPacket_buf(\"评委2:10\"); USART_TxPacket_buf(\" \"); } else { USART_TxPacket_buf(\"评委2:\"); USART_TxPacket_char(RxBuf[1]+0x30); USART_TxPacket_buf(\" \"); } } break; case 3: if(RxBuf[0]==0) { LCD_write_english_string(2*6,1,\"3 answer\"); USART_TxPacket_buf(\" 3回答 \"); tf=1; //清除回答模式标志位 } else \"); \"); 边的answer 数据 数据 { LCD_write_english_string(0*6,5,\"jury 3:\"); LCD_write_english_char(7*6,2,' '); LCD_write_english_char(8*6,5,RxBuf[1]+0x30); if(RxBuf[1]==10) { LCD_write_english_char(7*6,2,1+0x30); LCD_write_english_char(8*6,2,0+0x30); USART_TxPacket_buf(\"评委3:10\"); USART_TxPacket_buf(\" } else { USART_TxPacket_buf(\"评委3:\"); USART_TxPacket_char(RxBuf[1]+0x30); USART_TxPacket_buf(\" } } break; } RxBuf[0]=0; RxBuf[1]=0; if(tf) break; } LCD_write_english_string(2*6,5,\"clear flag\"); NRF24L01_TxPacket(TxBuf,number); //发送回发送的最快发送器 while(1) { if(KEY1==0) { NRF24L01_TxPacket(\" \ //清除发送 LCD_write_english_string(2*6,1,\" \"); //清除显示屏的LCD_write_english_string(2*6,5,\" \"); //清除显示屏的tf=0; led1=0; Delay(120); led1=1; while(!KEY1); break; } } } } /*//接收上位机的数据 void USART_RxPacket() interrupt 4 { RI=0; =SBUF; }*/ /********************************************************************************** 修改日:2013/9/25 称号:起点 学校:桂林电子科技大学 QQ:978019740 本人现在正在写上位机的串口通信软件有什么意见的可以一起交流 **********************************************************************************/ 从机代码(如果你们做的是上图的板可以不用修改从机的引脚) #include typedef unsigned char uchar; typedef unsigned char uint; /*****************NRF24L01端口定义*****************************************/ sbit MISO =P2^3; sbit MOSI =P2^1; sbit SCK =P2^4; sbit CE =P2^5; sbit CSN =P2^0; sbit IRQ =P2^2; /*************LCD5110 I/O定义***********************************************/ sbit LCD_RST =P1^0; sbit LCD_CE =P1^1; sbit LCD_DC =P1^2; sbit LCD_SCLK =P1^4; sbit LCD_Din =P1^3; /******************按键****************************************************/ sbit KEY1=P3^5; sbit KEY2=P3^6; sbit KEY3=P3^7; sbit KEY4=P3^4; /******************发光二极管*********************************************/ sbit led1=P1^6; sbit led2=P1^7; /******************NRF24L01地址宏定义*************************************/ #define TX_ADR_WIDTH 5 // 5 uints TX address width #define RX_ADR_WIDTH 5 // 5 uints RX address width #define TX_PLOAD_WIDTH 20 // 20 uints TX payload #define RX_PLOAD_WIDTH 20 // 20 uints TX payload uint const TX_ADDRESS[TX_ADR_WIDTH]= {0xf1,0xb3,0xb4,0xb5,0xb6}; //本地地址 uint const RX_ADDRESS[RX_ADR_WIDTH]= {0xf1,0xb3,0xb4,0xb5,0xb6}; //接收地址 /********************NRF24L01寄存器指令*************************************/ #define READ_REG 0x00 // 读寄存器指令 #define WRITE_REG 0x20 // 写寄存器指令 #define RD_RX_PLOAD 0x61 // 读取接收数据指令 #define WR_TX_PLOAD 0xA0 // 写待发数据指令 #define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令 #define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令 #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令 #define NOP 0xFF // 保留 /**********************SPI(nRF24L01)寄存器地址*******************************/ #define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式 #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 // 频道0接收数据地址 #define RX_ADDR_P1 0x0B // 频道1接收数据地址 #define RX_ADDR_P2 0x0C // 频道2接收数据地址 #define RX_ADDR_P3 0x0D // 频道3接收数据地址 #define RX_ADDR_P4 0x0E // 频道4接收数据地址 #define RX_ADDR_P5 0x0F // 频道5接收数据地址 #define TX_ADDR 0x10 // 发送地址寄存器 #define RX_PW_P0 0x11 // 接收频道0接收数据长度 #define RX_PW_P1 0x12 // 接收频道0接收数据长度 #define RX_PW_P2 0x13 // 接收频道0接收数据长度 #define RX_PW_P3 0x14 // 接收频道0接收数据长度 #define RX_PW_P4 0x15 // 接收频道0接收数据长度 #define RX_PW_P5 0x16 // 接收频道0接收数据长度 #define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置 /******************ASCII数组区**********************************/ code unsigned char font6x8[92][6] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, //数字和字母 { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 } }; /***************************************************************/ /***************函数声明区*****************************************************************/ void LCD_write_byte(unsigned char dat, unsigned char command); //SPI写入数据函数 void LCD_init(void); //LCD5110初始化函数 void LCD_set_XY(unsigned char X, unsigned char Y); //设置显示指针函数 void LCD_write_char(unsigned char c); //写一个字符到LCD5110 void LCD_clear(void); //LCD初始化函数 void inerDelay_us(unsigned char n); //延时函数 void LCD_write_english_string(unsigned char X,unsigned char Y,char *s); //写字符串到LCD函数 void LCD_write_english_char(unsigned char X,unsigned char Y,unsigned char ch); //写一个字符到LCD函数 void Delay(unsigned int s); //场延时函数 void NRF24L01_init(void); //NRF24L01初始化 uint NRF24L01_SPI_RW(uint uchar); //SPI写入和读出 uchar NRF24L01_SPI_Read(uchar reg); //读寄存器reg void NRF24L01_SetRX_Mode(void); //设置接收模式 uint NRF24L01_SPI_RW_Reg(uchar reg, uchar value); //向寄存器reg中存入数据 uint NRF24L01_SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //读取寄存器reg的数据,存到pBuf中 uint NRF24L01_SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //向寄存器reg中写入数据pBuf unsigned char NRF24L01_RxPacket(unsigned char* rx_buf); //由MCU读取NRF24L01接收到的数据 void NRF24L01_TxPacket(unsigned char * tx_buf); //由NRF24L01 发送数据tx_buf /*****************************************************************************************/ /*****************************************长延时*****************************************/ void Delay(unsigned int s) { unsigned int i,j; for(i=0; i<1000; i++); for(j=0; j /***************************NRF2401*******************************************************/ uint bdata sta; //状态标志 sbit RX_DR =sta^6; //接收终端标示 sbit TX_DS =sta^5; //发送中断标志 sbit MAX_RT =sta^4; //重发次数中断标志,当重发次数超过了最发充许的重发次数该中断产生 /*****************************************************************************************/ /****************************************************************************************** /*延时函数 /******************************************************************************************/ void inerDelay_us(unsigned char n) { for(;n>0;n--) _nop_(); } /******************************************************************************************/ /*********************************************************** 函数名称:LCD_write_byte 函数功能:模拟SPI接口时序写数据/命令LCD 入口参数:data :写入的数据; command :写数据/命令选择; 出口参数:无 备 注: ***********************************************************/ void LCD_write_byte(unsigned char dat, unsigned char command) { unsigned char i; LCD_CE = 0; //5110片选有效,允许输入数据 if (command==0) //写命令 LCD_DC = 0; else LCD_DC=1; for(i=0;i<8;i++) //传送8bit数据 { if(dat&0x80) LCD_Din= 1; else LCD_Din = 0; LCD_SCLK = 0; dat = dat << 1; LCD_SCLK = 1; } LCD_CE = 1; //禁止5110 } /*********************************************************** 函数名称:LCD_init 函数功能:5110初始化 入口参数:无 出口参数:无 备 注: ***********************************************************/ void LCD_init(void) { LCD_RST = 0; // 产生一个让LCD复位的低电平脉冲 inerDelay_us(1); LCD_RST = 1; LCD_CE = 0; // 关闭LCD inerDelay_us(1); LCD_CE = 1; // 使能LCD inerDelay_us(1); LCD_write_byte(0x21, 0); // 使用扩展命令设置LCD模式 LCD_write_byte(0xc8, 0); // 设置液晶偏置电压 LCD_write_byte(0x06, 0); // 温度校正 LCD_write_byte(0x13, 0); // 1:48 LCD_write_byte(0x20, 0); // 使用基本命令,V=0,水平寻址 LCD_clear(); // 清屏 LCD_write_byte(0x0c, 0); // 设定显示模式,正常显示 LCD_CE = 0; // 关闭LCD } /*********************************************************** 函数名称:LCD_set_XY 函数功能:设置LCD坐标函数 入口参数:X :0-83 Y :0-5 出口参数:无 备 注: ***********************************************************/ void LCD_set_XY(unsigned char X, unsigned char Y) { LCD_write_byte(0x40 | Y, 0); // column LCD_write_byte(0x80 | X, 0); // row } /*********************************************************** 函数名称:LCD_write_char 函数功能:显示英文字符 入口参数:c : 显示的字符 出口参数:无 备 注: ***********************************************************/ void LCD_write_char(unsigned char c) { unsigned char line; c -= 32; //数组的行号 for (line=0; line<6; line++) LCD_write_byte(font6x8[c][line], 1); } /*------------------------------------------ LCD_clear: LCD清屏函数 编写日期:20080918 --------------------------------------------*/ void LCD_clear(void) { unsigned int i; LCD_write_byte(0x0c, 0); LCD_write_byte(0x80, 0); for (i=0; i<504; i++) LCD_write_byte(0, 1); } /*------------------------------------------------------------------------------- 函数名称:void LCD_write_english_string(unsigned char X,unsigned char Y,char *s) 函数功能:写字符串函数 入口参数:X、Y :位图绘制的起始X、Y坐标; *s :字符串; 出口参数:无 备 注: --------------------------------------------------------------------------------*/ void LCD_write_english_string(unsigned char X,unsigned char Y,char *s) { LCD_set_XY(X,Y); while (*s) { LCD_write_char(*s); s++; } } /*------------------------------------------------------------------------------- 函数名称:void LCD_write_english_string(unsigned char X,unsigned char Y,char *s) 函数功能:写字符串函数 入口参数:X、Y :位图绘制的起始X、Y坐标; *s :字符串; 出口参数:无 备 注: --------------------------------------------------------------------------------*/ void LCD_write_english_char(unsigned char X,unsigned char Y,unsigned char ch) { LCD_set_XY(X,Y); LCD_write_char(ch); } /*********************************************************************************/ /****************************************************************************************/ /*NRF24L01初始化 //***************************************************************************************/ void NRF24L01_init(void) { inerDelay_us(100); CE=0; // 芯片使能 CSN=1; // (Spi disable)SPI 失能,即禁止2401芯片的SPI功能 SCK=0; // 初始化SPI时钟 NRF24L01_SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 设置本地地址 NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 设置接收端地址0 NRF24L01_SPI_RW_Reg(WRITE_REG + EN_AA,0x01); // 频道0,自动 ACK应答允许 NRF24L01_SPI_RW_Reg(WRITE_REG + EN_RXADDR,0x01); // 允许接收地址有频道0,如果需要多频道可以参考Page21 NRF24L01_SPI_RW_Reg(WRITE_REG+SETUP_RETR,0x1a); //设置自动重发的延时和次数,延时大小为4000+86us,次数5次 NRF24L01_SPI_RW_Reg(WRITE_REG + RF_CH,0); // 设置信道工作为2.4GHZ,收发必须一致 NRF24L01_SPI_RW_Reg(WRITE_REG + RX_PW_P0,RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节 NRF24L01_SPI_RW_Reg(WRITE_REG + RF_SETUP,0x07); //设置发射速率为2MHZ,发射功率为最大值0dB NRF24L01_SPI_RW_Reg(WRITE_REG+CONFIG,0x0f); //IRQ收发完成中断响应,16为CRC,主接收 } /**************************************************************************************************** /*函数:uint SPI_RW(uint uchar) /*功能:NRF24L01的SPI写时序 /****************************************************************************************************/ uint NRF24L01_SPI_RW(uint uchar) //发送uchar数据,并返回接收到的数据 { uint bit_ctr; //位计数器,用于确定接收或者发送的位数,这里是一个字节即8位 for(bit_ctr=0;bit_ctr<8;bit_ctr++) { MOSI = (uchar & 0x80); // (output 'uchar', MSB to MOSI)输出数据, MSB to MOSI,即先送高位后送低位 uchar = (uchar << 1); // (shift next bit into MSB..)右移一位,准备传送下一个数据 SCK = 1; // (Set SCK high..)设置SCK为高 uchar |= MISO; // (capture current MISO bit )接收24L01传出的数据,他是先先送高位后送低位 SCK = 0; // (..then set SCK low again)拉低SCK时钟产生下降沿,从MSOI送出数据,在下一次SCK为高时读入MISO } return(uchar); // return read uchar } /**************************************************************************************************** /*函数:uchar SPI_Read(uchar reg) /*功能:NRF24L01的SPI时序 /****************************************************************************************************/ uchar NRF24L01_SPI_Read(uchar reg) { uchar reg_val; CSN = 0; // (CSN low, initialize SPI communication...)CSN拉低,启动SPI通信 NRF24L01_SPI_RW(reg); // (Select register to read from..)设置读取的寄存器 reg_val = NRF24L01_SPI_RW(0); // (..then read registervalue)读出寄存器中的数据 CSN = 1; // (CSN high, terminate SPI communication)CSN拉高,终止SPI通信 return(reg_val); // (return register value)返回接收到的数据 } /****************************************************************************************************/ /*功能:NRF24L01读写寄存器函数 /****************************************************************************************************/ uint NRF24L01_SPI_RW_Reg(uchar reg, uchar value) { uint status; CSN = 0; // (CSN low, init SPI transaction)SCN拉低,启动SPI通信 status = NRF24L01_SPI_RW(reg); // (select register)选择要操作的寄存器 NRF24L01_SPI_RW(value); // (..and write value to it..)向选择的寄存器中写入数据 CSN = 1; // (CSN high again)CSN拉高,终止SPI通信 return(status); // (return nRF24L01 status uchar)返回2401 reg寄存器的状态 } /****************************************************************************************************/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数 /****************************************************************************************************/ uint NRF24L01_SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) { uint status,uchar_ctr; CSN = 0; // Set CSN low, init SPI tranaction status = NRF24L01_SPI_RW(reg); // Select register to write to and read status uchar for(uchar_ctr=0;uchar_ctr /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于写数据,reg:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数 /*********************************************************************************************************/ uint NRF24L01_SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) { uint status,uchar_ctr; CSN = 0; //SPI使能 status = NRF24L01_SPI_RW(reg); for(uchar_ctr=0; uchar_ctr /****************************************************************************************************/ /*函数:void SetRX_Mode(void) /*功能:数据接收配置 /****************************************************************************************************/ void NRF24L01_SetRX_Mode(void) { CE=0; //片选使能 NRF24L01_SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收 CE = 1; //片选失能 inerDelay_us(130); } /******************************************************************************************************/ /*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) /*功能:数据读取后放如rx_buf接收缓冲区中 /******************************************************************************************************/ unsigned char NRF24L01_RxPacket(unsigned char* rx_buf) { unsigned char revale=0; NRF24L01_SetRX_Mode(); Delay(1000); sta=NRF24L01_SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状? if(RX_DR) // 判断是否接收到数据 { CE = 0; //SPI使能 NRF24L01_SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// (read receive payload from RX_FIFO buffer)从接收缓冲器中读出数据 revale =1; //读取数据完成标志 led2=0; //二极管显示接没接收到数据 } NRF24L01_SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清除中断标志 CSN=0; NRF24L01_SPI_RW(FLUSH_RX); //用于清空FIFO !!关键!!防止接收先前的数据! CSN=1; Delay(100); led2=1; return revale; } /*********************************************************************************************************** /*函数:void nRF24L01_TxPacket(unsigned char * tx_buf) /*功能:发送 tx_buf中数据 /**********************************************************************************************************/ void NRF24L01_TxPacket(unsigned char * tx_buf) { CE=0; //(StandBy I模式)待机 I模式 CSN=0; NRF24L01_SPI_RW(FLUSH_TX); //用于清空FIFO !!关键!!防止发送先前的数据! CSN=1; NRF24L01_SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 装载接收端地址0 NRF24L01_SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据 NRF24L01_SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送 CE=1; //置高CE,激发数据发送 inerDelay_us(10); } /****************************************************************************************************/ void main() { unsigned char TxBuf[TX_PLOAD_WIDTH]={0}; //定义发送的数据数组 unsigned char RxBuf[RX_PLOAD_WIDTH]={0}; //定义接收数据的数组 unsigned char tf=0; //模式标志 LCD_init(); //5110的初始化 LCD_clear(); //5110的清屏函数 NRF24L01_init(); //NRF24L01的初始化 LCD_write_english_string(3*6,0,\"acceptor\"); //字符串显示 while(1) { while(1) { NRF24L01_RxPacket(RxBuf); Delay(1000); LCD_write_english_string(3*6,1,RxBuf); if(KEY2==0) { //去抖延时 Delay(30); if(KEY2==0) { TxBuf[0]=0; //抢答模式 led1=0; Delay(120); led1=1; Delay(120); NRF24L01_TxPacket(TxBuf); while(!KEY2); } } if(KEY4==0) { Delay(30); //去抖延时 if(KEY4==0) {while(!KEY4);break;} } } TxBuf[0]=0; TxBuf[1]=0; LCD_write_english_string(2*6,1,\"jury mode\"); LCD_write_english_string(2*6,2,\"grade:\"); LCD_write_english_char(8*6,2,'0'); while(1) { if(KEY1==0) { Delay(30); //去抖延时 if(KEY1==0) { TxBuf[1]=TxBuf[1]+1; if(TxBuf[1]==11) TxBuf[1]=0; LCD_write_english_char(8*6,2,TxBuf[1]+0x30); LCD_write_english_char(9*6,2,' '); if(TxBuf[1]==10) { LCD_write_english_char(8*6,2,'1'); LCD_write_english_char(9*6,2,'0'); } led1=0; Delay(120); led1=1; Delay(120); while(!KEY1); } } if(KEY2==0) { Delay(30); //去抖延时 if(KEY2==0) { TxBuf[0]=1; //评委模式 NRF24L01_TxPacket(TxBuf); led1=0; Delay(120); led1=1; Delay(120); while(!KEY2); } } if(KEY3==0) { Delay(30); //去抖延时 if(KEY3==0) { if(TxBuf[1]==0) {TxBuf[1]=10;} else {TxBuf[1]=TxBuf[1]-1;} LCD_write_english_char(8*6,2,TxBuf[1]+0x30); LCD_write_english_char(9*6,2,' '); if(TxBuf[1]==10) { LCD_write_english_char(8*6,2,'1'); LCD_write_english_char(9*6,2,'0'); } led1=0; Delay(120); led1=1; Delay(120); while(!KEY3); } } if(KEY4==0) { Delay(30); //去抖延时 if(KEY4==0) {while(!KEY4);break;} } } LCD_write_english_string(2*6,1,\" \"); LCD_write_english_string(2*6,2,\" \"); TxBuf[0]=0; TxBuf[1]=0; } } /********************************************************************************** 修改日:2013/9/25 称号:起点 学校:桂林电子科技大学 QQ:978019740 本人现在正在写上位机的串口通信软件有什么意见的可以一起交流 **********************************************************************************/ 因篇幅问题不能全部显示,请点此查看更多更全内容/******************************************************************************************//******************************************************************************************/