(转载)——STM32简单数据传输方法与通信协议(适合串口和一般总线)

论坛 期权论坛     
选择匿名的用户   2021-6-2 16:20   707   0
<p>原帖地址:<a href="http://www.eeworld.com.cn/mcu/article_2018042238782.html">http://www.eeworld.com.cn/mcu/article_2018042238782.html</a></p>
<h1>引言</h1>
<p>在一般的项目开发过程中,往往需要两块或以上单片机进行通信完成<strong><a href="http://www.eeworld.com.cn/tags/%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93">数据传输</a></strong>,例如四旋翼无人机在飞行过程中无线传输数据回到地面站,治疗仪器需要实时将患者和机器运转情况传回上位机平台,粮仓温控装置需将各种传感器通过RS485总线或者CAN总线的方式达到数据传输的目的等等,这些数据传输往往需要合适稳定的总线和灵活的<strong><a href="http://www.eeworld.com.cn/tags/%E9%80%9A%E4%BF%A1%E5%8D%8F%E8%AE%AE">通信协议</a></strong>,我发现无论什么数据传输,原理大同小异,这里简单以stm32的几种数据传输总结下平时项目中用的一些传输方法。</p>
<h1>通信协议</h1>
<h2>简单情况(如一对一)</h2>
<p>首先在数据传输前一定要想好通信协议,如果传输的数据和过程非常简单,那么就可以采用简单的传输协议,例如: </p>
<p>直接上代码:</p>
<p> </p>
<p>int temp;   </p>
<p>u8 RS485_receive_str[128];   //接收缓冲,最大128个字节.</p>
<p>u8 uart_byte_count&#61;0;        //接收到的数据长度</p>
<p>        ...</p>
<p>/****************************************************************************</p>
<p>* void RS485_Receive_Data(u8 *buf,u8 *len)</p>
<p>* RS485查询接收到的数据</p>
<p>* 入口参数:buf:接收缓存首地址</p>
<p>            len:读到的数据长度   </p>
<p>****************************************************************************/</p>
<p>void RS485_Receive_Data(u8 *buf,u8 *len)</p>
<p>{<!-- --></p>
<p>    u8 rxlen&#61;uart_byte_count;</p>
<p>    u8 i&#61;0;</p>
<p>    *len&#61;0;                //默认为0</p>
<p>    delay_ms(10);        //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束</p>
<p> </p>
<p>    if(rxlen&#61;&#61;uart_byte_count&amp;&amp;rxlen) //接收到了数据,且接收完成了</p>
<p>    {<!-- --></p>
<p>        for(i&#61;0;i</p>
<p>        {<!-- --></p>
<p>            buf[i]&#61;RS485_receive_str[i];    </p>
<p>        }       </p>
<p>        *len&#61;uart_byte_count;   //记录本次数据长度</p>
<p>        uart_byte_count&#61;0;        //清零</p>
<p>    }</p>
<p>}</p>
<p>//接收中断服务函数</p>
<p>int state&#61;0;</p>
<p>void USART2_IRQHandler(void)</p>
<p>{<!-- --></p>
<p>    u8 rec_data;        </p>
<p>    if(USART_GetITStatus(USART2, USART_IT_RXNE) !&#61; RESET)//接收到数据</p>
<p>    {       </p>
<p>        rec_data &#61;(u8)USART_ReceiveData(USART2);                 //(USART2-&gt;DR) 读取接收到的数据</p>
<p>        if(rec_data&#61;&#61;&#39;S&#39;&amp;&amp;state&#61;&#61;0)                              //如果是S,表示是命令信息的起始位</p>
<p>        {<!-- --></p>
<p>            state&#61;1;</p>
<p>            uart_byte_count&#61;0x00; </p>
<p>        }else if(rec_data&#61;&#61;&#39;E&#39;&amp;&amp;state&#61;&#61;2)                         //如果E,表示是命令信息传送的结束位并开始处理数据</p>
<p>        {<!-- --></p>
<p>            state&#61;0;</p>
<p>            if(RS485_receive_str[0]&#61;&#61;0x00)                      //判断地址 地址正确</p>
<p>            {<!-- --></p>
<p>                if(RS485_receive_str[1]&#61;&#61;0x02)                  //接受温度数据</p>
<p>                {<!-- --></p>
<p>                    temp&#61;RS485_receive_str[5]&lt;&lt;24&#34;RS485_receive_str[2]|RS485_receive_str[3]&lt;&lt;8|RS485_receive_str[4]&lt;&lt;16;</p>
<p> </p>
<p>                }   else if(RS485_receive_str[1]&#61;&#61;0x03)         //led控制回馈</p>
<p>                {<!-- --></p>
<p>                    led&#61;RS485_receive_str[2];</p>
<p> </p>
<p>                }</p>
<p>            }</p>
<p>        }else if(state&#61;&#61;1)                                  //一位位接收数据并装入缓存</p>
<p>        {<!-- --></p>
<p>            RS485_receive_str[uart_byte_count&#43;&#43;]&#61;rec_data;</p>
<p>            if(uart_byte_count&#61;&#61;6)</p>
<p>                state&#61;2;</p>
<p>        }</p>
<p>    }                                            </p>
<p>} </p>
<p>这样的传输协议往往在两个一对一的传输中比较好用,主要在接受缓存部分使用了状态机机制,并且定义了简单的帧头和结束帧,显然这样的通信协议并不可靠,遇到复杂的情况就不好办了。</p>
<h2>复杂情况</h2>
<p>复杂情况的协议可以先制定协议表,再做细分,帧头&#43;功能字&#43;长度&#43;数据&#43;校验位,这样的协议既能满足多功能的场合也能避免数据过多出现错误,比较通用。 <br> 例如 GPS定位下位机协议: <br>  </p>
<p>遥控上位机协议:</p>
<p> </p>
<ul><li> <p>SUM所有字节的和:等于从该数据帧第一字节开始,也就是帧头开始,至该
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP