关于IO口的自定义通信协议设计

2024-06-01 13:28

本文主要是介绍关于IO口的自定义通信协议设计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

设计一个通信协议需要start、end、数据0,数据1,这样就组成了一个最基本的通信协议。

要考虑到有运行误差的情况,加了误差之后以上四个信号也不会相互干扰,就是说加上误差后,0也不会变成1,1也不会变成0。

发送和接收的数据最好自己加校验,这样可以避免数据错误。

/********************************************** 设计一个协议* start: 3ms高 1ms低* end  : 1.5ms高 1.5ms低 //end的低电平持续时间是没有进行判断的,感觉没必要,想要的可以自己加上* 0    : 700us高 300us低* 1    : 300us高 700us低* 空闲态:低电平* *******************************************/
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;#define _RECV_IO //接收的IO口 
#define _SEND_IO //发送的IO口#define USE_RECV //使用接收功能就打开注释,不使用就注释掉,默认使用
#define USE_SEND //使用发送功能就打开注释,不使用就注释掉,默认使用#define n_100US_100US    (1)//中断时间是100us
#define BASE_TIME_TICK   (1*(n_100US_100US))
#define START_HIGH_TIME	 (30*(BASE_TIME_TICK))
#define START_LOW_TIME 	 (10*(BASE_TIME_TICK))
#define END_HIGH_TIME  	 (15*(BASE_TIME_TICK))
#define END_LOW_TIME	 (15*(BASE_TIME_TICK)) 
#define START_END_PERMISSIBLE_ERROR (4*(BASE_TIME_TICK))//允许误差#define ZERO_HIGH_TIME	 (7*(BASE_TIME_TICK))
#define ZERO_LOW_TIME	 (3*(BASE_TIME_TICK))
#define ONE_HIGH_TIME	 (3*(BASE_TIME_TICK))
#define ONE_LOW_TIME	 (7*(BASE_TIME_TICK))
#define ZERO_ONE_PERMISSIBLE_ERROR (1*(BASE_TIME_TICK))//允许误差#define MAX_ERROR_TIME 250//最大的时间限制#define PROTOCOL_DATA_LENGTH 8//发送和接收数据的长度typedef enum{n_StartHigh=0,n_StartLow,n_DataTransmission,n_EndHigh,n_EndLow,
}StepEnum_t;typedef struct
{
#ifdef USE_RECV//接收uint8_t RecvTempArr[PROTOCOL_DATA_LENGTH];StepEnum_t RecvStep;uint8_t RecvHighCount;//高电平计数值uint8_t RecvLowCount;//低电平计数值uint16_t RecvDataBitCount;//接收到数据的bit值uint8_t RecvOneBitFlag;//接收到了一个bituint8_t RecvOkFlag;//接收完毕,根据这个标志位提取数据uint8_t RecvArr[PROTOCOL_DATA_LENGTH];//接收到的数据
#endif
#ifdef USE_SEND//发送uint8_t NeedSendFlag;//需要发送StepEnum_t SendStep;uint8_t SendCount;//计数值uint16_t SendDataBitCount;//发送数据的bit值uint8_t OnSendingOneBitFlag;//正在发送了一个bituint8_t SendingBit;//要发送的bit:0或1uint8_t SendArr[PROTOCOL_DATA_LENGTH];//要发送的数据
#endif
}ProtocolDesignStruct_t;ProtocolDesignStruct_t Protocol;void TimerInterrupt(void)//100us
{uint8_t i;uint8_t sendHighTime;uint8_t sendTotalTime;
#ifdef USE_RECVswitch(Protocol.RecvStep){case n_StartHigh:if(_RECV_IO){if(Protocol.RecvHighCount < MAX_ERROR_TIME)Protocol.RecvHighCount++;}else{if(Protocol.RecvHighCount >= (START_HIGH_TIME-START_END_PERMISSIBLE_ERROR) && Protocol.RecvHighCount <= (START_HIGH_TIME+START_END_PERMISSIBLE_ERROR)){Protocol.RecvStep = n_StartLow;Protocol.RecvHighCount = 0;Protocol.RecvLowCount = 1;}else//长度错误{Protocol.RecvHighCount = 0;}}break;case n_StartLow:if(_RECV_IO){if(Protocol.RecvHighCount >= (START_LOW_TIME-START_END_PERMISSIBLE_ERROR) && Protocol.RecvHighCount <= (START_LOW_TIME+START_END_PERMISSIBLE_ERROR)){Protocol.RecvStep = n_DataTransmission;for(i=0;i<PROTOCOL_DATA_LENGTH;i++)//要接收数据了,先清0{Protocol.RecvTempArr[i] = 0;}Protocol.RecvDataBitCount = 0;Protocol.RecvOneBitFlag = 0;}else{Protocol.RecvStep = n_StartHigh;//数据错误}Protocol.RecvHighCount = 1;Protocol.RecvLowCount = 0;}else{if(Protocol.RecvLowCount < MAX_ERROR_TIME)Protocol.RecvLowCount++;}break;case n_DataTransmission:if(_RECV_IO){if(Protocol.RecvOneBitFlag == 0)//还没接收到1个字节{if(Protocol.RecvHighCount < MAX_ERROR_TIME)Protocol.RecvHighCount++;}else{if((Protocol.RecvHighCount >= ZERO_HIGH_TIME-ZERO_ONE_PERMISSIBLE_ERROR)&&(Protocol.RecvHighCount <= ZERO_HIGH_TIME+ZERO_ONE_PERMISSIBLE_ERROR)&&(Protocol.RecvLowCount >= ZERO_LOW_TIME-ZERO_ONE_PERMISSIBLE_ERROR)&&(Protocol.RecvLowCount <= ZERO_LOW_TIME+ZERO_ONE_PERMISSIBLE_ERROR) )//接收到0{Protocol.RecvDataBitCount++;}else if((Protocol.RecvHighCount >= ONE_HIGH_TIME-ZERO_ONE_PERMISSIBLE_ERROR)&&(Protocol.RecvHighCount <= ONE_HIGH_TIME+ZERO_ONE_PERMISSIBLE_ERROR)&&(Protocol.RecvLowCount >= ONE_LOW_TIME-ZERO_ONE_PERMISSIBLE_ERROR)&&(Protocol.RecvLowCount <= ONE_LOW_TIME+ZERO_ONE_PERMISSIBLE_ERROR) )//接收到1{Protocol.RecvTempArr[Protocol.RecvDataBitCount>>3] |= (0X01)<<(Protocol.RecvDataBitCount&0X0007);Protocol.RecvDataBitCount++;}else{Protocol.RecvStep = n_StartHigh;//数据错误}if(Protocol.RecvDataBitCount >= (PROTOCOL_DATA_LENGTH<<3))//数据接收完毕{Protocol.RecvStep = n_End;}Protocol.RecvHighCount = 1;Protocol.RecvOneBitFlag = 0;//重新接收一个字节}}else{if(Protocol.RecvLowCount < MAX_ERROR_TIME)Protocol.RecvLowCount++;Protocol.RecvOneBitFlag = 1;//已经接收到1个字节了}break;case n_EndHigh:if(_RECV_IO){if(Protocol.RecvHighCount < MAX_ERROR_TIME)Protocol.RecvHighCount++;}else{if(Protocol.RecvHighCount >= (END_HIGH_TIME-START_END_PERMISSIBLE_ERROR) && Protocol.RecvHighCount <= (END_HIGH_TIME+START_END_PERMISSIBLE_ERROR)){for(i=0;i<PROTOCOL_DATA_LENGTH;i++){Protocol.RecvArr[i] = Protocol.RecvTempArr[i];}Protocol.RecvOkFlag = 1;//接收到数据了}Protocol.RecvStep = n_StartHigh;Protocol.RecvHighCount = 0;Protocol.RecvLowCount = 0;}break;default:Protocol.RecvStep = n_StartHigh;Protocol.RecvHighCount = 0;Protocol.RecvLowCount = 0;break;}
#endif#ifdef USE_SENDif(Protocol.NeedSendFlag){switch(Protocol.SendStep){case n_StartHigh:_SEND_IO = 1;if(++Protocol.SendCount >= START_HIGH_TIME){Protocol.SendCount = 0;Protocol.SendStep = n_StartLow;}break;case n_StartLow:_SEND_IO = 0;if(++Protocol.SendCount >= START_LOW_TIME){Protocol.SendCount = 0;Protocol.SendStep = n_DataTransmission;Protocol.SendDataBitCount = 0;//还未发送Protocol.OnSendingOneBitFlag = 0;//还未发送}break;case n_DataTransmission:if(Protocol.OnSendingOneBitFlag == 0){//获取bit值if(Protocol.SendArr[Protocol.SendDataBitCount>>3]&(0X0001<<(Protocol.SendDataBitCount&0X0007)))Protocol.SendingBit = 1;else Protocol.SendingBit = 0;	Protocol.SendDataBitCount++;Protocol.OnSendingOneBitFlag = 1;}//获取高低电平时间if(Protocol.SendingBit){sendHighTime = ONE_HIGH_TIME;sendTotalTime = ONE_HIGH_TIME + ONE_LOW_TIME;}else{sendHighTime = ZERO_HIGH_TIME;sendTotalTime = ZERO_HIGH_TIME + ZERO_LOW_TIME;}if(Protocol.SendCount < sendHighTime){_SEND_IO = 1;}else{_SEND_IO = 0;}if(++Protocol.SendCount >= sendTotalTime){Protocol.SendCount = 0;Protocol.OnSendingOneBitFlag = 0;if(Protocol.SendDataBitCount >= (PROTOCOL_DATA_LENGTH<<3))//数据发送完毕{Protocol.SendStep = n_EndHigh;}}break;case n_EndHigh:_SEND_IO = 1;if(++Protocol.SendCount >= END_HIGH_TIME){Protocol.SendCount = 0;Protocol.SendStep = n_EndLow;}break;case n_EndLow:_SEND_IO = 0;if(++Protocol.SendCount >= END_LOW_TIME){Protocol.SendCount = 0;Protocol.SendStep = n_StartHigh;Protocol.NeedSendFlag = 0;//发送完成}break;default:Protocol.NeedSendFlag = 0;break;}}else{_SEND_IO = 0;Protocol.SendStep = n_StartHigh;Protocol.SendCount = 0;}
#endif
}

