上一期我们讲了一下实现无线聊天的简要步骤,我们运用之前实现的收发数据的效果加上无线控灯的运用就可以达到聊天的效果,就是ZigBee和串口的结合使用,那么我们怎么实现的呢?先创建一个函数来设置我们想要使用的名称,在函数里面我们通过串口询问的方式得到用户想要设置的名称:
//3.3 设置名字
void setName(void)
{
Delay(5000);
UartSend("请输入名字:",15);
while(1)
{
//控制其一个一个发以便于判断
len = UartRcv(TestTxBuf + TestRxPos,1);
if( len > 255 )
{
len = 0;
}
//4.2 接收数据
if(len > 0)
{
//从串口接收数据并且拷贝到Myname数组中
if(TestTxBuf[TestRxPos] == '\n')
{
memcpy(Myname,TestTxBuf,TestRxPos);
MynameLen = TestRxPos;
UartSend("名字设置成功!",14);
TestRxPos = 0;
break;
}else{
TestRxPos += len;
}
}
}
}
这个步骤也很简单,其实就是通过串口发送:请输入名字:,长度是15个字节,然后进入死循环
循环里面就等着用户输入回车,输入回车之后就将串口发送过来的数据存储到数组里面,这里要注意数组的长度和设置完成的时候将数据滚动(TestRxPos )清零,数组是必须要设置长度的,不然的话发不了:
//创建一个存储单个数据的数组
static unsigned char TestTxBuf[255];
//3.2 创建一个拼接名字后的存储的数组
static unsigned char SwapBuf[255];
//创建一个接收数据的数组
static unsigned char TestRxBuf[255];
//3.4 创建一个滚动的位置用于数据接收判断
static unsigned char TestRxPos = 0;
unsigned char juge = 0;
//3.1 创建一个存储名字的数组
static unsigned char Myname[20];
static unsigned char MynameLen;
这里我就用到了这些变量,四个数组,很明显,有接收数据的数组,发送数据的数组,存放名字的数组,存放临时消息的数组;
如果拿到了存放有我们名称和数据的数组是不是就可以通过ZigBee的收发数据将数据通过串口实现一个聊天效果呢?那么思路有了,咱们就开始吧:
1、初始化
//定义一个强度
unsigned short pRssi = 0;
//2.3 定义通讯的结构体
basicRfCfg_t pRfConfig;
LEDInit();
KeyInit();
//初始化一下时钟
SysClkInit();
TimerInit();
UartInit(9600,'n');
pRfConfig.myAddr = 0x0002;
pRfConfig.panId = 0x1000;
pRfConfig.channel = 11;
pRfConfig.ackRequest = 1;
//2.1 初始化函数
basicRfInit(&pRfConfig);
//2.5 保持接收的打开
basicRfReceiveOn();
setName();
Delay(1000);
一些基础的初始化,串口必须的,时钟,led 、按键什么的不需要其实,当然大家加上也没什么影响,然后就是我们的无线模块的初始化,有一个结构体,这个结构体大家自行设置即可,然后需要打开接收,设置名字,最好延时一下,毕竟单片机运行速度还是蛮快的;
2、发送数据,因为前面我们讲解了如何设置名称,这里就直接重发送数据开始:
while(1)
{
len = 0;
//控制其一个一个发以便于判断
len = UartRcv(TestTxBuf + TestRxPos,1);
if( len > sizeof(TestTxBuf) )
{
len = 0;
}
//4.1 接收数据
if(len > 0)
{
if(TestTxBuf[TestRxPos] == '\n')
{
//将数组拷贝到带有名称的数组中
memcpy(SwapBuf,Myname,MynameLen - 1);
memcpy(SwapBuf +MynameLen - 1,TestTxBuf,TestRxPos);
basicRfSendPacket(0xffff,SwapBuf,TestRxPos + MynameLen - 1);
TestRxPos = 0;
}else{
TestRxPos += len;
}
}
首先我们拿到串口里面用户输入的数据,这个串口函数的意思是一个一个接收,len的话就是接收到数据的长度,这个函数前面我们有讲过,后面就不在讲解的,有需要的去翻前面的;这里接收到的数据会一个一个的存到发送数据的数组中;
len的长度不可以超过数组的最大值255,越界之后就发送不了了;当检测到len的值大于0,也就是接收到了用户的数据之后,是一个一个接的,所以len其实就是1,然后判断一下,如果检测到换行我们就可以发送准备了,如果没有检测到TestRxPos就会滚动,那么这个值到检测到了换行的时候就是发送数据的长度,所以在检测到换行之后,我们就可以将我们的名称数组和发送数据数组一同拷贝到临时数据数组里面,这里我拷贝的时候减掉了1,目的是去掉名字数据最后的换行;
拷贝到临时数据数组里面之后我们就可以通过无线发送函数发送,发送完成之后将我们滚动的位置清零,准备下一次发送;
3、接收数据:
if(basicRfPacketIsReady())
{
//收到之后我们接收到数组中,然后判断亮灯
//接收函数的第三个参数是信号的强度
UartSend(TestRxBuf,basicRfReceive(TestRxBuf,sizeof(TestRxBuf),(unsigned short *)&pRssi));
}
这个很简单,就是判断是否做好接收准备然后通过串口将数据显示到pc上,用的是接收数据数组,长度就是接收到数据的长度;
好了,总之,不要将程序想的太难,这里我将整体代码贴出来:
#include "LED.h"
#include "KEY.h"
#include "Timer.h"
#include "UART.h"
#include "ADC.h"
#include "basic_rf.h"
static void SysClkInit(void)
{
//由16MHZ时钟切换到32MHZ时钟
CLKCONCMD &= ~0x40;
for(;CLKCONSTA & 0x40;);
CLKCONCMD &= ~0X7F;
}
void KeyControlLedShow(unsigned char n)
{
if(n & 0x01)
{
LEDOn(1);
}
else
{
LEDOff(1);
}
if(n & 0x02)
{
LEDOn(2);
}
else
{
LEDOff(2);
}
if(n & 0x04)
{
LEDOn(3);
}
else
{
LEDOff(3);
}
if(n & 0x08)
{
LEDOn(4);
}
else
{ LEDOff(4);
}
}
void ShowNumber(void)
{
unsigned static char i = 0;
KeyControlLedShow(i++);
if(i > 15)
{
i = 0;
}
}
void TimeLed(void)
{
LEDToggle(0);
}
//创建一个存储单个数据的数组
static unsigned char TestTxBuf[255];
//3.2 创建一个拼接名字后的存储的数组
static unsigned char SwapBuf[255];
//创建一个接收数据的数组
static unsigned char TestRxBuf[255];
//3.4 创建一个滚动的位置用于数据接收判断
static unsigned char TestRxPos = 0;
unsigned char juge = 0;
//3.1 创建一个存储名字的数组
static unsigned char Myname[20];
static unsigned char MynameLen;
//1.3定义一个需要发送数据的长度和采集数据的存储变量
unsigned int len = 0;
//3.3 设置名字
void setName(void)
{
Delay(5000);
UartSend("请输入名字:",15);
while(1)
{
//控制其一个一个发以便于判断
len = UartRcv(TestTxBuf + TestRxPos,1);
if( len > 255 )
{
len = 0;
}
//4.2 接收数据
if(len > 0)
{
//从串口接收数据并且拷贝到Myname数组中
if(TestTxBuf[TestRxPos] == '\n')
{
memcpy(Myname,TestTxBuf,TestRxPos);
MynameLen = TestRxPos;
UartSend("名字设置成功!",14);
TestRxPos = 0;
break;
}else{
TestRxPos += len;
}
}
}
}
void main(void)
{
//2.6 我们需要一个判断来确定按钮的状态
unsigned char switchstate = 0;
float ret = 0;
//定义一个强度
unsigned short pRssi = 0;
//1.1 通过传感器产生的数据,发送到pc端显示,
unsigned int length = 0;
//2.3 定义通讯的结构体
basicRfCfg_t pRfConfig;
LEDInit();
KeyInit();
//初始化一下时钟
SysClkInit();
//KeyCallBackRegister(&ShowNumber);
TimerInit();
// static unsigned long ledtime = 0;
// TimeSetCallBack(500,TimeLed,1);
UartInit(9600,'n');
// AdcInit();
pRfConfig.myAddr = 0x0002;
pRfConfig.panId = 0x1000;
pRfConfig.channel = 11;
pRfConfig.ackRequest = 1;
//2.1 初始化函数
basicRfInit(&pRfConfig);
//2.5 保持接收的打开
basicRfReceiveOn();
setName();
Delay(1000);
while(1)
{
len = 0;
//控制其一个一个发以便于判断
len = UartRcv(TestTxBuf + TestRxPos,1);
if( len > sizeof(TestTxBuf) )
{
len = 0;
}
//4.1 接收数据
if(len > 0)
{
if(TestTxBuf[TestRxPos] == '\n')
{
//将数组拷贝到带有名称的数组中
memcpy(SwapBuf,Myname,MynameLen - 1);
memcpy(SwapBuf +MynameLen - 1,TestTxBuf,TestRxPos);
basicRfSendPacket(0xffff,SwapBuf,TestRxPos + MynameLen - 1);
TestRxPos = 0;
}else{
// length = sizeof(Myname);
// memcpy(SwapBuf+length+TestRxPos,TestTxBuf,len);
TestRxPos += len;
}
}
//4.2 发送数据
// //2.8 判断是否收到数据
if(basicRfPacketIsReady())
{
//收到之后我们接收到数组中,然后判断亮灯
//接收函数的第三个参数是信号的强度
UartSend(TestRxBuf,basicRfReceive(TestRxBuf,sizeof(TestRxBuf),(unsigned short *)&pRssi));
}
//#ifdef SWITCH
// //2.4 发送逻辑
// //每次按下按钮我们将switchstate取反
// if(Key1Getstate()|| Key2Getstate())
// {
// switchstate = !switchstate;
// }
// //将数据检测出来之后我们要存入数组
// TestTxBuf[0] = switchstate;
//
// //2.7 我们按照地址发送数据,一次第一个
// basicRfSendPacket(0x0002,TestTxBuf,1);
//#else
// //2.8 判断是否收到数据
// if(basicRfPacketIsReady())
// {
// //收到之后我们接收到数组中,然后判断亮灯
// //接收函数的第三个参数是信号的强度
// len = basicRfReceive(TestRxBuf,sizeof(TestRxBuf),(unsigned short *)&pRssi);
// if(TestRxBuf[0])
// {
// LEDOn(0);
// }
// else
// {
// LEDOff(0);
// }
// }
//#endif
// //1.2 我们利用定时器1s中采集一次显示即可
// if(TimerCheck(ledtime))
// {
// ledtime = TimerSet(1000);
// //1.5 通过adc模块拿到采集到的数据
// ret = AdcGetValue();
// //1.4 进行数据的格式化处理
// len = sprintf(TestBuf,"The value of ADC is %f",ret);
// UartSend((char *)TestBuf,len);
// }
/*unsigned char i = 1;
Delay(2000);
len = UartRcv(TestTxBuf,1);
if(len > 0)
{
UartSend("你的名字是小白",16);
}
LEDToggle(i++);
Delay(100);
if(i > 4)
{
i = 1;
}*/
}
}
注释的地方是以前的代码;
好了,那么这一期就到这里了,快去试试吧。