仿百科荣创小车通信,nRF24L01实现单片机之间传输数据,易懂稳定的通信协议

仿百科荣创小车通信,使用nRF24L01实现多块单片机通信

开发平台51单片机、艾姆克EasySTC8_V2.0系统板(可实现不同型号单片机无线通信)

以下为具体内容

1. (半双工)测试搭建使用的平台

主端艾克姆EsaySTC8开发板+LCD12864+nRF24L01p
在这里插入图片描述

副端STC15最小系统板+nRF24L01p

在这里插入图片描述

2. 实际运用

启动时,副端监听,主端发送数据,当副端接收到命令,执行后续程序,此时主端可在发送完数据执行监听,当副端执行完任务,可发送数据给主端,主段继续执行接下来的任务。与百科荣创嵌入式智能小车实际ZigBee通信类似,它是两辆编程车与一个控制任务平台使用。

3. 原理

驱动代码:基于艾姆克EasySTC8_V2.0系统板初始nRFL01p测试的驱动代码,添加LCD12864驱动代码,无需添加其他驱动代码。
添加的函数:修改nRF24L01p发送地址函数,LCD12864显示字符函数(非指针),发送数据函数和接收数据函数。
关键的变量:无线接收数组和无线发送数组,无线接收和无线发射缓存的首位缓存,nRF24L01p的发送和接收地址两个地址数组(很重要)。
关键的算法:8位数据校验位算法。
发送原理: (注释二次的是预留测试程序)

/***************************************************************************
 * 描  述 : NRF24L01设置发送地址函数
 * 入  参 : x包头,y主指令,z副指令,c副指令,v副指令(详情看模仿的通信协议)
 * 返回值 : 无
 **************************************************************************/
 void TX_ADDRESS_Configure(uint8 x,uint8 y,uint8 z,uint8 c,uint8 v){
   TX_ADDRESS[0]=x;
   TX_ADDRESS[1]=y;
   TX_ADDRESS[2]=z;
   TX_ADDRESS[3]=c;
   TX_ADDRESS[4]=v;
   Set_TxMode_MA();//nRF24L01p写入发送地址,转为发送模式
 }
/***************************************************************************
 * 描  述 : 发送数据函数
 * 入  参 : x包头,y主指令,z副指令,c副指令,v副指令(详情看模仿的通信协议)
 * 返回值 : 无
 **************************************************************************/
void TXnRF(uint8 x,uint8 y,uint8 z,uint8 c,uint8 v){
 uint8 i;
 switch(x){//注意接收地址要先去nRF24l01p.c里配置,相当于单片机的手机号,不配置就收不到
  case 1:
   TX_ADDRESS_Configure(0xE1,0xE2,0xE3,0xE4,0xE5);//对应第一块单片机的接收地址
   break;
  case 2:
   TX_ADDRESS_Configure(0xE1,0xE2,0xE3,0xE4,0xE5);//对应第二块单片机的接收地址
   break;
  case 3:
   TX_ADDRESS_Configure(0xE1,0xE2,0xE3,0xE4,0xE5);//对应第三块单片机的接收地址
   break;
  default:
   break;
 }//自行更改,这里只是示范
 delay_ms(50);//可删除
 TxData[1]=x;
 TxData[2]=y;
 TxData[3]=z;
 TxData[4]=c;
 TxData[5]=v;//这里懒得写了,直接了当的替换
 TxData[6] = (TxData[2] + TxData[3] + TxData[4] + TxData[5]) % 256;//校验位算法
 
 for(i=0;i<8;i++){
  TxPayload[0]=TxData[i];//写入无线发送缓存
  if(NRF24L01_MA_TxPacket(TxPayload) == MAX_TX)   //如果发送成功
   {
     Disp2(2,i,1,TxData[i]+0x30);//显示数字,但有间隔
   }
   delay_ms(50);//延时可调整,根据环境最小27ms,建议50ms
 }//自行更改,这里只是示范
 led=~led;//NRF24L01模块状态指示灯翻转
 delay_ms(20);//等待NRF24L01p硬件响应,自行调整
}
int main()            //主函数 
{     
   Init_NRF24L01_MA();         //初始化
   Ini_Lcd();                           //液晶初始化子程序
   Disp(1,0,16,"LCD12864检测成功");
   // Disp2(2,0,2,5+0x30-1);//覆盖显示,这种方式不改变驱动代码的情况下,可以做到增加显示位数,
   //每位是原位数加1,详情看后面第二种显示方法
   while(1)
   {  
     TXnRF(1,1,2,3,4);//添加发送或接收数据函数或者需要执行的命令
     //RXnRF();//添加发送或接收数据函数或者需要执行的命令
   }
 } 