这篇关于关于IO口的自定义通信协议设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1021135

相关文章

在线装修管理系统的设计

管理员账户功能包括:系统首页,个人中心,管理员管理,装修队管理,用户管理,装修管理,基础数据管理,论坛管理 前台账户功能包括:系统首页,个人中心,公告信息,论坛,装修,装修队 开发系统:Windows 架构模式:B/S JDK版本:Java JDK1.8 开发工具:IDEA(推荐) 数据库版本: mysql5.7 数据库可视化工具: navicat 服务器:SpringBoot自带 ap

ROS话题通信流程自定义数据格式

ROS话题通信流程自定义数据格式 需求流程实现步骤定义msg文件编辑配置文件编译 在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如:

DDei在线设计器-API-DDeiSheet

DDeiSheet   DDeiSheet是代表一个页签,一个页签含有一个DDeiStage用于显示图形。   DDeiSheet实例包含了一个页签的所有数据,在获取后可以通过它访问其他内容。DDeiFile中的sheets属性记录了当前文件的页签列表。   一个DDeiFile实例至少包含一个DDeiSheet实例。   本篇最后提供的示例可以在DDei文档直接预览 属性 属性名说明数

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

比较学习难度:Adobe Illustrator、Photoshop和新兴在线设计平台

从入门设计开始,几乎没有人不知道 Adobe 公司两大设计软件:Adobe Illustrator和 Photoshop。虽然AI和PS很有名,有一定设计经验的设计师可以在早期探索和使用后大致了解AI和PS的区别,但似乎很少有人会系统地比较AI和PS。目前,设计软件功能多样,轻量级和网页设计软件已成为许多设计师的需求。对于初学者来说,一篇有针对性的AI和PS比较总结文章具有非常重要的指导意义。毕竟

