您的位置:首页 > 其它

协议设计练习

2016-07-04 19:00 330 查看

协议说明

数据包头命令分片标志数据包尾
1字节1字节1字节n字节2字节
主机—->从机:

包头:0xaa

包尾:0x0d 0x0a

命令:0x01 查询从机状态

0x02 数据请求

0x03 控制命令

发送信息示例:

查询命令:0xaa | 0x01 | 0x00 | 0x0d 0x0a

数据请求:0xaa | 0x02 | 0x00 | 0x0d 0x0a

控制命令:0xaa | 0x03 | 0x00 | 0x01 | 0x00 | 0x0d | 0x0a

(字节编号从0开始)字节3为执行器(0x01led灯,0x02beep,0x03风扇)

字节4为执行器的开关(0x00关,0x01开)

从机—->主机:

包头:0xbb

包尾:0x0d 0x0a

命令:0x01 就绪

0x02 忙

0x03 出错

0x11 命令执行成功

0x12 忙

0x13 命令执行出错,命令不存在

发送信息示例:

0xbb | 0x01 | 0x01 | data | 0x0d 0x0a

0xbb | 0x11 | 0x00 | 0x01 | 0x00 | 0x0d 0x0a

(字节编号从0开始)字节3为执行器(0x01led灯,0x02beep,0x03风扇)

字节4为执行器的状态(0x00关,0x01开)

协议示例

下面是一个stm32f103中蓝牙透传的协议的练习,蓝牙使用串口3。为了简便此协议并没有实现校验。

由于安卓中蓝牙每次接收数据最大长度只有20字节,故将数据包进行拆包,数据报最大长度为20字节。

数据拆包传输完整的实现了,从机状态信息函数void slaveState()没有根据现实的机器信息进行反馈,

只简单返回了一个信息。主机控制从机的部分,采取一次行发送所有控制信息,没有再进行细分。

#ifndef _protocal_H
#define _protocal_H

#include "usart.h"

//包头
#define   HOST_TO_SLAVE_H    0xaa     //主机->从机  包头
#define   SLAVE_TO_HOST_H    0xbb     //从机->主机  包头

#define   MESSAGE_TAIL_F     0x0d     //包尾结束标志  0x0d  0x0a
#define   MESSAGE_TAIL_B     0x0a

#define   DIVIDE_ENABLE      0x01     //有分片
#define   DIVIDE_DISABLE     0x00     //无分片

//主机->从机 命令
#define   HOST_CMD_CHECK     0x01     //查询从机状态
#define   HOST_CMD_READ      0x02     //读取从机数据
#define   HOST_CMD_WRITE     0x03     //向从机中写入数据

//从机->主机 从机状态命令
#define   SLAVE_STA_READY    0x01     //从机准备就绪
#define   SLAVE_STA_BUSY     0x02     //从机忙
#define   SLAVE_STA_ERROR    0x03     //从机出错

//从机->主机 从机执行状态命令
#define   SLAVE_EXU_SUCCE    0x11     //命令执行成功
#define   SLAVE_EXU_BUSY     0x12     //从机忙
#define   SLAVE_EXU_ERROR    0x13     //命令执行出错,命令不存在

//执行器
#define   LEDCONTROL         0x01
#define   BEEPCONTROL        0x02
#define   FANCONTROL         0x03
#define   ONSTATE            0x01     //开
#define   OFFSTATE           0x00     //关

#define   MES_HEAD_LEN      3      //包头长度
#define   MES_TAIL_LEN      2      //包尾长度

enum MixData {
TMPH, TMPL,         //温度
HUMH, HUML,         //湿度
PRETH,PRETL,        // bmp1750 ut值
PRESH, PRESL,       // bmp1750 up值
LIGH, LIGL,         //光强
PRE_REG_AC1H, PRE_REG_AC1L,      //bmp1750 ac1-ac6,b1,b2,mb-md的值
PRE_REG_AC2H, PRE_REG_AC2L,
PRE_REG_AC3H, PRE_REG_AC3L,
PRE_REG_AC4H, PRE_REG_AC4L,
PRE_REG_AC5H, PRE_REG_AC5L,
PRE_REG_AC6H, PRE_REG_AC6L,
PRE_REG_B1H, PRE_REG_B1L,
PRE_REG_B2H, PRE_REG_B2L,
PRE_REG_MBH, PRE_REG_MBL,
PRE_REG_MCH, PRE_REG_MCL,
PRE_REG_MDH, PRE_REG_MDL,
TOTAL_DATA
};

extern unsigned char All_Info_Char[TOTAL_DATA];       //信息数组,将传感器采集的信息放入此数组中,存储次序为上方的MixData表
int messageAnalysis(u8 USART_RX_BUF[USART_REC_LEN]); //报文解析
void slaveState();
void slaveSendM();
void slaveRecM(u8 USART_RX_BUF[USART_REC_LEN]);


#include "protocal.h"
#include "crc16.h"
#include "app.h"
#include "string.h"
#include "delay.h"

unsigned char All_Info_Char[TOTAL_DATA] = {0};

int messageAnalysis(u8 USART_RX_BUF[USART_REC_LEN]) //报文解析
{
if(USART_RX_STA&0x8000) {    //当包尾为0d 0a时进行处理
if(USART_RX_BUF[1] == HOST_CMD_CHECK) {
slaveState();
USART_RX_STA = 0;
}else if(USART_RX_BUF[1] == HOST_CMD_READ) {
slaveSendM();
USART_RX_STA = 0;
}else if(USART_RX_BUF[1] == HOST_CMD_WRITE) {
slaveRecM(USART_RX_BUF);
USART_RX_STA = 0;
}else{
USART_RX_STA = 0;
}
}
}

