通过两个cc2530的点对点功能来实现—智能窗帘功能
本章主要是实现窗帘端和照明端的一个中继,实现一个中控端的代码,
这里我们中控端和两个设备端是通过自定义协议进行通信,关于协议具体内容请看代码,,这里只简单介绍一下,我们的协议采用包头,长度,主指令,副指令1,副指令2,校验位,包尾。
包头包尾固定,主指令是中控的下发命令或者是节点的上传命令,副指令是下发的数据或者上传的命令
其他的内容就是初始化按键或者就算通过按键和串口来做数据处理和下发了,这里博主就不在多说了。
直接上代码:
#include "hal_defs.h"
#include "hal_cc8051.h"
#include "hal_int.h"
#include "hal_mcu.h"
#include "hal_board.h"
#include "hal_led.h"
#include "hal_rf.h"
#include "basic_rf.h"
#include "hal_uart.h"
#include "sensor_drv/sensor.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "usart0.h"
/*****点对点通讯地址设置******/
#define RF_CHANNEL 25 // 频道 11~26
#define PAN_ID 0x2007 //网络id
#define CONTROL_ADDR 0x2520 //中控端地址
#define CURTAIN_ADDR 0x387A //窗帘模块地址
#define LIGHT_ADDR 0xbeef //照明端地址
/**************************************************/
static basicRfCfg_t basicRfConfig;
// 无线RF初始化
void ConfigRf_Init(void)
{
basicRfConfig.panId = PAN_ID;
basicRfConfig.channel = RF_CHANNEL;
basicRfConfig.myAddr = CONTROL_ADDR;
basicRfConfig.ackRequest = TRUE;
while(basicRfInit(&basicRfConfig) == FAILED);
basicRfReceiveOn();
}
//双方数据通信协议{包头,数据长度,主指令,副指令1,副指令2,校验位,包尾}
#define HEAD 0x55 //包头
#define TAIL 0xdd //包尾
#define MCMD_LIGHT_STATUS 0X01 //主指令--灯状态(照明模块上报灯的状态)
#define MCMD_CTRL_LIGHT 0X11 //主指令--控制灯(接收来自中控的控制灯的命令)
#define MCMD_CURTAIN_STATUS 0x02 //主指令--窗帘状态
#define MCMD_CTR_CURTAIN 0X22 //主指令---控制窗帘
#define SCMD_OPEN 0X01 //副指令--开
#define SCMD_CLOSE 0x02 //副指令--关
#define APP_PAYLOAD_LENGTH 7 //发送数据的长度
#define LED1 P1_0 //照明灯端口
#define KEY1 P0_1 //按键1端口
#define KEY2 P2_0 //按键2端口
static uint8 pTxData[APP_PAYLOAD_LENGTH];//发送数据数组
static uint8 pRxData[APP_PAYLOAD_LENGTH];//接收数据数组
uint8 masterCMD,slaveCMD1,slaveCMD2;//主指令,副指令1,副指令2
void build_payload(uint8 *pTxData, uint8 mCMD,uint8 sCMD1,uint8 sCMD2);//组建要发送的数据
int8 rcvdata_process(uint8 *rxbuf,uint8 *mCMD,uint8 *sCMD1,uint8 *sCMD2);//接受数据解析
void Init_Led(void);//初始化LED
void Init_key(void);//初始化按键
/********************MAIN************************/
void main(void)
{
uint8 led_state=0; //led灯此时的状态
uint8 curtain=0; //窗帘此时的状态
Init_Led(); //初始化照明灯
Init_key(); //初始化按键
Init_Uart0(); //串口0初始化
halBoardInit();//选手不得在此函数内添加代码
ConfigRf_Init();//选手不得在此函数内添加代码
while(1)
{
/* user code start */
if(basicRfPacketIsReady()) //如果准备好接收
{
if(basicRfReceive(pRxData,APP_PAYLOAD_LENGTH,NULL)>0)//如果接收数据长度大于0
{
if(rcvdata_process(pRxData,&masterCMD,&slaveCMD1,&slaveCMD2))
{
//接收内容错误
}else//接收内容正确
{
if(masterCMD==MCMD_LIGHT_STATUS) //接收到的主指令为照明端上报led灯状态
{
if(slaveCMD1==0x01) //如果副指令1为开灯状态
{
led_state=1;
LED1=0;
}else if(slaveCMD1==0x02)//如果副指令1为关灯状态
{
led_state=0;
LED1=1;//高电平熄灭
}
}else if(masterCMD==MCMD_CURTAIN_STATUS) //如果接受到的主指令为窗帘端上报窗帘状态
{
if(slaveCMD1==0x01) //如果副指令1为窗帘开
{
curtain=1;
UR0SendString("窗帘开\n");
//此处填写串口发送窗帘开关命令
}else if(slaveCMD1==0x02)//如果副指令1为关窗帘状态
{
curtain=0;
UR0SendString("窗帘关\n");
//此处填写串口发送窗帘开关命令
}
}
}
memset(pRxData,0,7);
}
}
if(KEY1==0)
{
halMcuWaitMs(20);
if(KEY1==0)
{
while(KEY1==0);
if(led_state==1) //如果此时led灯亮
{
LED1=1; //高电平熄灭
led_state=0; //状态灭
build_payload(pTxData,MCMD_CTRL_LIGHT,0X02,0x00); //发送LED控制指令,灭
}else if(led_state==0)
{
LED1=0;
led_state=1;
build_payload(pTxData,MCMD_CTRL_LIGHT,0X01,0x00); //发送控制指令,亮
}
basicRfSendPacket(LIGHT_ADDR,pTxData,APP_PAYLOAD_LENGTH); //向照明端发送数据包
}
}
if(KEY2==0)
{
halMcuWaitMs(20);
if(KEY2==0)
{
while(KEY1==0);
if(curtain==1)
{
curtain=0;
build_payload(pTxData,MCMD_CTR_CURTAIN,0X02,0x00); //发送窗帘控制指令,关
}else if(curtain==0)
{
curtain=1;
build_payload(pTxData,MCMD_CTR_CURTAIN,0X01,0x00); //发送窗帘控制指令,开
}
basicRfSendPacket(CURTAIN_ADDR,pTxData,APP_PAYLOAD_LENGTH); //向照明端发送数据包
}
}
halMcuWaitMs(20);
/* user code end */
}
}
//初始化照明端
void Init_Led(void)
{
P1SEL&=~0X13;
P1DIR|= 0X13;
LED1=1; //高电平熄灭
}
//初始化按键
void Init_key(void)
{
//KEY1
P0SEL&=~0X02;
P0DIR&=~0X02;
P0INP&=~0X02;
P2INP&=~0X20;
//KEY2
P2SEL&=~0X01;
P2DIR&=~0X01;
P0INP&=~0X01;
P2INP&=~0X80;
}
//接受数据解析
//rxbuf--收到的数据
//mCMD---主指令
//sCMD1--副指令1
//sCMD2--副指令2
int8 rcvdata_process(uint8 *rxbuf,uint8 *mCMD,uint8 *sCMD1,uint8 *sCMD2)
{
uint8 checksum=0x00;
if((rxbuf[0]!=HEAD)||(rxbuf[6]!=TAIL))
return 1;
checksum=(rxbuf[1]+rxbuf[2]+rxbuf[3]+rxbuf[4])%256;
if(checksum!=rxbuf[5])
return 1;
*mCMD=rxbuf[2];
*sCMD1=rxbuf[3];
*sCMD2=rxbuf[4];
return 0;
}
//组建要发送的数据
void build_payload(uint8 *pTxData, uint8 mCMD,uint8 sCMD1,uint8 sCMD2)
{
pTxData[0]=HEAD;
pTxData[1]=APP_PAYLOAD_LENGTH;
pTxData[2]=mCMD;
pTxData[3]=sCMD1;
pTxData[4]=sCMD2;
pTxData[5]=(pTxData[1]+pTxData[2]+pTxData[3]+pTxData[4])%256;
pTxData[6]=TAIL;
}