基于Java医院药品交易系统详细设计和实现(源码+LW+调试文档+讲解等)

💗博主介绍:✌全网粉丝10W+,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码+数据库🌟 感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人  Java精品实战案例《600套》 2023-2025年最值得选择的Java毕业设计选题大全:1000个热

展厅设计主要的六大要素

1、从创意开始      展示设计的开始必须创意在先。根据整体的风格思路进行创意,首先要考虑的是主体的造型、大小高度位置以及它和周围展厅的关系。另外其他道具设计制作与运作方式也必须在创意中有明确的体现。      2、平面感      平面感是指对展示艺术设计平面图纸审美和功能两个方面理性的感觉认识。它是三维空间设计认识的基础,也是施工的重要依据。展示空间的设计应先在展场环境的平面

添加自定义的CALayer

iOS开发UI篇—CAlayer(创建图层) 一、添加一个图层 添加图层的步骤: 1.创建layer 2.设置layer的属性(设置了颜色,bounds才能显示出来) 3.将layer添加到界面上(控制器view的layer上)  1 // 2 // YYViewController.m 3 // 01-创建一个简单的图层 4 // 5 //

android自定义View的和FramgentActivity的一个小坑

对于自定义View //加载样式TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TitleBarView, defStyleAttr, 0);setTitle(typedArray.getString(R.styleable.TitleBarView_main_title));//不能写成

办理河南建筑工程乙级设计资质的流程与要点

办理河南建筑工程乙级设计资质的流程与要点 办理河南建筑工程乙级设计资质的流程与要点主要包括以下几个方面: 流程: 工商注册与资质规划:确保企业具有独立法人资格,完成工商注册,并明确乙级设计资质的具体要求,包括注册资本、人员配置、技术条件等。 专业技术人员配置: 雇佣或签约符合资质要求的专业技术人员,包括但不限于:一级注册结构工程师2名、一级注册建筑师2名、注册暖通工程师1名、注册供配电工