协议设计练习

协议说明

数据包头命令分片标志数据包尾
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) {}  
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值