void slaveState()
{
unsigned char message[7] = {0};
message[0] = SLAVE_TO_HOST_H;
message[1] = SLAVE_EXU_SUCCE;
message[2] = DIVIDE_DISABLE;
message[5] = MESSAGE_TAIL_F;
message[6] = MESSAGE_TAIL_B;

message[3] = LEDCONTROL;            //执行器
message[4] = LedState;           //状态
USART_SendMessage(USART3, message, 7);
delay_ms(50);
message[3] = BEEPCONTROL;
message[4] = BeepState;
USART_SendMessage(USART3, message, 7);
delay_ms(50);
message[3] = FANCONTROL;
message[4] = FanState;
USART_SendMessage(USART3, message, 7);
delay_ms(50);
}

void slaveSendM()         //从机向主机发送信息
{
int i = 0,j = 0, len;
volatile int  k = 0;
int totaldata = TOTAL_DATA;
unsigned char message[TOTAL_DATA+MES_HEAD_LEN+MES_TAIL_LEN] = {0};
for(i = 0; i < TOTAL_DATA / 15; i++) {   //分片,每片最多20字节
message[0] = SLAVE_TO_HOST_H;
message[1] = SLAVE_STA_READY;
message[2] = DIVIDE_ENABLE;
for(j = MES_HEAD_LEN; j < 15 + MES_HEAD_LEN; j++, k++) {
message[j] = All_Info_Char[k];
}
message[18] = MESSAGE_TAIL_F;
message[19] = MESSAGE_TAIL_B;
USART_SendMessage(USART1, message, 20);
delay_ms(10);
}
len = k;
message[0] = SLAVE_TO_HOST_H;
message[1] = SLAVE_STA_READY;
message[2] = DIVIDE_DISABLE;
for(j = MES_HEAD_LEN; j < TOTAL_DATA+MES_HEAD_LEN - k; j++, k++) {
message[j] = All_Info_Char[k];
}
message[TOTAL_DATA+MES_HEAD_LEN+MES_TAIL_LEN -len-2] = MESSAGE_TAIL_F;
message[TOTAL_DATA+MES_HEAD_LEN+MES_TAIL_LEN - 1-len] = MESSAGE_TAIL_B;
USART_SendMessage(USART1, message, TOTAL_DATA+MES_HEAD_LEN+MES_TAIL_LEN - len);
}

void slaveRecM(u8 USART_RX_BUF[USART_REC_LEN])
{
//  USART_SendMessage(USART3, "ok3", 3);
unsigned char message[7] = {0};
if(USART_RX_BUF[3] == LEDCONTROL) {
LED_Cont(USART_RX_BUF[4]);
LedState = USART_RX_BUF[4];
message[1] = SLAVE_EXU_SUCCE;
}else if(USART_RX_BUF[3] == BEEPCONTROL) {
Buzzer_Cont(USART_RX_BUF[4]);
BeepState = USART_RX_BUF[4];
message[1] = SLAVE_EXU_SUCCE;
}else if(USART_RX_BUF[3] == FANCONTROL) {
Fan_Cont(USART_RX_BUF[4]);
FanState = USART_RX_BUF[4];
message[1] = SLAVE_EXU_SUCCE;
}else {
message[1] = SLAVE_EXU_ERROR;
}

message[0] = SLAVE_TO_HOST_H;

message[2] = DIVIDE_DISABLE;
message[3] = USART_RX_BUF[3];            //执行器
message[4] = USART_RX_BUF[4];            //状态
message[5] = MESSAGE_TAIL_F;
message[6] = MESSAGE_TAIL_B;
USART_SendMessage(USART3, message, 7);
}


串口1的中断处理函数,作用是当判断收到的信息为aa时开始接收,将信息放入USART_RX_BUF数组中,当信息为0d 0a时,结束接收。交与下面进行报文的解析。

#define USART_REC_LEN           200     //定义最大接受字节数 200
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大接收USART_REC_LEN个字符
//接收状态
//bit15,    接收完成标志
//bit14,   接收到0x0d
//bit13~0  接收到的有效字节数
u16 USART_RX_STA=0;       //接收状态标记
u16 USART_RX_S_STA=0;     //帧起始标志

void USART1_IRQHandler(void)                                         //串口1中断服务程序
{

uint16_t Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)            //接收中断(aa开始0d0a结束)
{
Res =USART_ReceiveData(USART1);                                //(USART1->DR);  //读取收到的数据
//  USART_SendData(USART1,Res);
if(Res == HOST_TO_SLAVE_H && USART_RX_S_STA == 0) {  //包头标志0xaa
USART_RX_S_STA = 1;
}
if(USART_RX_S_STA) {
if((USART_RX_STA&0x8000)==0)                                   //接收未完成
{
if(USART_RX_STA&0x4000)                                      //接收到0x0d
{
if(Res!=0x0a)USART_RX_STA=0;                               //接收错误,重新开始
else {
USART_RX_STA|=0x8000;                                  //接收完成           //bit31表明是否接收到0x0a
USART_RX_BUF[USART_RX_STA&0X3FFF]= '\0';
USART_RX_S_STA = 0;
}
}
else //还没接收到0x0d
{
if(Res==0x0d) USART_RX_STA|=0x4000;                     //bit30表明是否接收到0x0d
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}       //   printf("%s", USART_RX_BUF);
}
}

void USART_SendMessage(USART_TypeDef* USARTx, u8 *buf, u8 len)
{
u8 i;
for (i = 0; i < len; i++)  {
USART_SendData(USARTx,buf[i]);
while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET) {}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息