基于24L01+1302+1602的无线传输及显示的时钟日历的51单片机程序

  • 格式:docx
  • 大小:35.49 KB
  • 文档页数:20

//发射#include <reg52.h>//发射#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;/*************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 14 // 20 uints TX payload#define RX_PLOAD_WIDTH 14 // 20 uints TX payload//***************************************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栈入栈出状态寄存器设置/*********NRF24L01端口定义**********/sbit IRQ =P1^0;sbit M OSI =P1^1;sbit CSN =P1^2;sbit M ISO =P1^3;sbit SCK =P1^4;sbit CE =P1^5;/**********定义1302管脚*******/sbit IO = P0^5; //6sbit SCLK = P0^6;//7sbit RST = P0^4; //5/**********定义1602管脚*******/sbit RS = P3^3;//4sbit RW = P3^4;//5sbit EN = P3^5;//6/**********定义调时键盘管脚*******/sbit key1=P0^0;//选择sbit key2=P0^1;//加sbit key3=P0^2;//减sbit key4=P0^3;//确定/**********定义闹铃管脚*******/sbit led = P0^7;//led代替闹铃/***********状态标志*****************/uint bdata sta;sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址unsigned char x1=0;int hour=8,minute=0;//闹钟的初始时间8:00unsigned char DateTime[9]; //秒,分,时,日,周,月,年//***********************************发送缓冲区uchar TxBuf[14]={0};unsigned char lcd1[]={"DATE 00-00-00 "};unsigned char lcd2[]={"TIME 00:00:00 "};/******************************************/void inerDelay_us(unsigned char n);void init_NRF24L01(void);uint SPI_RW(uint uchar);uchar SPI_Read(uchar reg);void SetRX_Mode(void);uint SPI_RW_Reg(uchar reg, uchar value);uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);void nRF24L01_TxPacket(unsigned char * tx_buf);//*****************************************长延时void delayms(unsigned int x)//延时毫秒程序{ unsigned j;unsigned int i;for(i=x;i>0;i--)for(j=110;j>0;j--);}void inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}/****************************************************************************** *********************************************************************//****************************************************************************** *********************************************************************//****************************************************************************** *********************************************************************//****************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=0; // Spi clock line init highSPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动ACK应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dBSPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送}/**************/*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序/******************/uint SPI_RW(uint uchar){uint bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit{MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSIuchar = (uchar << 1); // shift next bit into MSB..SCK = 1; // Set SCK high..uchar |= MISO; // capture current MISO bitSCK = 0; // ..then set SCK low again }return(uchar); // return read uchar}/*********NRF24L01的SPI时序**********uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; // CSN low, initialize SPI communication...SPI_RW(reg); // Select register to read from..reg_val = SPI_RW(0); // ..then read registervalueCSN = 1; // CSN high, terminate SPI communicationreturn(reg_val); // return register value}*//*******************//*功能:NRF24L01读写寄存器函数/*********************/uint SPI_RW_Reg(uchar reg, uchar value){uint status;CSN = 0; // CSN low, init SPI transactionstatus = SPI_RW(reg); // select registerSPI_RW(value); // ..and write value to it..CSN = 1; // CSN high againreturn(status); // return nRF24L01 status uchar}/******* 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数*************uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0; // Set CSN low, init SPI tranactionstatus = SPI_RW(reg); // Select register to write to and read status ucharfor(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)pBuf[uchar_ctr] = SPI_RW(0); //CSN = 1;return(status); // return nRF24L01 status uchar} *//**************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/**************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0; //SPI使能status = SPI_RW(reg);for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}/********数据接收配置*************void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收CE = 1;inerDelay_us(130); //延时不能太短} *//**********************unsigned char nRF24L01_RxPacket(unsigned char* rx_buf){unsigned char revale=0;sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况if(RX_DR) // 判断是否接收到数据{CE = 0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO bufferrevale =1; //读取数据完成标志}SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志return revale;} *//****************************/void nRF24L01_TxPacket(unsigned char * tx_buf){CE=0; //StandBy I模式SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送inerDelay_us(10);}/****************************************************************************** *********************************************************************//****************************************************************************** *********************************************************************//****************************************************************************** *********************************************************************//********1302的驱动程序***********///写入数据,dat:要写入的数据void DS1302WriteByte(unsigned char dat){unsigned char i;SCLK=0;//初始时钟线置为0inerDelay_us(2);for(i=0;i<8;i++)//开始传输8个字节的数据{IO=dat&0x01;//取最低位,注意DS1302的数据和地址都是从最低位开始传输的inerDelay_us(2);SCLK=1;//时钟线拉高,制造上升沿,SDA的数据被传输inerDelay_us(2);SCLK=0;//时钟线拉低,为下一个上升沿做准备dat>>=1;//数据右移一位,准备传输下一位数据}}/********1302的驱动程序**********///功能: 读取数据,dat:读取的数据unsigned char DS1302ReadByte(){ unsigned char i;unsigned char dat;inerDelay_us(2);for(i=0;i<8;i++){dat>>=1;//要返回的数据左移一位if(IO==1)//当数据线为高时,证明该位数据为1dat|=0x80;//要传输数据的当前值置为1,若不是,则为0SCLK=1;//拉高时钟线inerDelay_us(2);SCLK=0;//制造下降沿inerDelay_us(2);}return dat;//返回读取出的数据/16*10+dat%16}/*********1302的驱动程序*********///从cmd相应地址中读取一个字节的数据unsigned char DS1302Read(unsigned char cmd)//cmd:要写入的控制字节,dat:读取的数据{unsigned char dat;RST=0;//初始CE线置为0SCLK=0;//初始时钟线置为0RST=1;//初始CE置为1,传输开始DS1302WriteByte(cmd);//传输命令字,要读取的时间/日历地址dat=DS1302ReadByte();//读取要得到的时间/日期SCLK=1;//时钟线拉高RST=0;//读取结束,CE置为0,结束数据的传输return dat;//返回得到的时间/日期}/**********1302的驱动程序*********///向cmd相应地址中写一个字节的数据void DS1302Write(unsigned char cmd, unsigned int dat)//cmd:要写入的控制字,dat:要写入的数据{RST=0; //初始CE线置为0SCLK=0; //初始时钟线置为0RST=1; //初始CE置为1,传输开始DS1302WriteByte(cmd); //传输命令字,要写入的时间/日历地址DS1302WriteByte(dat); //写入要修改的时间/日期SCLK=1; //时钟线拉高RST=0; //读取结束,CE置为0,结束数据的传输}/*************初始化ds1302********///给1302写入日期和时钟的值void chushihuaDS1302(void){DS1302Write(0x8e,0x00);//写保护关DS1302Write(0x80,0x10); //初始秒DS1302Write(0x82,0x44);//初始分钟DS1302Write(0x84,0x21); //初始为24小时模式,初始时DS1302Write(0x86,0x22); //1日DS1302Write(0x88,0x08);//8月DS1302Write(0x8c,0x13);//2013年DS1302Write(0x8a,0x04);//星期4// DS1302Write(0x90,0x01); //充电//DS1302Write(0xc0,0xf0); //初始化一次标示//DS1302Write(0x8e,0x80);//写保护开}/************以下是1602的程序******************//******************************///向1602内写命令void write_order(unsigned char order){RS=0;P2=order;delayms(5);EN=1;delayms(5);EN=0;}/******************************///向1602内写数据void write_date(unsigned char date){RS=1;P2=date;delayms(5);EN=1;delayms(5);EN=0;}/******************************///lcd1602的初始化void chushihuaLCD1602(){ EN=0;write_order(0x38);write_order(0x0c);write_order(0x06);write_order(0x01);}/*************其他操作*****************/void gettime(){ unsigned char i,n;for(i=0,n=1;i<7,n<15;i++,n=n+2){ DateTime[i]=DS1302Read(0x80+n);inerDelay_us(1);}}void zhuanhuan(){ gettime();lcd1[5]=((DateTime[6]>>4)+0x30);lcd1[6]=((DateTime[6]&0x0f)+0x30);inerDelay_us(2);//年lcd1[14]=((DateTime[5]>>4)+0x30);lcd1[15]=((DateTime[5]&0x0f)+0x30);inerDelay_us(2);//周lcd1[11]=((DateTime[3]>>4)+0x30);lcd1[12]=((DateTime[3]&0x0f)+0x30);inerDelay_us(2);//日lcd1[8]=((DateTime[4]>>4)+0x30);lcd1[9]=((DateTime[4]&0x0f)+0x30);inerDelay_us(2);//月lcd2[5]=((DateTime[2]>>4)+0x30);lcd2[6]=((DateTime[2]&0x0f)+0x30);inerDelay_us(2);//时lcd2[8]=((DateTime[1]>>4)+0x30);lcd2[9]=((DateTime[1]&0x0f)+0x30);inerDelay_us(2);//分lcd2[11]=((DateTime[0]>>4)+0x30);lcd2[12]=((DateTime[0]&0x0f)+0x30);inerDelay_us(2);//秒TxBuf[12]=lcd2[11];TxBuf[13]=lcd2[12];//秒的个位和十位TxBuf[0]=lcd2[9];TxBuf[1]=lcd2[8];//分的个位和十位TxBuf[2]=lcd2[6];TxBuf[3]=lcd2[5];//时的个位和十位TxBuf[4]=lcd1[12];TxBuf[5]=lcd1[11];//天的个位和十位TxBuf[6]=lcd1[15];TxBuf[7]=lcd1[14];//周的个位和十位TxBuf[8]=lcd1[9];TxBuf[9]=lcd1[8];//月的个位和十位TxBuf[10]=lcd1[6];TxBuf[11]=lcd1[5];//年的个位和十位/**/if(DateTime[7]==DateTime[2] & DateTime[8]==DateTime[1])//闹钟{led = 1;delayms(150);led = 0;}}/********键盘调时+闹钟调时***************/void jianpan(){ unsigned char x2,address,max,min;int item;if(key1==0){ delayms(10);if(key1==0){ x1++;if(x1>=9) x1=1;switch(x1){ case 1: lcd2[13]=' ';lcd2[14]=' ';lcd2[15]='Y';x2=1;address=0x8c; max=99;min=0;break;//年case 2: lcd2[13]=' ';lcd2[14]=' ';lcd2[15]='M';x2=2;address=0x88; max=12;min=1;break;//月case 3: lcd2[13]=' ';lcd2[14]=' ';lcd2[15]='D';x2=3;address=0x86; max=31;min=1;break;//天case 4: lcd2[13]=' ';lcd2[14]=' ';lcd2[15]='H';x2=4;address=0x84; max=23;min=0;break;//时case 5: lcd2[13]=' ';lcd2[14]=' ';lcd2[15]='F';x2=5;address=0x82; max=59;min=0;break;//分case 6: lcd2[13]=' ';lcd2[14]=' ';lcd2[15]='W';x2=6;address=0x8A; max=7;min=1;break;//周/**********************/case 7: lcd2[13]='M';x2=7;max=59;min=0;lcd2[14]=((minute>>4)+0x30);lcd2[15]=((minute&0x0f)+0x30);inerDelay_us(2);break;//分case 8: lcd2[13]='H';x2=8;max=23;min=0;lcd2[14]=((hour>>4)+0x30);lcd2[15]=((hour&0x0f)+0x30);inerDelay_us(2);break;//时}}while(!key1);}item=(DS1302Read(address+1)/16)*10 + (DS1302Read(address+1))%16;if(key2==0){ delayms(10);if(key2==0){ if(x2==1) {item++;}else if(x2==2) {item++;}else if(x2==3) {item++;}else if(x2==4) {item++;}else if(x2==5) {item++;}else if(x2==6) {item++;}/**********************/else if(x2==7)//分{ minute=((minute/16)*10)+(minute%16);minute++;if(minute>max) minute=min;minute=(minute/10)*16+minute%10;lcd2[14]=((minute>>4)+0x30);lcd2[15]=((minute&0x0f)+0x30);inerDelay_us(2);}else if(x2==8)//时{hour=((hour/16)*10)+(hour%16);hour++;if(hour>max) hour=min;hour=(hour/10)*16+hour%10;lcd2[14]=((hour>>4)+0x30);lcd2[15]=((hour&0x0f)+0x30);inerDelay_us(2);}}while(!key2);}if(key3==0){ delayms(10);if(key3==0){ if(x2==1) {item--;}else if(x2==2) {item--;}else if(x2==3) {item--;}else if(x2==4) {item--;}else if(x2==5) {item--;}else if(x2==6) {item--;}/**********************/else if(x2==7)//分{ minute=((minute/16)*10)+(minute%16);minute--;if(minute<min) minute=max;minute=(minute/10)*16+minute%10;lcd2[14]=((minute>>4)+0x30);lcd2[15]=((minute&0x0f)+0x30);inerDelay_us(2);}else if(x2==8)//时{ hour=((hour/16)*10)+(hour%16);hour--;if(hour<min) hour=max;hour=(hour/10)*16+hour%10;lcd2[14]=((hour>>4)+0x30);lcd2[15]=((hour&0x0f)+0x30);inerDelay_us(2);}}while(!key3);}if(key4==0){ delayms(10);if(key4==0){ lcd2[13]=' ';lcd2[14]=' ';lcd2[15]=' ';x1=0;x2=0;}while(!key4);}DateTime[7]=hour;DateTime[8]=minute;if(item>max) item=min;if(item<min) item=max;DS1302Write(0x8e,0x00);//允许写操作delayms(10);DS1302Write(address,(item/10)*16+item%10); //写入DS1302 //转成BCD码delayms(20);DS1302Write(0x8e,0x80);//写保护,禁止写操作}void wzd0() interrupt 0//外部中断0{jianpan();//}//************************************主函数//发射void main(void){unsigned char k;EA=1;EX0=1;IT0=1; RW=0;led=0;init_NRF24L01() ;//nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer datachushihuaLCD1602();//1602初始化if( (DS1302Read(0x81) & 0x80) ) chushihuaDS1302();//1302初始化delayms(85);while(1){ zhuanhuan();write_order(0x80);//lcd的第一行for(k=0;k<16;k++){ write_date(lcd1[k]);inerDelay_us(2);}write_order(0x80+0x40);//lcd的第二行for(k=0;k<16;k++){ write_date(lcd2[k]);inerDelay_us(2);}/****************************************************************/nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer datadelayms(30); //可变SPI_RW_Reg(WRITE_REG+STATUS,0XFF);delayms(12);}}//////////////////////////////////////////////////////////////////////////// ///////////////接收#include <reg52.h> //接收#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;/**************/#define TX_ADR_WIDTH 5 // 5 uints TX address width#define RX_ADR_WIDTH 5 // 5 uints RX address width#define TX_PLOAD_WIDTH 14 // 20 uints TX payload#define RX_PLOAD_WIDTH 14 // 20 uints TX payload//***************************************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栈入栈出状态寄存器设置/********************NRF24L01端口定义********************/sbit IRQ =P1^0;sbit M OSI =P1^1;sbit CSN =P1^2;sbit M ISO =P1^3;sbit SCK =P1^4;sbit CE =P1^5;/**********定义1602管脚*******/sbit RS = P2^5;sbit RW = P2^6;sbit EN = P2^7;/************状态标志*************************/uint bdata sta;sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;unsigned char lcd1[]={"DATE 00-00-00 "};unsigned char lcd2[]={"TIME 00:00:00 "};uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址/*****************************************************************************/ void inerDelay_us(unsigned char n);void init_NRF24L01(void);uint SPI_RW(uint uchar);uchar SPI_Read(uchar reg);void SetRX_Mode(void);uint SPI_RW_Reg(uchar reg, uchar value);uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);void nRF24L01_TxPacket(unsigned char * tx_buf);//*****************************************长延时void delayms(unsigned int x)//延时毫秒程序{ unsigned j;unsigned int i;for(i=x;i>0;i--)for(j=110;j>0;j--);}void delayus(unsigned char x)//延时微秒程序{ unsigned char i;for(i=0;i<x;i++);}void inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}/*******************NRF24L01初始化**********************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=0; // Spi clock line init highSPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动ACK应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dBSPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收}/***********************************/uint SPI_RW(uint uchar){uint bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit{MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSIuchar = (uchar << 1); // shift next bit into MSB..SCK = 1; // Set SCK high..uchar |= MISO; // capture current MISO bitSCK = 0; // ..then set SCK low again}return(uchar); // return read uchar}/************************************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; // CSN low, initialize SPI communication...SPI_RW(reg); // Select register to read from..reg_val = SPI_RW(0); // ..then read registervalueCSN = 1; // CSN high, terminate SPI communicationreturn(reg_val); // return register value}/*****************************************************************************/ /*功能:NRF24L01读写寄存器函数/*****************************************************************************/ uint SPI_RW_Reg(uchar reg, uchar value){uint status;CSN = 0; // CSN low, init SPI transactionstatus = SPI_RW(reg); // select registerSPI_RW(value); // ..and write value to it..CSN = 1; // CSN high againreturn(status); // return nRF24L01 status uchar}/*****************************************************************************/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数/*****************************************************************************/ uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0; // Set CSN low, init SPI tranactionstatus = SPI_RW(reg); // Select register to write to and read status ucharfor(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)pBuf[uchar_ctr] = SPI_RW(0); //CSN = 1;return(status); // return nRF24L01 status uchar}/****************************************************************************** /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/*****************************************************************************/ uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0; //SPI使能status = SPI_RW(reg);for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}/*****************************************************************************/ /*函数:void SetRX_Mode(void)/*功能:数据接收配置/*****************************************************************************/ void SetRX_Mode(void){CE=0;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;sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况if(RX_DR) // 判断是否接收到数据{CE = 0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO bufferrevale =1; //读取数据完成标志}SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志return revale;}/**************发送tx_buf中数据****************/void nRF24L01_TxPacket(unsigned char * tx_buf){CE=0; //StandBy I模式SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送inerDelay_us(10);}/****************串口初始化********************/void StartUART( void ){ //波特率4800SCON = 0x50;TMOD = 0x20;TH1 = 0xFA;TL1 = 0xFA;PCON = 0x00;TR1 = 1;}//************************************通过串口将接收到的数据发送给PC端void R_S_Byte(uchar R_Byte){SBUF = R_Byte;while( TI == 0 ); //查询法TI = 0;}/************以下是1602的程序******************************************************************************* **************************************//******************************///向1602内写命令void write_order(unsigned char order){RS=0;P0=order;delayms(5);EN=1;delayms(5);EN=0;}/******************************///向1602内写数据void write_date(unsigned char date){RS=1;P0=date;delayms(5);EN=1;delayms(5);EN=0;}/******************************///lcd1602的初始化void chushihuaLCD1602(){ EN=0;write_order(0x38);write_order(0x0c);write_order(0x06);write_order(0x01);}/**************主函数**********************///////接收void main(void){uchar i;unsigned char k;uchar RxBuf[14]={0};RW=0;chushihuaLCD1602();//1602初始化init_NRF24L01() ;StartUART();delayms(60);while(1){SetRX_Mode();if(nRF24L01_RxPacket(RxBuf)){for(i=0;i<14;i++){R_S_Byte(RxBuf[i]);delayms(8);}lcd1[6]=RxBuf[10];lcd1[5]=RxBuf[11];delayus(2);//年lcd1[15]=RxBuf[6];lcd1[14]=RxBuf[7];delayus(2);//周lcd1[12]=RxBuf[4];lcd1[11]=RxBuf[5];delayus(2);//日lcd1[9]=RxBuf[8];lcd1[8]=RxBuf[9];delayus(2);//月lcd2[6]=RxBuf[2];lcd2[5]=RxBuf[3];delayus(2);//时lcd2[9]=RxBuf[0];lcd2[8]=RxBuf[1];delayus(2);//分lcd2[11]=RxBuf[12];lcd2[12]=RxBuf[13];delayus(2);//秒}delayms(6);write_order(0x80);//lcd的第一行for(k=0;k<16;k++){ write_date(lcd1[k]);delayus(2);}write_order(0x80+0x40);//lcd的第二行for(k=0;k<16;k++){ write_date(lcd2[k]);delayus(2);}}}。