/*******************************************************
** 温度无线发送程序
** 时间:2012.2.3
** ——by Keliwen
*******************************************************/
#include
#include
#include
#include
typedef unsigned char uchar;
typedef unsigned int uint;
/***************************************************/
#define TX_ADR_WIDTH 5 // 5字节宽度的发送/接收地址
#define TX_PLOAD_WIDTH 4 // 数据通道有效数据宽度
uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // 定义一个静态发送地址
uchar RX_BUF[TX_PLOAD_WIDTH];
uchar TX_BUF[TX_PLOAD_WIDTH];
sbit CSN = P1^0; // Chip Enable pin signal (output)
sbit MOSI= P1^1; // Slave Select pin, (output to CSN, nRF24L01)
sbit IRQ = P1^2; // Interrupt signal, from nRF24L01 (input)
sbit MISO= P1^3; // Master In, Slave Out pin (input)
sbit SCLK= P1^4; // Serial Clock pin, (output)
sbit CE = P1^5; // Master Out, Slave In pin (output)
// SPI(nRF24L01) commands
#define READ_REG 0x00 // Define read command to register
#define WRITE_REG 0x20 // Define write command to register
#define RD_RX_PLOAD 0x61 // Define RX payload register address
#define WR_TX_PLOAD 0xA0 // Define TX payload register address
#define FLUSH_TX 0xE1 // Define flush TX register command
#define FLUSH_RX 0xE2 // Define flush RX register command
#define REUSE_TX_PL 0xE3 // Define reuse TX payload register command
#define NOP 0xFF // Define No Operation, might be used to read status register
// SPI(nRF24L01) registers(addresses)
#define CONFIG 0x00 // 'Config' register address
#define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address
#define EN_RXADDR 0x02 // 'Enabled RX addresses' register address
#define SETUP_AW 0x03 // 'Setup address width' register address
#define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address
#define RF_CH 0x05 // 'RF channel' register address
#define RF_SETUP 0x06 // 'RF setup' register address
#define STATUS 0x07 // 'Status' register address
#define OBSERVE_TX 0x08 // 'Observe TX' register address
#define CD 0x09 // 'Carrier Detect' register address
#define RX_ADDR_P0 0x0A // 'RX address pipe0' register address
#define RX_ADDR_P1 0x0B // 'RX address pipe1' register address
#define RX_ADDR_P2 0x0C // 'RX address pipe2' register address
#define RX_ADDR_P3 0x0D // 'RX address pipe3' register address
#define RX_ADDR_P4 0x0E // 'RX address pipe4' register address
#define RX_ADDR_P5 0x0F // 'RX address pipe5' register address
#define TX_ADDR 0x10 // 'TX address' register address
#define RX_PW_P0 0x11 // 'RX payload width, pipe0' register address
#define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address
#define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address
#define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address
#define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address
#define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address
#define FIFO_STATUS 0x17 // 'FIFO Status Register' register address
uchar bdata Sta;
uchar code Dis[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阳数码管花数。bit flag=0;
sbit DQ=P3^0;
void Delay(uint t)
{
while(t--)
{}
}
/*初始化IO*/
void Init_IO(void)
{
CE=0; //待机
CSN=1; //SPI标止
SCLK=0; //SPI时钟置低
IRQ=1; //中断复位
}
/*根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节*/
uchar SPI_Write_Read(uchar Byte)
{
uchar i;
for(i=0;i<8;i++) // 循环8次
{
MOSI=(Byte&0x80); // byte最高位输出到MOSI
Byte<<=1; // 低一位移位到最高位
SCLK=1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据
Byte |=MISO; // 读MISO到byte最低位
SCLK=0; // SCK置低
}
return Byte; // 返回读出的一字节
}
/*写数据value到reg寄存器*/
uchar SPI_Write_Read_Register(uchar Reg,uchar value)
{
uchar Status;
CSN=0; // CSN置低,开始传输数据
Status=SPI_Write_Read(Reg); // 选择寄存器,同时返回状态字
SPI_Write_Read(value); // 然后写数据到该寄存器
CSN=1; // CSN拉高,结束数据传输
return Status; // 返回状态寄存器
}
/*从reg寄存器读一字节*/
/*uchar SPI_Read(uchar Reg)
{
uchar result;
CSN=0; // CSN置低,开始传输数据
SPI_Write_Read(Reg); // 选择寄存器
result=SPI_Write_Read(0); // 然后从该寄存器读数据
CSN=1; // CSN拉高,结束数据传输
return result; // 返回寄存器数据
} */
/*从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址*/
/*uchar SPI_Read_Buffer(uchar Reg,uchar *Buf,uchar Bytes)
{
uchar Status,i;
CSN=0; // CSN置低,开始传输数据
Status=SPI_Write_Read(Reg); // 选择寄存器,同时返回状态字
for(i=0;i { Buf[i]=SPI_Write_Read(0);// 逐个字节从nRF24L01读出 } CSN=1; // CSN拉高,结束数据传输 return Status; // 返回状态寄存器 } */ /*把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址*/ uchar SPI_Write_Buffer(uchar Reg,uchar *Buf,uchar Bytes) { uchar Status,i; CSN=0; // CSN置低,开始传输数据 Status=SPI_Write_Read(Reg); // 选择寄存器,同时返回状态字 for(i=0;i { SPI_Write_Read(Buf[i]); // 逐个字节写入nRF24L01 } CSN=1; // CSN拉高,结束数据传输 return Status; // 返回状态寄存器 } /*设置nRF24L01为接收模式,等待接收发送设备的数据包*/ /*void RX_Mode(void) { CE=0; SPI_Write_Buffer(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);// 接收设备接收通道0使用和发送设备相同的发送地址 SPI_Write_Read_Register(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_Write_Read_Register(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 SPI_Write_Read_Register(WRITE_REG + RF_CH, 0x00); // 选择射频通道0x00 SPI_Write_Read_Register(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0选择和发送通道相同有效数据宽度 SPI_Write_Read_Register(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 SPI_Write_Read_Register(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式 CE=1; // 拉高CE启动接收设备 } */ /*设置nRF24L01为发送模式,(CE=1持续至少10us),130us后启动发射,数据发送结束后,发送模块自动转入接收模式等待应答信号*/ void TX_Mode(void) { CE=0; SPI_Write_Buffer(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写入发送地址 SPI_Write_Buffer(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 为了应答接收设备,接收通道0地址和发送地址相同 //SPI_Write_Buffer(WR_TX_PLOAD,Buffer, TX_PLOAD_WIDTH); // 写数据包到TX FIFO SPI_Write_Read_Register(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_Write_Read_Register(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 SPI_Write_Read_Register(WRITE_REG + SETUP_RETR, 0x0a); // 自动重发延时等待250us+86us,自动重发10次 SPI_Write_Read_Register(WRITE_REG + RF_CH, 0x00); // 选择射频通道0x00 SPI_Write_Read_Register(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 SPI_Write_Read_Register(WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电 CE=1; } /*检查接收设备有无接收到数据包,设定没有收到应答信号是否重发*/ uchar Check_Ack(bit Clear) { while(IRQ); Sta=SPI_Write_Read(NOP); // 返回状态寄存器 if(Sta^4) { if(Clear) // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发 SPI_Write_Read(FLUSH_TX); } SPI_Write_Read_Register(WRITE_REG + STA TUS, Sta); // 清除TX_DS或MAX_RT中断标志 IRQ=1; if(Sta^5) return 0x00; else return 0xff; } /************************************************************* ** 温度传感器DS18B20程序部分 *************************************************************/ void DS18B20_Reset(void) { uchar N; DQ=1; Delay(4); Delay(160); DQ=1; Delay(4); N=DQ; Delay(160); DQ=1; } void DS18B20_Write_Byte(uchar Dat) { uchar i; for(i=0;i<8;i++) { DQ=0; _nop_(); DQ=Dat & 0x01; Delay(8); DQ=1; Dat>>=1; } Delay(7); } uchar DS18B20_Read_Byte(void) { uchar i,Value; for(i=0;i<8;i++) { DQ=0; _nop_(); _nop_(); Value>>=1; DQ=1; _nop_(); _nop_(); _nop_(); _nop_(); if(DQ) Value |=0x80; Delay(10); } return Value; } uint Read_Temperature(void) { uint Temper; DS18B20_Reset(); DS18B20_Write_Byte(0xcc); DS18B20_Write_Byte(0x44); Delay(600); DS18B20_Reset(); DS18B20_Write_Byte(0xcc); DS18B20_Write_Byte(0xbe); i=DS18B20_Read_Byte();//LSB j=DS18B20_Read_Byte();//MSB Temper=j*256+i; Temper*=6.25; return Temper; } void Dis_Temperature(uint Temper) { uchar St[4]; St[0]=Temper/1000; St[1]=Temper%1000/100; St[2]=Temper%100/10; St[3]=Temper%10; P0=Dis[St[0]]; P2=0xf7; Delay(330); P0=Dis[St[1]]; P2=0xfb; Delay(330); P0=Dis[St[2]]; P2=0xfd; Delay(330); //P0=Dis[St[3]]; //P2=0xfe; //Delay(330); P0=0x00; P2=0xff; } void nRF24L01_TxPacket(uchar *Buffer) { CE=0; //StandBy I模式 SPI_Write_Buffer(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址 SPI_Write_Buffer(WR_TX_PLOAD,Buffer, TX_PLOAD_WIDTH); // 装载数据 // SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16 位CRC,主发送 CE=1; //置高CE,激发数据发送 } /*主函数*/ void main(void) { uint TEMP; uchar Times; Init_IO(); TX_Mode(); do { if((Times++)>250) { Times=0; TEMP=Read_Temperature(); TX_BUF[0]=TEMP/10; nRF24L01_TxPacket(TX_BUF); Check_Ack(1); } Dis_Temperature(TEMP); } while(1); } /******************************************************* ** 温度无线接收程序 ** 时间:2012.2.3 ** ——by Keliwen *******************************************************/ #include #include #include #include typedef unsigned char uchar; typedef unsigned int uint; /***************************************************/ #define TX_ADR_WIDTH 5 // 5字节宽度的发送/接收地址 #define TX_PLOAD_WIDTH 4 // 数据通道有效数据宽度 uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // 定义一个静态发送地址 uchar RX_BUF[TX_PLOAD_WIDTH]; uchar TX_BUF[TX_PLOAD_WIDTH]; sbit CSN = P1^0; // Chip Enable pin signal (output) sbit MOSI= P1^1; // Slave Select pin, (output to CSN, nRF24L01) sbit IRQ = P1^2; // Interrupt signal, from nRF24L01 (input) sbit MISO= P1^3; // Master In, Slave Out pin (input) sbit SCLK= P1^4; // Serial Clock pin, (output) sbit CE = P1^5; // Master Out, Slave In pin (output) // SPI(nRF24L01) commands #define READ_REG 0x00 // Define read command to register #define WRITE_REG 0x20 // Define write command to register #define RD_RX_PLOAD 0x61 // Define RX payload register address #define WR_TX_PLOAD 0xA0 // Define TX payload register address #define FLUSH_TX 0xE1 // Define flush TX register command #define FLUSH_RX 0xE2 // Define flush RX register command #define REUSE_TX_PL 0xE3 // Define reuse TX payload register command #define NOP 0xFF // Define No Operation, might be used to read status register // SPI(nRF24L01) registers(addresses) #define CONFIG 0x00 // 'Config' register address #define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address #define EN_RXADDR 0x02 // 'Enabled RX addresses' register address #define SETUP_AW 0x03 // 'Setup address width' register address #define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address #define RF_CH 0x05 // 'RF channel' register address #define RF_SETUP 0x06 // 'RF setup' register address #define STATUS 0x07 // 'Status' register address #define OBSERVE_TX 0x08 // 'Observe TX' register address #define CD 0x09 // 'Carrier Detect' register address #define RX_ADDR_P0 0x0A // 'RX address pipe0' register address #define RX_ADDR_P1 0x0B // 'RX address pipe1' register address #define RX_ADDR_P2 0x0C // 'RX address pipe2' register address #define RX_ADDR_P3 0x0D // 'RX address pipe3' register address #define RX_ADDR_P4 0x0E // 'RX address pipe4' register address #define RX_ADDR_P5 0x0F // 'RX address pipe5' register address #define TX_ADDR 0x10 // 'TX address' register address #define RX_PW_P0 0x11 // 'RX payload width, pipe0' register address #define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address #define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address #define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address #define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address #define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address #define FIFO_STATUS 0x17 // 'FIFO Status Register' register address uchar bdata Sta; uchar code Dis[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阳数码管花数。bit flag=0; /*12232液晶引管定义*/ sbit CS=P0^2; sbit SID=P0^1; sbit CLK=P0^0; void Delay(uint t) { while(t--) {} } /*初始化IO*/ void Init_IO(void) { CE=0; //待机 CSN=1; //SPI标止 SCLK=0; //SPI时钟置低 IRQ=1; //中断复位 } /*根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节*/ uchar SPI_Write_Read(uchar Byte) { uchar i; for(i=0;i<8;i++) // 循环8次 { MOSI=(Byte&0x80); // byte最高位输出到MOSI Byte<<=1; // 低一位移位到最高位 SCLK=1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据 Byte |=MISO; // 读MISO到byte最低位 SCLK=0; // SCK置低 } return Byte; // 返回读出的一字节 } /*写数据value到reg寄存器*/ uchar SPI_Write_Read_Register(uchar Reg,uchar value) { uchar Status; CSN=0; // CSN置低,开始传输数据 Status=SPI_Write_Read(Reg); // 选择寄存器,同时返回状态字 SPI_Write_Read(value); // 然后写数据到该寄存器 CSN=1; // CSN拉高,结束数据传输 return Status; // 返回状态寄存器 } /*从reg寄存器读一字节*/ uchar SPI_Read(uchar Reg) { uchar result; CSN=0; // CSN置低,开始传输数据 SPI_Write_Read(Reg); // 选择寄存器 result=SPI_Write_Read(0); // 然后从该寄存器读数据 CSN=1; // CSN拉高,结束数据传输 return result; // 返回寄存器数据 } /*从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址*/ uchar SPI_Read_Buffer(uchar Reg,uchar *Buf,uchar Bytes) { uchar Status,i; CSN=0; // CSN置低,开始传输数据 Status=SPI_Write_Read(Reg); // 选择寄存器,同时返回状态字 for(i=0;i { Buf[i]=SPI_Write_Read(0);// 逐个字节从nRF24L01读出 } CSN=1; // CSN拉高,结束数据传输 return Status; // 返回状态寄存器 } /*把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址*/ uchar SPI_Write_Buffer(uchar Reg,uchar *Buf,uchar Bytes) { uchar Status,i; CSN=0; // CSN置低,开始传输数据 Status=SPI_Write_Read(Reg); // 选择寄存器,同时返回状态字 for(i=0;i { SPI_Write_Read(Buf[i]); // 逐个字节写入nRF24L01 } CSN=1; // CSN拉高,结束数据传输 return Status; // 返回状态寄存器 } /*设置nRF24L01为接收模式,等待接收发送设备的数据包*/ void RX_Mode(void) { CE=0; SPI_Write_Buffer(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);// 接收设备接收通道0使用和发送设备相同的发送地址 SPI_Write_Read_Register(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_Write_Read_Register(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 SPI_Write_Read_Register(WRITE_REG + RF_CH, 40); // 选择射频通道0x40 SPI_Write_Read_Register(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0选择和发送通道相同有效数据宽度 SPI_Write_Read_Register(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 SPI_Write_Read_Register(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式 CE=1; // 拉高CE启动接收设备 } /*设置nRF24L01为发送模式,(CE=1持续至少10us),130us后启动发射,数据发送结束后,发送模块自动转入接收模式等待应答信号*/ /*void TX_Mode(uchar *Buffer) { CE=0; SPI_Write_Buffer(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写入发送地址 SPI_Write_Buffer(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 为了应答接收设备,接收通道0地址和发送地址相同 SPI_Write_Buffer(WR_TX_PLOAD,Buffer, TX_PLOAD_WIDTH); // 写数据包到TX FIFO SPI_Write_Read_Register(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_Write_Read_Register(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 SPI_Write_Read_Register(WRITE_REG + SETUP_RETR, 0x0a); // 自动重发延时等待250us+86us,自动重发10次 SPI_Write_Read_Register(WRITE_REG + RF_CH, 40); // 选择射频通道0x40 SPI_Write_Read_Register(WRITE_REG + RF_SETUP, 0x07); // 数据传 输率1Mbps,发射功率0dBm,低噪声放大器增益 SPI_Write_Read_Register(WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电 CE=1; } */ /*检查接收设备有无接收到数据包,设定没有收到应答信号是否重发*/ uchar Check_Ack(bit Clear) { while(IRQ); Sta=SPI_Write_Read(NOP); // 返回状态寄存器 if(Sta^4) { if(Clear) // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发 SPI_Write_Read(FLUSH_TX); } SPI_Write_Read_Register(WRITE_REG + STA TUS, Sta); // 清除TX_DS或MAX_RT中断标志 IRQ=1; if(Sta^5) return 0x00; else return 0xff; } /************************************************************* ** LCD12232程序部分 *************************************************************/ /*写入一个数据或指令*/ void Send_DATA(uchar Data,uchar A) { uchar i,Dat; CS=0; switch(A) { case 0 : Dat=0xf8; break;//写指令 case 1 : Dat=0xfa; break;//写数据 default : break; } CLK=0; CS=1; for(i=0;i<8;i++) //发送第一字节:数据类型选择 { SID=Dat&0x80; CLK=0; CLK=1; Dat<<=1; } Dat=Data&0xf0; for(i=0;i<8;i++) //发送第一字节:8位数据高4位{ SID=Dat&0x80; CLK=0; CLK=1; Dat<<=1; } Dat=(Data<<4); for(i=0;i<8;i++) //发送第一字节:8位数据低4位{ SID=Dat&0x80; CLK=0; CLK=1; Dat<<=1; } CS=0; Delay(20); } /*12232液晶初始化*/ void LCD_Init(void) { Delay(60000); Send_DATA(0x02,0); Send_DATA(0x0c,0); Send_DATA(0x30,0); Send_DATA(0x06,0); Send_DATA(0x01,0); Delay(3000); } /*显示字符串*/ void Dis_str(uchar Addr,uchar *str) { Send_DATA(Addr,0); Delay(10); while(*str!='\0') { Send_DATA(*str,1); str++; Delay(10); } } /*主函数*/ void main(void) { uchar Temper; LCD_Init(); Dis_str(0x80,"当前温度:"); Init_IO(); RX_Mode(); do { Sta=SPI_Read(STATUS); if(Sta^6) { SPI_Read_Buffer(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH); flag=1; } SPI_Write_Read_Register(WRITE_REG + STATUS,Sta); // 清除RX_DS中断标志 if(flag) { flag=0; Temper=RX_BUF[0]; Send_DATA(0x92,0); Send_DATA(Temper%1000/100+0x30,1); Send_DATA(Temper%100/10+0x30,1); Send_DATA('.',1); Send_DATA(Temper%10+0x30,1); Send_DATA(0xa1,1);//"℃" Send_DATA(0xe6,1); Check_Ack(1); } Delay(60000); } while(1); } #include NRF24L01无线模块收发程序(实测成功多图) 本模块是NRF24L01无线传输模块,用于无线传输数据,距离不远,一般只是能够满足小距离的传输,目测是4-5m,价格一般是4元左右,可以方便的买到。 51最小系统学习板就可以,当时是用了两块学习板,一块用于发送,一块用于接收。 小车也是比较容易购到的,四个端口控制两个电机,两个控制一个电机,当两个端口高低电平不同时电机就会转动,即为赋值1和0是电机转动,赋值可以用单片机作用,当然这是小车启动部分,前进后退左转右转就是你赋值0和1的顺序问题了。 整体思路是用发射端的按键控制小车,即为按键按下就前进,再按其他按键实现其他功能,本次程序是在用NRF24L01发射数据在接收端用1602显示的基础上改变。 下面是程序源码(有好几个文件,分别创建) ////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////// #include #include #include'1602.h' #include'delay.h' #include 'nrf24l01.h' #define uint unsigned int #define uchar unsigned char uint Weight_Shiwu=1234; unsigned char KeyScan(void);//键盘扫描 // unsigned char KeyScan(void);//键盘扫描 //#define KeyPort P0 sbit KEY1 = P0^0; sbit KEY2 = P0^1; sbit KEY3 = P0^2; sbit KEY4 = P0^3; sbit KEY5 = P0^4; void main() { // char TxDate[4]; // LCD_Init(); //初始化液晶屏 // LCD_Clear(); //清屏 //下面是接收的NRF24L01的程序。 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include NRF24L01无线模块C语言程序 24MHz晶振 #include #include #include #include #include #include #define U8 unsigned char #define U16 unsigned int #define TX_ADDR_WITDH 5 //发送地址宽度设置为5个字节 #define RX_ADDR_WITDH 5 //接收地址宽度设置为5个字节 #define TX_DATA_WITDH 1//发送数据宽度1个字节 #define RX_DATA_WITDH 1//接收数据宽度1个字节 #define R_REGISTER 0x00//读取配置寄存器 #define W_REGISTER 0x20//写配置寄存器 #define R_RX_PAYLOAD 0x61//读取RX有效数据 #define W_TX_PAYLOAD 0xa0//写TX有效数据 #define FLUSH_TX 0xe1//清除TXFIFO寄存器 #define FLUSH_RX 0xe2//清除RXFIFO寄存器 #define REUSE_TX_PL 0xe3//重新使用上一包有效数据 #define NOP 0xff//空操作 #define CONFIG 0x00//配置寄存器 #define EN_AA 0x01//使能自动应答 #define EN_RXADDR 0x02//接收通道使能0-5个通道 #define SETUP_AW 0x03//设置数据通道地址宽度3-5 #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接收地址 //许多人都在找nrf24l01无线模块的c程序;我以前刚接触无线//时用的就是nrf24l01模块;搜索了许多程序有很多都没法直接用;甚至还怀疑模块是不是被我搞坏了;拿去让别人检测模块又是好的;为避免大家走弯路;我将我的程序发出来供大家参考; 这是nrf24l01无线模块pcb图; 下面有Nrf24l01无线模块的收发c程序;以下程序经本人亲自测试;绝对能用!! 请注意以下几点: 1、24L01模块的电源电压是否为3V-3.6V之间; 2、如果您用的单片机是5V的话,请在IO口与模块接口之间串一个1K电阻; 3、检查模块的GND是否与单片机的GND相连接 4、先用程序进行调试,如果IO口不同,请更改IO口或相关时序; 5、如果是51系列单片机,晶振请选用11.0592M Hz; 模块供电最好用asm1117 5v转3.3v 稳压 测试单片机是stc89c52;at89c52 通用; 收发一体; 一大截不废话了;上程序;此程序是按键控制led;当按下s的时候对应接受的led会闪闪发光;很简单的~如果要实现其他更先进的功能;自己发掘吧~~ 务必将硬件连接正确;否则;它不会工作的~~当然做什么都要严谨~~错一点就差大了~~ 《《收发一体程序》》 #include *************************************** sbit M ISO =P1^3; sbit M OSI =P1^4; sbit SCK =P1^2; sbit CE =P1^1; sbit CSN =P3^2; sbit IRQ =P3^3; //************************************按键*************************************************** sbit KEY=P2^0; //***************************************************************************** sbit led=P2^1; //*********************************************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}; //接收地址//***************************************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接收数据地址 NRF24L01使用文档 基于c8051f330单片机 目录 芯片简介 (3) 1 NRF24L01功能框图 (4) 2 NRF24L01状态机 (5) 3 Tx与Rx的配置过程 (7) 3.1 Tx 模式初始化过程 (7) 3.2 Rx模式初始化过程 (8) 4控制程序详解 (9) 4.1 函数介绍 (9) 4.1.1 uchar SPI_RW(uchar byte) (9) 4.1.2 uchar SPI_RW_Reg (uchar reg, uchar value) (10) 4.1.3 uchar SPI_Read (uchar reg); (10) 4.1.4 uchar SPI_Read_Buf (uchar reg, uchar *pBuf, uchar bytes); (11) 4.1.5 uchar SPI_Write_Buf (uchar reg, uchar *pBuf, uchar bytes); (11) 4.1.6 void RX_Mode(void) (12) 4.1.7 void TX_Mode(void) (13) 4.2 NRF24L01相关命令的宏定义 (13) 4.3 NRF24L01相关寄存器地址的宏定义 (14) 5 实际通信过程示波器图 (16) 1)发射节点CE与IRQ信号 (17) 2)SCK与IRQ信号(发送成功) (18) 3)SCK与IRQ信号(发送不成功) (19) 芯片简介 NRF24L01是NORDIC公司最近生产的一款无线通信通信芯片,采用FSK调制,内部集成NORDIC自己的Enhanced Short Burst 协议。可以实现点对点或是1对6的无线通信。无线通信速度可以达到2M(bps)。NORDIC公司提供通信模块的GERBER文件,可以直接加工生产。嵌入式工程师或是单片机爱好者只需要为单片机系统预留5个GPIO,1个中断输入引脚,就可以很容易实现无线通信的功能,非常适合用来为MCU系统构建无线通信功能。 NRF24L01 简易教程 先来看接口电路,使用的IO 口不是唯一的哦,可随意定义接口,当然是在使用IO 口模拟SPI 且IRQ 中断引脚不使用的使用查询方法判断接收状态的情况下了。作为初探我们就是用简单的IO 模拟SPI 的方法了,中断使用查询的方式。那么该教程讲解的接口与单片机的连接如下: 首先您需要了解NRF24L01,请参阅“NRF24L01 芯片中文资料”或者“NRF24L01 芯片英文资料”。 我们的教程是以一个简单的小项目为大家展示NRF24L01 的使用方法与乐趣。我们所写的教程均是以这种方式的呢,让您在学习的时候明白它能做什么,使您学起来不至于枯燥无味。 作为简易的教程,我们只需要知道它是怎么使用的就够了,我们本教程的目的是用NRF24L01 发送数据和接收数据,且接收方会对比发送的数据与接收的数据,若完全相同则控制LED 闪烁一次,并且把接收到的数据通过串口发送到PC 端,通过串口工具查看接收到的数据。 具体的要求如下: 1、具备发送和接收的能力。 2、发送32 个字节的数据,接收方接收到正确数据之后给予提示,通过LED 闪烁灯形 式。 3、把接收到的数据传送到PC 进行查看。 4、发送端每隔大约1.5 秒发送一次数据,永久循环。以上是程序的要求,若您想自行 设计出硬件接口,您也是可以添加一条呢:使用DIY 方 式设计NRF24L01 的接口板,且包含含单片机平台,使用PCB 方式或者万用板方式均可。如果您想让自己学的很扎实,那么推荐您自行做出接口板子呢。当然若您的能力不足,那么我们不推荐自行做板呢,因为这样会增加您学习的难度,反而起到了反效果呢。 我们使用的方式是画PCB 的方式呢,若您自己做了接口板子,那么您可以对比下一呢,O(∩_∩)O! 我们知道NRF24L01 的供电电压是1.9V~3.6V 不能超过这个范围,低了不工作,高了可能烧毁NRF24L01 芯片。我们常用的STC89C52 的单片机的供电电压是5V,我们不能直接给24L01 这个模块供电,我们需要使用AMS1117-3.3V 稳压芯片把5V 转成3.3V 的电压为24L01 模块供电。 为此我们的设计原理图如下:包含单片机最小系统、供电系统、下载程序接口、5V 转3.3V 电路、NRF24L01 模块接口。并且全部引出单片机的IO 口,另外还加了5 个电源输出接口,为扩展使用。还包括了电源指示LED 以及一个IO 口独立控制的LED,这个独立控制的LED用于NRF24L01 接收成功闪烁指示。为了保证系统的稳定性,在设计中添加了两个滤波电容。 (相关人员如觉得本人水平低下,还请见谅) Nrf24L01的使用程序和使用方法和简单操作: 功能: 无线对发程序。两个模块a,b,实现按下一个按键,会在对方的数码管上显示3或4,在本机上显示1,2。 当一个模块,比如a模块。当两个按键按下其中一个,则会在另一个模块b上显示数字3,4(具体根据按下哪个按键)。以上功能描述,B模块按键按下,如同a模块一样的功能,不做系统性描述了。 下面给出程序中几个地方的解释: #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 // 保留 类似这种的描述,可以等同于READ_REG =0x00;这个是经过实际程序测试出来的,比如 以下程序: #include MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSI uchar = (uchar << 1); // shift next bit into MSB.. SCK = 1; // Set SCK high.. uchar |= MISO; // capture current MISO bit SCK = 0; 此处为spi的核心,是spi协议的编程,其中uchar |= MISO; 表示uchar |= MISO | uchar; MOSI = (uchar & 0x80);其中0x80是1000 0000,与上uchar,这种&,是按位与,故可以从uchar提取出一个电平给mosi。 MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSI uchar = (uchar << 1); 这两句组合起来用,就实现了把uchar编程8位2进制数后的每一位都可以发送给mosi;Uchar的只待对象,就是上面的诸如#define FLUSH_TX 0xE1 这样的数,或者是相关的发送数据。 *pBuf这个并不是一个主要的问题,实际这个是涉及指针问题的,带*的跟地址有关系,但是我们其实不需要很关心编译的时候数据被具体存入哪个地址,即使是很重要的数据。 void init_NRF24L01(void) { inerDelay_us(100); CE=0; // chip enable CSN=1; // Spi disable SCK=0; // SPI_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,如果需要多频道可以参考Page21 SPI_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,发射功率为最大值0dB } 在整个初始化中我们看到: CE=0; // chip enable CSN=1; // Spi disable 这是设置整个的状态。如过状态设置成待机,则引脚可能变为高阻。(以上并非全部引脚) //***************************************************发送程序**********************************************************// #include //*********************************************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 32 // 20 uints TX payload #define RX_PLOAD_WIDTH 32 // 20 uints TX payload uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址 uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址 //***************************************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 // 可用信道设置 /******************************************************* ** 温度无线发送程序 ** 时间:2012.2.3 ** ——by Keliwen *******************************************************/ #include 1.简介 通过SPI方式与NRF24L01模块进行通讯,接收到的数据通过串口1打印出来,实时监测是否收到数据,发送的数据是“2.4G TEST”,当收不到数据时打印“no data”。一块STM32F103ZET6开发板接收数据,另一块STM32F103RBT6开发板发送数据,两个淘宝买的2.4G NRF24L01模块。还用到一块USB转TTL模块用来电平转换传送数据,串口调试助手接收串口发送数据。 2.代码部分 ---------nrf24l01.h----------- #ifndef __24L01_H #define __24L01_H #include "sys.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 NOP 0xFF //空操作,可以用来读状态寄存器 //SPI(NRF24L01)寄存器地址 #define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能; //bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能 #define EN_AA 0x01 //使能自动应答功能 bit0~5,对应通道0~5 #define EN_RXADDR 0x02 //接收地址允许,bit0~5,对应通道0~5 #define SETUP_AW 0x03 //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节; #define SETUP_RETR 0x04 //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时 250*x+86us #define RF_CH 0x05 //RF通道,bit6:0,工作通道频率; #define RF_SETUP 0x06 //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益 #define STATUS 0x07 //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发 //bit5:数据发送完成中断;bit6:接收数据中断; #define MAX_TX 0x10 //达到最大发送次数中断 #define TX_OK 0x20 //TX发送完成中断 先来看接口电路,使用的IO 口不是唯一的哦,可随意定义接口,当然是在使用IO 口模拟SPI 且IRQ 中断引脚不使用的使用查询方法判断接收状态的情况下了。作为初探我们就是用简单的IO 模拟SPI 的方法了,中断使用查询的方式。那么该教程讲解的接口与单片机的连接如下: 首先您需要了解NRF24L01,请参阅“NRF24L01 芯片中文资料”或者“NRF24L01 芯片英文资料”。 我们的教程是以一个简单的小项目为大家展示NRF24L01 的使用方法与乐趣。我们所写教程均是以这种方式的呢,让您在学习的时候明白它能做什么,使您学起来不至于枯燥无味。 作为简易的教程,我们只需要知道它是怎么使用的就够了,我们本教程的目的是用NRF24L01 发送数据和接收数据,且接收方会对比发送的数据与接收的数据,若完全相同则控制LED 闪烁一次,并且把接收到的数据通过串口发送到PC 端,通过串口工具查看接收到的数据。 具体的要求如下: 1、具备发送和接收的能力。 2、发送32 个字节的数据,接收方接收到正确数据之后给予提示,通过LED 闪烁灯形 式。 3、把接收到的数据传送到PC 进行查看。 4、发送端每隔大约1.5 秒发送一次数据,永久循环。 以上是程序的要求,若您想自行设计出硬件接口,您也是可以添加一条呢:使用DIY 方式设计NRF24L01 的接口板,且包含含单片机平台,使用PCB 方式或者万用板方式均可。如果您想让自己学的很扎实,那么推荐您自行做出接口板子呢。当然若您的能力不足,那么我们不推荐自行做板呢,因为这样会增加您学习的难度,反而起到了反效果呢。 我们知道NRF24L01 的供电电压是1.9V~3.6V 不能超过这个范围,低了不工作,高了可能烧毁NRF24L01 芯片。我们常用的STC89C52 的单片机的供电电压是5V,我们不能直接给24L01 这个模块供电,我们需要使用AMS1117-3.3V 稳压芯片把5V 转成3.3V 的电压为24L01 模块供电。 为此我们的设计原理图如下:包含单片机最小系统、供电系统、下载程序接口、5V 转3.3V 电路、NRF24L01 模块接口。并且全部引出单片机的IO 口,另外还加了5 个电源输出接口,为扩展使用。还包括了电源指示LED 以及一个IO 口独立控制的LED,这个独立控制的LED用于NRF24L01 接收成功闪烁指示。为了保证系统的稳定性,在设计中添加了两个滤波电容。 NRF24L01 MSP430发送接收程序 作者:codebaby 文章来源:codebaby 点击数: 1351 更新时间:2011-8-18 最近弄了几天的无线模块,玩的是NRF2L01,因为这款 无线模块价格便宜,网上也就卖10多块钱!刚开始用51 写,“百度一下”发现网上的程序真是百篇一律,你抄我, 我抄你。对比了几个程序之后,发现他们的程序注释也是 自相矛盾,看了的唯一收获就是,结合技术资料,对NR F24L01的工作模式和通信过程有了个总体的把握。 用51调了几次没成功,改而用430板子来写。在网上查 了一些相关的程序,终于成功了。现在发现其实要写对N RF24L01的基本通信程序并不难,当然要玩转它又是另外 一回事了。我也刚刚才玩会单通道接收发送这个工作模式,其他的工作模式还没玩!还是附上相应的程序供大家学习交流,当然程序可能难免还有疏漏和错误,还望比拼 指出! 这是NRF24L01的头文件配置程序: #include ////************************************接收程序******************************************************// #include NRF24L01发送程序
NRF24L01无线模块收发程序(实测成功 多图)
NRF24L01无线模块收发程序例程
NRF24L01无线模块C语言程序
nrf24l01无线模块NRF24L01模块收发c程序
NRF24L01功能使用文档
NRF24L01无线发射简易教程
NRF24L01参考程序(包含多个实例)
NRF24L01发送程序(可用)
nRF24L01温度发送与接收程序
SPI方式STM32F103与2.4G模块NRF24L01收发通讯
NRF24L01详细教程..
NRF24L01 MSP430发送接收程序
NRF24L01接收程序(可用)