接收原理:

/***************************************************************************
 * 描  述 : 接收数据函数
 * 入  参 : 无参
 * 返回值 : 无
 **************************************************************************/
void RXnRF(){
	uint8 i,j=0,k=0;
	RxPayload[0]=0x00;
	Set_RxMode_MA();//配置nRF24L01为接收模式
	Disp2(2,1,1,5+0x30);
	//delay_ms(20);
	while(1){
	if(NRF24L01_MA_RxPacket(RxPayload) == RX_OK)	//如果接收成功
	{   		
	  if(RxPayload[0]==0xBB){//收到的是包尾,关闭k标志位,j计数复位
	    j=0;
	    k=0;
	    led2=1;
	    led=0;
	    Disp2(3,0,1,RxData[0]-0x25);//显示数字,但有间隔
	    Disp2(3,6,1,RxData[6]+0x2F);//显示数字,但有间隔
	    Disp2(3,7,1,RxData[7]-0x88);//显示数字,但有间隔
	    for(i=1;i<6;i++){
	      Disp2(4,i,1,RxData[i]+0x30);//显示数字,但有间隔
	    }
	   if(RxData[6]==((RxData[2] + RxData[3] + RxData[4] + RxData[5]) % 256)){
	   //校验位算法
	     for(i=1;i<6;i++){
		Disp2(2,i,1,RxData[i]+0x30);//显示数字,但有间隔
	     }

//	     {//第二种,覆盖显示,充分利用LCD12864
//	     Disp2(3,0,5,RxData[4]+0x30-4);
//	     Disp2(3,0,4,RxData[3]+0x30-3);
//	     Disp2(3,0,3,RxData[2]+0x30-2);
//	     Disp2(3,0,2,RxData[1]+0x30-1);
//	     Disp2(3,0,1,RxData[0]+0x30);
//	     }						
	     }
 //这块显示也可改成单片机动作,比如处理数据、显示数据在数码管上、开关蜂鸣器、开关LED、验证密钥等。
	  break;
	  }
	  if(RxPayload[0]==0x55){//收到的是包头,开启k标志位,j计数复位
	    led2=0;
	    led=1;
	    k=1;
	    j=0;
	    //Disp(2,0,16,"                ");//第二行清空
	    //led=~led;//NRF24L01模块状态指示灯翻转
	    }
	    if(k==1){
	      RxData[j]=RxPayload[0];//保存接收到的数据
	      Disp2(2,j,1,RxPayload[0]+0x30);//显示数字,但有间隔
	      j++;
	     }
	     RxPayload[0] = 0;	//清除
	  }//自行更改,这里只是示范
        }
delay_ms(500);
	
	
Disp(3,0,16,"                ");
Disp(4,0,16,"                ");
}
//这里复制时对齐有问题,我也不知道为什么。
/***************************************************************************
 * 描  述 : 主函数
 * 入  参 : 无
 * 返回值 : 无
 **************************************************************************/
int main()            //主函数 
{     
 Init_NRF24L01_MA();         //初始化
 Ini_Lcd();                           //液晶初始化子程序
 Disp(1,0,16,"LCD12864检测成功");
// Disp2(2,0,2,5+0x30-1);//这种方式不改变驱动代码的情况下,可以做到增加显示位数,每位是原位数加1,详情看后面第二种显示方法
  while(1)//循环监听
  {  
  //TXnRF(1,1,2,3,4);//添加发送或接收数据函数或者需要执行的命令
  RXnRF();//添加发送或接收数据函数或者需要执行的命令
 }
} 

4. 存在的BUG:

副端平台采用杜邦线连接,始终无法接收到数据,用初始程序也无法收到,但互换程序主端可成功接收到数据,采用其他单片机平台建议替换 头文件.h 并用初始测试工程测试。
5月31日已解决,原14口接到16口,导致接收不到。

4. 查阅资料:

ASCII.html

2019智能嵌入式实训系统通信协议V4.2.pdf

CSDN:Vcc海波
2020年5月29日首发,使用/二创请注明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vcc海波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值