精华内容
下载资源
问答
  • KELONGPowersoft交流电源监控管理系统前端智能设备通讯协议通讯协议内部标准,山特UPS串口通讯协议
  • 众所周知,工业设备种类繁多,厂家很多,对应的协议也非常多。 想做个产品支持这些协议,求交流。 求交流
  • 串口通讯协议

    万次阅读 多人点赞 2018-03-02 10:02:47
    文章转载自http://www.cnblogs.com/firege/p/5805753.html20.1 串口通讯协议简介串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,大部分电子设备都支持该通讯方式,电子工程师...

    文章转载自http://www.cnblogs.com/firege/p/5805753.html


    20.1 串口通讯协议简介

    串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。

    在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和片上外设;STM32标准库则是在寄存器与用户代码之间的软件层。对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和协议层。物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。简单来说物理层规定我们用嘴巴还是用肢体来交流,协议层则规定我们用中文还是英文来交流。

    下面我们分别对串口通讯协议的物理层及协议层进行讲解。

    20.1.1 物理层

    串口通讯的物理层有很多标准及变种,我们主要讲解RS-232标准RS-232标准主要规定了信号的用途、通讯接口以及信号的电平标准。

    使用RS-232标准的串口设备间常见的通讯结构见图 201

     201 串口通讯结构图

    在上面的通讯方式中,两个通讯设备的"DB9接口"之间通过串口信号线建立起连接,串口信号线中使用"RS-232标准"传输数据信号。由于RS-232电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个"电平转换芯片"转换成控制器能识别的"TTL校准"的电平信号,才能实现通讯。

    1.    电平标准    

    根据通讯使用的电平标准不同,串口通讯可分为TTL标准及RS-232标准,见表 201

     201 TTL电平标准与RS232电平标准

    通讯标准

    电平标准(发送端)

    5V TTL

    逻辑12.4V-5V

    逻辑00~0.5V

    RS-232

    逻辑1-15V~-3V

    逻辑0+3V~+15V

    我们知道常见的电子电路中常使用TTL的电平标准,理想状态下,使用5V表示二进制逻辑1,使用0V表示逻辑0;而为了增加串口通讯的远距离传输及抗干扰能力,它使用-15V表示逻辑1+15V表示逻辑0。使用RS232TTL电平校准表示同一个信号时的对比见图 202

     202 RS-232TTL电平标准下表示同一个信号

    因为控制器一般使用TTL电平标准,所以常常会使用MA3232芯片对TTL及RS-232电平的信号进行互相转换。

    2.    RS-232信号线

    在最初的应用中,RS-232串口标准常用于计算机、路由与调制调解器(MODEN,俗称"猫")之间的通讯 ,在这种通讯系统中,设备被分为数据终端设备DTE(计算机、路由)和数据通讯设备DCE(调制调解器)。我们以这种通讯模型讲解它们的信号线连接方式及各个信号线的作用。

    在旧式的台式计算机中一般会有RS-232标准的COM口(也称DB9接口),见图 203。

     203 电脑主板上的COM口及串口线

    其中接线口以针式引出信号线的称为公头,以孔式引出信号线的称为母头。在计算机中一般引出公头接口,而在调制调解器设备中引出的一般为母头,使用上图中的串口线即可把它与计算机连接起来。通讯时,串口线中传输的信号就是使用前面讲解的RS-232标准调制的。

    在这种应用场合下,DB9接口中的公头及母头的各个引脚的标准信号线接法见图 204及表 202。

     204 DB9标准的公头及母头接法

     202 DB9信号线说明(公头,为方便理解,可把DTE理解为计算机,DCE理解为调制调解器)

    序号

    名称

    符号

    数据方向

    说明

    1

    载波检测

    DCD

    DTEàDCE

    Data Carrier Detect,数据载波检测,用于DTE告知对方,本机是否收到对方的载波信号

    2

    接收数据

    RXD

    DTEßDCE

    Receive Data,数据接收信号,即输入

    3

    发送数据

    TXD

    DTEàDCE

    Transmit Data,数据发送信号,即输出。两个设备之间的TXDRXD应交叉相连

    4

    数据终端(DTE) 就绪

    DTR

    DTEàDCE

    Data Terminal Ready,数据终端就绪,用于DTE向对方告知本机是否已准备好

    5

    信号地

    GND

    -

    地线,两个通讯设备之间的地电位可能不一样,这会影响收发双方的电平信号,所以两个串口设备之间必须要使用地线连接,即共地。

    6

    数据设备(DCE)就绪

    DSR

    DTEßDCE

    Data Set Ready,数据发送就绪,用于DCE告知对方本机是否处于待命状态

    7

    请求发送

    RTS

    DTEàDCE

    Request To Send,请求发送, DTE 请求 DCE 本设备向DCE端发送数据

    8

    允许发送

    CTS

    DTEßDCE

    Clear To Send,允许发送,DCE回应对方的RTS发送请求,告知对方是否可以发送数据

    9

    响铃指示

    RI

    DTEßDCE

    Ring Indicator,响铃指示,表示DCE端与线路已接通

    上表中的是计算机端的DB9公头标准接法,由于两个通讯设备之间的收发信号(RXDTXD)应交叉相连,所以调制调解器端的DB9母头的收发信号接法一般与公头的相反,两个设备之间连接时,只要使用"直通型"的串口线连接起来即可,见图 205

     205 计算机与调制调解器的信号线连接

    串口线中的RTSCTSDSRDTRDCD信号,使用逻辑 1表示信号有效,逻辑0表示信号无效。例如,当计算机端控制DTR信号线表示为逻辑1时,它是为了告知远端的调制调解器,本机已准备好接收数据,0则表示还没准备就绪。

    在目前的其它工业控制使用的串口通讯中,一般只使用RXDTXD以及GND三条信号线,直接传输数据信号。而RTSCTSDSRDTRDCD信号都被裁剪掉了,如果您在前面被这些信号弄得晕头转向,那就直接忽略它们吧。

    20.1.2 协议层

    串口通讯的数据包由发送设备通过自身的TXD接口传输到接收设备的RXD接口。在串口通讯的协议层中,规定了数据包的内容,它由启始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据,其组成见图 206。

     206 串口数据包的基本组成

    1.    波特率

    本章中主要讲解的是串口异步通讯,异步通讯中由于没有时钟信号(如前面讲解的DB9接口中是没有时钟信号的),所以两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码,图 206中用虚线分开的每一格就是代表一个码元。常见的波特率为4800、9600、115200等。

    2.    通讯的起始和停止信号

    串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑0的数据位表示,而数据包的停止信号可由0.5、1、1.5或2个逻辑1的数据位表示,只要双方约定一致即可。

    3.    有效数据

    在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效数据的长度常被约定为5、6、7或8位长。

    4.    数据校验

    在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0校验(space)、1校验(mark)以及无校验(noparity),它们介绍如下:

        奇校验要求有效数据和校验位中"1"的个数为奇数,比如一个8位长的有效数据为:01101001,此时总共有4个"1",为达到奇校验效果,校验位为"1",最后传输的数据将是8位的有效数据加上1位的校验位总共9位。

        偶校验与奇校验要求刚好相反,要求帧数据和校验位中"1"的个数为偶数,比如数据帧:11001010,此时数据帧"1"的个数为4个,所以偶校验位为"0"。

        0校验是不管有效数据中的内容是什么,校验位总为"0",1校验是校验位总为"1"。

        在无校验的情况下,数据包中不包含校验位。

    20.2 STM32的USART简介

    STM32芯片具有多个USART外设用于串口通讯,它是 Universal Synchronous Asynchronous Receiver and Transmitter的缩写,即通用同步异步收发器可以灵活地与外部设备进行全双工数据交换。有别于USART,它还有具有UART外设(Universal Asynchronous Receiver and Transmitter),它是在USART基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是UART

    USART满足外部设备对工业标准NRZ异步串行数据格式的要求,并且使用了小数波特率发生器,可以提供多种波特率,使得它的应用更加广泛。USART支持同步单向通信和半双工单线通信;还支持局域互连网络LIN、智能卡(SmartCard)协议与lrDA(红外线数据协会) SIR ENDEC规范。

    USART支持使用DMA,可实现高速数据通信,有关DMA具体应用将在DMA章节作具体讲解。

    USARTSTM32应用最多莫过于"打印"程序信息,一般在硬件设计时都会预留一个USART通信接口连接电脑,用于在调试程序是可以把一些调试信息"打印"在电脑端的串口调试助手工具上,从而了解程序运行是否正确、指出运行出错位置等等。

    STM32USART输出的是TTL电平信号,若需要RS-232标准的信号可使用MAX3232芯片进行转换。

    20.3 USART功能框图

    STM32USART功能框图包含了USART最核心内容,掌握了功能框图,对USART就有一个整体的把握,在编程时就思路就非常清晰,见图 207

     207 USART功能框图

    1.    ①功能引脚

    TX:发送数据输出引脚。

    RX:接收数据输入引脚。

    SW_RX:数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚。

    nRTS:请求以发送(Request To Send)n表示低电平有效。如果使能RTS流控制,当USART接收器准备好接收新数据时就会将nRTS变成低电平;当接收寄存器已满时,nRTS将被设置为高电平。该引脚只适用于硬件流控制。

    nCTS:清除以发送(Clear To Send)n表示低电平有效。如果使能CTS流控制,发送器在发送下一帧数据之前会检测nCTS引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。

    SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。

    USART引脚在STM32F429IGT6芯片具体发布见表 203

     203 STM32F429IGT6芯片的USART引脚

      

    APB2(最高90MHz)

    APB1(最高45MHz)

    USART1

    USART6

    USART2

    USART3

    UART4

    UART5

    UART7

    UART8

    TX

    PA9/PB6

    PC6/PG14

    PA2/PD5

    PB10/PD8
    /PC10

    PA0/PC10

    PC12

    PF7/PE8

    PE1

    RX

    PA10/PB7

    PC7/PG9

    PA3/PD6

    PB11/PD9
    /PC11

    PA1/PC11

    PD2

    PF6/PE7

    PE0

    SCLK

    PA8

    PG7/PC8

    PA4/PD7

    PB12/PD10
    /PC12

      

      

      

      

    nCTS

    PA11

    PG13/PG15

    PA0/PD3

    PB13/PD11

      

      

      

      

    nRTS

    PA12

    PG8/PG12

    PA1/PD4

    PB14/PD12

      

      

      

      

    STM32F42xxx系统控制器有四个USART和四个UART,其中USART1USART6的时钟来源于APB2总线时钟,其最大频率为90MHz,其他六个的时钟来源于APB1总线时钟,其最大频率为45MHz

    UART只是异步传输功能,所以没有SCLKnCTSnRTS功能引脚。

    观察表 203可发现很多USART的功能引脚有多个引脚可选,这非常方便硬件设计,只要在程序编程时软件绑定引脚即可。

    2.    ②数据寄存器

    USART数据寄存器(USART_DR)只有低9位有效,并且第9位数据是否有效要取决于USART控制寄存器1(USART_CR1)M位设置,当M位为0时表示8位数据字长,当M位为1表示9位数据字长,我们一般使用8位数据字长。

    USART_DR包含了已发送的数据或者接收到的数据。USART_DR实际是包含了两个寄存器,一个专门用于发送的可写TDR,一个专门用于接收的可读RDR。当进行发送操作时,往USART_DR写入数据会自动存储在TDR内;当进行读取操作时,向USART_DR读取数据会自动提取RDR数据。

    TDRRDR都是介于系统总线和移位寄存器之间。串行通信是一个位一个位传输的,发送时把TDR内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接收时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到RDR

    USART支持DMA传输,可以实现高速数据传输,具体DMA使用将在DMA章节讲解。

    3.    ③控制器

    USART有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等等。使用USART之前需要向USART_CR1寄存器的UE位置1使能USART。发送或者接收数据字长可选8位或9位,由USART_CR1M位控制。

    发送器

    USART_CR1寄存器的发送使能位TE1时,启动数据发送,发送移位寄存器的数据会在TX引脚输出,如果是同步模式SCLK也输出时钟信号。

    一个字符帧发送需要三个部分:起始位+数据帧+停止位。起始位是一个位周期的低电平,位周期就是每一位占用的时间;数据帧就是我们要发送的8位或9位数据,数据是从最低位开始传输的;停止位是一定时间周期的高电平。

    停止位时间长短是可以通过USART控制寄存器2(USART_CR2)STOP[1:0]位控制,可选0.5个、1个、1.5个和2个停止位。默认使用1个停止位。2个停止位适用于正常USART模式、单线模式和调制解调器模式。0.5个和1.5个停止位用于智能卡模式。

    当选择8位字长,使用1个停止位时,具体发送字符时序图见图 208

     208 字符发送时序图

    当发送使能位TE1之后,发送器开始会先发送一个空闲帧(一个数据帧长度的高电平),接下来就可以往USART_DR寄存器写入要发送的数据。在写入最后一个数据后,需要等待USART状态寄存器(USART_SR)TC位为1,表示数据传输完成,如果USART_CR1寄存器的TCIE位置1,将产生中断。

    在发送数据时,编程的时候有几个比较重要的标志位我们来总结下。

    名称

    描述

    TE

    发送使能

    TXE

    发送寄存器为空,发送单个字节的时候使用

    TC

    发送完成,发送多个字节数据的时候使用

    TXIE

    发送完成中断使能

     

    接收器

    如果将USART_CR1寄存器的RE位置1,使能USART接收,使得接收器在RX线开始搜索起始位。在确定到起始位后就根据RX线电平状态把数据存放在接收移位寄存器内。接收完成后就把接收移位寄存器数据移到RDR内,并把USART_SR寄存器的RXNE位置1,同时如果USART_CR2寄存器的RXNEIE1的话可以产生中断。

    在接收数据时,编程的时候有几个比较重要的标志位我们来总结下。

    名称

    描述

    RE

    接收使能

    RXNE

    读数据寄存器非空

    RXNEIE

    发送完成中断使能

     

    为得到一个信号真实情况,需要用一个比这个信号频率高的采样信号去检测,称为过采样,这个采样信号的频率大小决定最后得到源信号准确度,一般频率越高得到的准确度越高,但为了得到越高频率采样信号越也困难,运算和功耗等等也会增加,所以一般选择合适就好。

    接收器可配置为不同过采样技术,以实现从噪声中提取有效的数据。USART_CR1寄存器的OVER8位用来选择不同的采样采样方法,如果OVER8位设置为1采用8倍过采样,即用8个采样信号采样一位数据;如果OVER8位设置为0采用16倍过采样,即用16个采样信号采样一位数据。

    USART的起始位检测需要用到特定序列。如果在RX线识别到该特定序列就认为是检测到了起始位。起始位检测对使用16倍或8倍过采样的序列都是一样的。该特定序列为:1110X0X0X0000,其中X表示电平任意,10皆可。

    8倍过采样速度更快,最高速度可达fPCLK/8fPCLKUSART时钟,采样过程见图 209。使用第456次脉冲的值决定该位的电平状态。

     209 8倍过采样过程

    16倍过采样速度虽然没有8倍过采样那么快,但得到的数据更加精准,其最大速度为fPCLK/16,采样过程见图 2010。使用第8910次脉冲的值决定该位的电平状态。

     2010 16倍过采样过程

    4.    ④小数波特率生成

    波特率指数据信号对载波的调制速率,它用单位时间内载波调制状态改变次数来表示,单位为波特。比特率指单位时间内传输的比特数,单位bit/s(bps)。对于USART波特率与比特率相等,以后不区分这两个概念。波特率越大,传输速率越快。

    USART的发送器和接收器使用相同的波特率。计算公式如下:

    公式 201 波特率计算

    其中,fPLCKUSART时钟,参考表 203OVER8USART_CR1寄存器的OVER8位对应的值,USARTDIV是一个存放在波特率寄存器(USART_BRR)的一个无符号定点数。其中DIV_Mantissa[11:0]位定义USARTDIV的整数部分,DIV_Fraction[3:0]位定义USARTDIV的小数部分,DIV_Fraction[3]位只有在OVER8位为0时有效,否则必须清零。

    例如,如果OVER8=0DIV_Mantissa=24DIV_Fraction=10,此时USART_BRR值为0x18A;那么USARTDIV的小数位10/16=0.625;整数位24,最终USARTDIV的值为24.625

    如果OVER8=0并且知道USARTDIV值为27.68,那么DIV_Fraction=16*0.68=10.88,最接近的正整数为11,所以DIV_Fraction[3:0]0xBDIV_Mantissa=整数(27.68)=27,即位0x1B

    如果OVER8=1情况类似,只是把计算用到的权值由16改为8

    波特率的常用值有2400960019200115200。下面以实例讲解如何设定寄存器值得到波特率的值。

    由表 203可知USART1USART6使用APB2总线时钟,最高可达90MHz,其他USART的最高频率为45MHz。我们选取USART1作为实例讲解,即fPLCK=90MHz

    当我们使用16倍过采样时即OVER8=0,为得到115200bps的波特率,此时:

     

    解得USARTDIV=48.825125,可算得DIV_Fraction=0xDDIV_Mantissa=0x30,即应该设置USART_BRR的值为0x30D

    在计算DIV_Fraction时经常出现小数情况,经过我们取舍得到整数,这样会导致最终输出的波特率较目标值略有偏差。下面我们从USART_BRR的值为0x30D开始计算得出实际输出的波特率大小。

    USART_BRR的值为0x30D,可得DIV_Fraction=13DIV_Mantissa=48,所以USARTDIV=48+16*0.13=48.8125,所以实际波特率为:115237;这个值跟我们的目标波特率误差为0.03%,这么小的误差在正常通信的允许范围内。

    8倍过采样时计算情况原理是一样的。

    5.    校验控制

    STM32F4xx系列控制器USART支持奇偶校验。当使用校验位时,串口传输的长度将是8位的数据帧加上1位的校验位总共9位,此时USART_CR1寄存器的M位需要设置为1,即9数据位。将USART_CR1寄存器的PCE位置1就可以启动奇偶校验控制,奇偶校验由硬件自动完成。启动了奇偶校验控制之后,在发送数据帧时会自动添加校验位,接收数据时自动验证校验位。接收数据时如果出现奇偶校验位验证失败,会见USART_SR寄存器的PE位置1,并可以产生奇偶校验中断。

    使能了奇偶校验控制后,每个字符帧的格式将变成:起始位+数据帧+校验位+停止位。

    6.    中断控制

    USART有多个中断请求事件,具体见表 204

     204 USART中断请求

    中断事件

    事件标志

    使能控制位

    发送数据寄存器为空

    TXE

    TXEIE

    CTS标志

    CTS

    CTSIE

    发送完成

    TC

    TCIE

    准备好读取接收到的数据

    RXNE

    RXNEIE

    检测到上溢错误

    ORE

    检测到空闲线路

    IDLE

    IDLEIE

    奇偶校验错误

    PE

    PEIE

    断路标志

    LBD

    LBDIE

    多缓冲通信中的噪声标志、
    上溢错误和帧错误

    NF/ORE/FE

    EIE

    20.4 USART初始化结构体详解

    标准库函数对每个外设都建立了一个初始化结构体,比如USART_InitTypeDef,结构体成员用于设置外设工作参数,并由外设初始化配置函数,比如USART_Init()调用,这些设定参数将会设置外设相应的寄存器,达到配置外设工作环境的目的。

    初始化结构体和初始化库函数配合使用是标准库精髓所在,理解了初始化结构体每个成员意义基本上就可以对该外设运用自如了。初始化结构体定义在stm32f4xx_usart.h文件中,初始化库函数定义在stm32f4xx_usart.c文件中,编程时我们可以结合这两个文件内注释使用。

    USART初始化结构体

    1 typedef struct {

    uint32_t USART_BaudRate; // 波特率

    uint16_t USART_WordLength; // 字长

    uint16_t USART_StopBits; // 停止位

    uint16_t USART_Parity; // 校验位

    uint16_t USART_Mode; // USART模式

    uint16_t USART_HardwareFlowControl; // 硬件流控制

    } USART_InitTypeDef;

    1)    USART_BaudRate:波特率设置。一般设置为2400、9600、19200、115200。标准库函数会根据设定值计算得到USARTDIV值,见公式 201,并设置USART_BRR寄存器值。

    2)    USART_WordLength:数据帧字长,可选8位或9位。它设定USART_CR1寄存器的M位的值。如果没有使能奇偶校验控制,一般使用8数据位;如果使能了奇偶校验则一般设置为9数据位。

    3)    USART_StopBits:停止位设置,可选0.5个、1个、1.5个和2个停止位,它设定USART_CR2寄存器的STOP[1:0]位的值,一般我们选择1个停止位。

    4)    USART_Parity:奇偶校验控制选择,可选USART_Parity_No(无校验)、USART_Parity_Even(偶校验)以及USART_Parity_Odd(奇校验),它设定USART_CR1寄存器的PCE位和PS位的值。

    5)    USART_Mode:USART模式选择,有USART_Mode_Rx和USART_Mode_Tx,允许使用逻辑或运算选择两个,它设定USART_CR1寄存器的RE位和TE位。

    6)    USART_HardwareFlowControl:硬件流控制选择,只有在硬件流控制模式才有效,可选有⑴使能RTS、⑵使能CTS、⑶同时使能RTS和CTS、⑷不使能硬件流。

    当使用同步模式时需要配置SCLK引脚输出脉冲的属性,标准库使用一个时钟初始化结构体USART_ClockInitTypeDef来设置,因此该结构体内容也只有在同步模式才需要设置。

    USART时钟初始化结构体

    1 typedef struct {

    uint16_t USART_Clock; // 时钟使能控制

    uint16_t USART_CPOL; // 时钟极性

    uint16_t USART_CPHA; // 时钟相位

    uint16_t USART_LastBit; // 最尾位时钟脉冲

    } USART_ClockInitTypeDef;

    1)    USART_Clock:同步模式下SCLK引脚上时钟输出使能控制,可选禁止时钟输出(USART_Clock_Disable)或开启时钟输出(USART_Clock_Enable);如果使用同步模式发送,一般都需要开启时钟。它设定USART_CR2寄存器的CLKEN位的值。

    2)    USART_CPOL:同步模式下SCLK引脚上输出时钟极性设置,可设置在空闲时SCLK引脚为低电平(USART_CPOL_Low)或高电平(USART_CPOL_High)。它设定USART_CR2寄存器的CPOL位的值。

    3)    USART_CPHA:同步模式下SCLK引脚上输出时钟相位设置,可设置在时钟第一个变化沿捕获数据(USART_CPHA_1Edge)或在时钟第二个变化沿捕获数据。它设定USART_CR2寄存器的CPHA位的值。USART_CPHA与USART_CPOL配合使用可以获得多种模式时钟关系。

    4)    USART_LastBit:选择在发送最后一个数据位的时候时钟脉冲是否在SCLK引脚输出,可以是不输出脉冲(USART_LastBit_Disable)、输出脉冲(USART_LastBit_Enable)。它设定USART_CR2寄存器的LBCL位的值。

    20.5 USART1接发通信实验

    USART只需两根信号线即可完成双向通信,对硬件要求低,使得很多模块都预留USART接口来实现与其他模块或者控制器进行数据传输,比如GSM模块,WIFI模块、蓝牙模块等等。在硬件设计时,注意还需要一根"共地线"。

    我们经常使用USART来实现控制器与电脑之间的数据传输。这使得我们调试程序非常方便,比如我们可以把一些变量的值、函数的返回值、寄存器标志位等等通过USART发送到串口调试助手,这样我们可以非常清楚程序的运行状态,当我们正式发布程序时再把这些调试信息去除即可。

    我们不仅仅可以将数据发送到串口调试助手,我们还可以在串口调试助手发送数据给控制器,控制器程序根据接收到的数据进行下一步工作。

    首先,我们来编写一个程序实现开发板与电脑通信,在开发板上电时通过USART发送一串字符串给电脑,然后开发板进入中断接收等待状态,如果电脑有发送数据过来,开发板就会产生中断,我们在中断服务函数接收数据,并马上把数据返回发送给电脑。

    20.5.1 硬件设计

    为利用USART实现开发板与电脑通信,需要用到一个USBUSARTIC,我们选择CH340G芯片来实现这个功能,CH340G是一个USB总线的转接芯片,实现USBUSARTUSBIrDA红外或者USB转打印机接口,我们使用其USBUSART功能。具体电路设计见图 2011

    我们将CH340GTXD引脚与USART1RX引脚连接,CH340GRXD引脚与USART1TX引脚连接。CH340G芯片集成在开发板上,其地线(GND)已与控制器的GND连通。

     2011 USB转串口硬件设计

    20.5.2 软件设计

    这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。我们创建了两个文件:bsp_debug_usart.cbsp_debug_usart.h文件用来存放USART驱动程序及相关宏定义。

    1.    编程要点

    1)    使能RX和TX引脚GPIO时钟和USART时钟;

    2)    初始化GPIO,并将GPIO复用到USART上;

    3)    配置USART参数;

    4)    配置中断控制器并使能USART接收中断;

    5)    使能USART;

    6)    在USART接收中断服务函数实现数据接收和发送。

    2.    代码分析
    GPIO和USART宏定义

    代码清单 201 GPIOUSART宏定义

    #define DEBUG_USART USART1

    #define DEBUG_USART_CLK RCC_APB2Periph_USART1

    #define DEBUG_USART_BAUDRATE 115200 //串口波特率

    4

    #define DEBUG_USART_RX_GPIO_PORT GPIOA

    #define DEBUG_USART_RX_GPIO_CLK RCC_AHB1Periph_GPIOA

    #define DEBUG_USART_RX_PIN GPIO_Pin_10

    #define DEBUG_USART_RX_AF GPIO_AF_USART1

    #define DEBUG_USART_RX_SOURCE GPIO_PinSource10

    10

    11 #define DEBUG_USART_TX_GPIO_PORT GPIOA

    12 #define DEBUG_USART_TX_GPIO_CLK RCC_AHB1Periph_GPIOA

    13 #define DEBUG_USART_TX_PIN GPIO_Pin_9

    14 #define DEBUG_USART_TX_AF GPIO_AF_USART1

    15 #define DEBUG_USART_TX_SOURCE GPIO_PinSource9

    16

    17 #define DEBUG_USART_IRQHandler USART1_IRQHandler

    18 #define DEBUG_USART_IRQ USART1_IRQn

    使用宏定义方便程序移植和升级,根据图 2011电路,我们选择使用USART1,设定波特率为115200,一般我们会默认使用"8-N-1"参数,即8个数据位、不用校验、一位停止位。查阅表 203可知USART1TX线可对于PA9PB6引脚,RX线可对于PA10PB7引脚,这里我们选择PA9以及PA10引脚。最后定义中断相关参数。

    嵌套向量中断控制器NVIC配置

    代码清单 202 中断控制器NVIC配置

    static void NVIC_Configuration(void)

    {

    NVIC_InitTypeDef NVIC_InitStructure;

    4

    /* 嵌套向量中断控制器组选择 */

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    7

    /* 配置USART为中断源 */

    NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;

    10 /* 抢断优先级为1 */

    11 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

    12 /* 子优先级为1 */

    13 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

    14 /* 使能中断 */

    15 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    16 /* 初始化配置NVIC */

    17 NVIC_Init(&NVIC_InitStructure);

    18 }

    19

    在中断章节已对嵌套向量中断控制器的工作机制做了详细的讲解,这里我们就直接使用它,配置USART作为中断源,因为本实验没有使用其他中断,对优先级什么具体要求。

    USART初始化配置

    代码清单 203 USART初始化配置

    void Debug_USART_Config(void)

    {

    GPIO_InitTypeDef GPIO_InitStructure;

    USART_InitTypeDef USART_InitStructure;

    /* 使能 USART GPIO 时钟 */

    RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK |

    DEBUG_USART_TX_GPIO_CLK,

    ENABLE);

    9

    10 /* 使能 USART 时钟 */

    11 RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);

    12

    13 /* GPIO初始化 */

    14 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    15 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

    16 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    17

    18 /* 配置Tx引脚为复用功能 */

    19 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    20 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN ;

    21 GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

    22

    23 /* 配置Rx引脚为复用功能 */

    24 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    25 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;

    26 GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);

    27

    28 /* 连接 PXx  USARTx_Tx*/

    29 GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,

    30 DEBUG_USART_RX_SOURCE,

    31 DEBUG_USART_RX_AF);

    32

    33 /* 连接 PXx  USARTx__Rx*/

    34 GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,

    35 DEBUG_USART_TX_SOURCE,

    36 DEBUG_USART_TX_AF);

    37

    38 /* 配置串DEBUG_USART 模式 */

    39 /* 波特率设置:DEBUG_USART_BAUDRATE */

    40 USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;

    41 /* 字长(数据位+校验位)8 */

    42 USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    43 /* 停止位:1个停止位 */

    44 USART_InitStructure.USART_StopBits = USART_StopBits_1;

    45 /* 校验位选择:不使用校验 */

    46 USART_InitStructure.USART_Parity = USART_Parity_No;

    47 /* 硬件流控制:不使用硬件流 */

    48 USART_InitStructure.USART_HardwareFlowControl =

    49 USART_HardwareFlowControl_None;

    50 /* USART模式控制:同时使能接收和发送 */

    51 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    52 /* 完成USART初始化配置 */

    53 USART_Init(DEBUG_USART, &USART_InitStructure);

    54

    55 /* 嵌套向量中断控制器NVIC配置 */

    56 NVIC_Configuration();

    57

    58 /* 使能串口接收中断 */

    59 USART_ITConfig(DEBUG_USART, USART_IT_RXNE, ENABLE);

    60

    61 /* 使能串口 */

    62 USART_Cmd(DEBUG_USART, ENABLE);

    63 }

    64

    使用GPIO_InitTypeDefUSART_InitTypeDef结构体定义一个GPIO初始化变量以及一个USART初始化变量,这两个结构体内容我们之前已经有详细讲解。

    调用RCC_AHB1PeriphClockCmd函数开启GPIO端口时钟,使用GPIO之前必须开启对应端口的时钟。使用RCC_APB2PeriphClockCmd函数开启USART时钟。

    使用GPIO之前都需要初始化配置它,并且还要添加特殊设置,因为我们使用它作为外设的引脚,一般都有特殊功能。我们在初始化时需要把它的模式设置为复用功能。

    每个GPIO都可以作为多个外设的特殊功能引脚,比如PA10这个引脚不仅仅可以作为普通的输入\输出引脚,还可以作为USART1RX线引脚(USART1_RX)、定时器1通道3引脚(TIM1_CH3)、全速OTGID引脚(OTG_FS_ID)以及DCMI的数据1引脚(DCMI_D1)这四个外设的功能引脚,我们只能从中选择一个使用,这时就通过GPIO引脚复用功能配置(GPIO_PinAFConfig)函数实现复用功能引脚的连接。

    这时我们可能会想如果程序把PA10用于TIM1_CH3,此时USART1_RX就没办法使用了,那岂不是不能使用USART1了,实际上情况没有这么糟糕的,查阅表 203我们可以看到USART1_RX不仅仅只有PA10,还可以是PB7。所以此时我们可以PB7这个引脚来实现USART1通信。那要是PB7也是被其他外设占用了呢?那就没办法了,只能使用其他USART

    GPIO_PinAFConfig函数接收三个参数,第一个参数为GPIO端口,比如GPIOA;第二个参数是指定要复用的引脚号,比如GPIO_PinSource10;第三个参数是选择复用外设,比如GPIO_AF_USART1。该函数最终操作的是GPIO复用功能寄存器GPIO_AFRHGPIO_AFRL,分高低两个。

    接下来,我们配置USART1通信参数并调用USART初始化函数完成配置。

    程序用到USART接收中断,需要配置NVIC,这里调用NVIC_Configuration函数完成配置。配置NVIC就可以调用USART_ITConfig函数使能USART接收中断。

    最后调用USART_Cmd函数使能USART

    字符发送

    代码清单 204 字符发送函数

    /***************** 发送一个字符 **********************/

    void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)

    {

    /* 发送一个字节数据到USART */

    USART_SendData(pUSARTx,ch);

    6

    /* 等待发送数据寄存器为空 */

    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);

    }

    10

    11 /***************** 发送字符串 **********************/

    12 void Usart_SendString( USART_TypeDef * pUSARTx, char *str)

    13 {

    14 unsigned int k=0;

    15 do {

    16 Usart_SendByte( pUSARTx, *(str + k) );

    17 k++;

    18 while (*(str + k)!='\0');

    19

    20 /* 等待发送完成 */

    21 while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {

    22 }

    23 }

    Usart_SendByte函数用来在指定USART发送一个ASCLL码值字符,它有两个形参,第一个为USART,第二个为待发送的字符。它是通过调用库函数USART_SendData来实现的,并且增加了等待发送完成功能。通过使用USART_GetFlagStatus函数来获取USART事件标志来实现发送完成功能等待,它接收两个参数,一个是USART,一个是事件标志。这里我们循环检测发送数据寄存器为空这个标志,当跳出while循环时说明发送数据寄存器为空这个事实。

    Usart_SendString函数用来发送一个字符串,它实际是调用Usart_SendByte函数发送每个字符,直到遇到空字符才停止发送。最后使用循环检测发送完成的事件标志来实现保证数据发送完成后才退出函数。

    USART中断服务函数

    代码清单 205 USART中断服务函数

    void DEBUG_USART_IRQHandler(void)

    {

    uint8_t ucTemp;

    if (USART_GetITStatus(DEBUG_USART,USART_IT_RXNE)!=RESET) {

    ucTemp = USART_ReceiveData( DEBUG_USART );

    USART_SendData(DEBUG_USART,ucTemp);

    }

    8

    }

    这段代码是存放在stm32f4xx_it.c文件中的,该文件用来集中存放外设中断服务函数。当我们使能了中断并且中断发生时就会执行中断服务函数。

    我们在代码清单 203使能了USART接收中断,当USART有接收到数据就会执行DEBUG_USART_IRQHandler函数。USART_GetITStatus函数与USART_GetFlagStatus函数类似用来获取标志位状态,但USART_GetITStatus函数是专门用来获取中断事件标志的,并返回该标志位状态。使用if语句来判断是否是真的产生USART数据接收这个中断事件,如果是真的就使用USART数据读取函数USART_ReceiveData读取数据到指定存储区。然后再调用USART数据发送函数USART_SendData把数据又发送给源设备。

    主函数

    代码清单 206 主函数

    int main(void)

    {

    /*初始化USART 配置模式为 115200 8-N-1,中断接收*/

    Debug_USART_Config();

    5

    Usart_SendString( DEBUG_USART,"这是一个串口中断接收回显实验\n");

    7

    while (1) {

    9

    10 }

    11 }

    首先我们需要调用Debug_USART_Config函数完成USART初始化配置,包括GPIO配置,USART配置,接收中断使用等等信息。

    接下来就可以调用字符发送函数把数据发送给串口调试助手了。

    最后主函数什么都不做,只是静静地等待USART接收中断的产生,并在中断服务函数把数据回传。

    20.5.3 下载验证

    保证开发板相关硬件连接正确,用USB线连接开发板"USB TO UART"接口跟电脑,在电脑端打开串口调试助手,把编译好的程序下载到开发板,此时串口调试助手即可收到开发板发过来的数据。我们在串口调试助手发送区域输入任意字符,点击发送按钮,马上在串口调试助手接收区即可看到相同的字符。

     2012 实验现象

    20.6 USART1指令控制RGB彩灯实验

    在学习C语言时我们经常使用C语言标准函数库输入输出函数,比如printfscanfgetchar等等。为让开发板也支持这些函数需要把USART发送和接收函数添加到这些函数的内部函数内。

    正如之前所讲,可以在串口调试助手输入指令,让开发板根据这些指令执行一些任务,现在我们编写让程序接收USART数据,根据数据内容控制RGB彩灯的颜色。

    20.6.1 硬件设计

    硬件设计同第一个实验。

    20.6.2 软件设计

    这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。我们创建了两个文件:bsp _usart.cbsp _usart.h文件用来存放USART驱动程序及相关宏定义。

    1.    编程要点

    1)    初始化配置RGB彩色灯GPIO;

    2)    使能RX和TX引脚GPIO时钟和USART时钟;

    3)    初始化GPIO,并将GPIO复用到USART上;

    4)    配置USART参数;

    5)    使能USART;

    6)    获取指令输入,根据指令控制RGB彩色灯。

    2.    代码分析
    GPIO和USART宏定义

    代码清单 207 GPIOUSART宏定义

    
    						1 //引脚定义
    			

    /*******************************************************/

    #define USARTx USART1

    4

    /* 不同的串口挂载的总线不一样,时钟使能函数也不一样,移植时要注意

    串口16 RCC_APB2PeriphClockCmd

    串口2/3/4/5/7 RCC_APB1PeriphClockCmd

    */

    #define USARTx_CLK RCC_APB2Periph_USART1

    10 #define USARTx_CLOCKCMD RCC_APB2PeriphClockCmd

    11 #define USARTx_BAUDRATE 115200 //串口波特率

    12

    13 #define USARTx_RX_GPIO_PORT GPIOA

    14 #define USARTx_RX_GPIO_CLK RCC_AHB1Periph_GPIOA

    15 #define USARTx_RX_PIN GPIO_Pin_10

    16 #define USARTx_RX_AF GPIO_AF_USART1

    17 #define USARTx_RX_SOURCE GPIO_PinSource10

    18

    19 #define USARTx_TX_GPIO_PORT GPIOA

    20 #define USARTx_TX_GPIO_CLK RCC_AHB1Periph_GPIOA

    21 #define USARTx_TX_PIN GPIO_Pin_9

    22 #define USARTx_TX_AF GPIO_AF_USART1

    23 #define USARTx_TX_SOURCE GPIO_PinSource9

    24

    25 /************************************************************/

    使用宏定义方便程序移植和升级,这里我们可以USART1,设定波特率为115200

    USART初始化配置

    代码清单 208 USART初始化配置

    void USARTx_Config(void)

    {

    GPIO_InitTypeDef GPIO_InitStructure;

    USART_InitTypeDef USART_InitStructure;

    5

    RCC_AHB1PeriphClockCmd(USARTx_RX_GPIO_CLK|USARTx_TX_GPIO_CLK,ENABLE);

    7

    /* 使能 USART 时钟 */

    USARTx_CLOCKCMD(USARTx_CLK, ENABLE);

    10

    11 /* GPIO初始化 */

    12 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    13 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

    14 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    15

    16 /* 配置Tx引脚为复用功能 */

    17 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    18 GPIO_InitStructure.GPIO_Pin = USARTx_TX_PIN ;

    19 GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStructure);

    20

    21 /* 配置Rx引脚为复用功能 */

    22 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    23 GPIO_InitStructure.GPIO_Pin = USARTx_RX_PIN;

    24 GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStructure);

    25

    26 /* 连接 PXx  USARTx_Tx*/

    27 GPIO_PinAFConfig(USARTx_RX_GPIO_PORT,USARTx_RX_SOURCE,USARTx_RX_AF);

    28

    29 /* 连接 PXx  USARTx__Rx*/

    30 GPIO_PinAFConfig(USARTx_TX_GPIO_PORT,USARTx_TX_SOURCE,USARTx_TX_AF);

    31

    32 /* 配置串DEBUG_USART 模式 */

    33 /* 波特率设置:DEBUG_USART_BAUDRATE */

    34 USART_InitStructure.USART_BaudRate = USARTx_BAUDRATE;

    35 /* 字长(数据位+校验位)8 */

    36 USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    37 /* 停止位:1个停止位 */

    38 USART_InitStructure.USART_StopBits = USART_StopBits_1;

    39 /* 校验位选择:偶校验 */

    40 USART_InitStructure.USART_Parity = USART_Parity_No;

    41 /* 硬件流控制:不使用硬件流 */

    42 USART_InitStructure.USART_HardwareFlowControl =

    43 USART_HardwareFlowControl_None;

    44 /* USART模式控制:同时使能接收和发送 */

    45 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    46 /* 完成USART初始化配置 */

    47 USART_Init(USARTx, &USART_InitStructure);

    48

    49 /* 使能串口 */

    50 USART_Cmd(USARTx, ENABLE);

    51 }

    使用GPIO_InitTypeDefUSART_InitTypeDef结构体定义一个GPIO初始化变量以及一个USART初始化变量,这两个结构体内容我们之前已经有详细讲解。

    调用RCC_AHB1PeriphClockCmd函数开启GPIO端口时钟,使用GPIO之前必须开启对应端口的时钟。

    初始化配置RX线和TX线引脚为复用功能,并将指定的GPIO连接至USART1,然后配置串口的工作参数为115200-8-N-1。最后调用USART_Cmd函数使能USART

    重定向prinft和scanf函数

    代码清单 209 重定向输入输出函数

    ///重定向c库函数printf到串口,重定向后可使用printf函数

    int fputc(int ch, FILE *f)

    {

    /* 发送一个字节数据到串口 */

    USART_SendData(USARTx, (uint8_t) ch);

    6

    /* 等待发送完毕 */

    while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);

    9

    10 return (ch);

    11 }

    12

    13 ///重定向c库函数scanf到串口,重写向后可使用scanfgetchar等函数

    14 int fgetc(FILE *f)

    15 {

    16 /* 等待串口输入数据 */

    17 while (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == RESET);

    18

    19 return (int)USART_ReceiveData(USARTx);

    20 }

    C语言标准库中,fputc函数是printf函数内部的一个函数,功能是将字符ch写入到文件指针f所指向文件的当前写指针位置,简单理解就是把字符写入到特定文件中。我们使用USART函数重新修改fputc函数内容,达到类似"写入"的功能。

    fgetc函数与fputc函数非常相似,实现字符读取功能。在使用scanf函数时需要注意字符输入格式。

    还有一点需要注意的,使用fputfgetc函数达到重定向C语言标准库输入输出函数必须在MDK的工程选项把"Use MicroLIB"勾选上,MicoroLIB是缺省C库的备选库,它对标准C库进行了高度优化使代码更少,占用更少资源。

    为使用printfscanf函数需要在文件中包含stdio.h头文件。

    输出提示信息

    代码清单 2010 输出提示信息

    static void Show_Message(void)

    {

    printf("\r\n这是一个通过串口通信指令控制RGB彩灯实验 \n");

    printf("使用 USART1 参数为:%d 8-N-1 \n",USARTx_BAUDRATE);

    printf("开发板接到指令后控制RGB彩灯颜色,指令对应如下:\n");

    printf(指令 ------ 彩灯颜色 \n");

    printf(" 1 ------  \n");

    printf(" 2 ------ 绿 \n");

    printf(" 3 ------  \n");

    10 printf(" 4 ------  \n");

    11 printf(" 5 ------  \n");

    12 printf(" 6 ------  \n");

    13 printf(" 7 ------  \n");

    14 printf(" 8 ------  \n");

    15 }

    Show_Message函数全部是调用printf函数,"打印"实验操作信息到串口调试助手。

    主函数

    代码清单 2011 主函数

    int main(void)

    {

    char ch;

    4

    /* 初始化RGB彩灯 */

    LED_GPIO_Config();

    7

    /* 初始化USART 配置模式为 115200 8-N-1 */

    USARTx_Config();

    10

    11 /* 打印指令输入提示信息 */

    12 Show_Message();

    13 while (1)

    14 {

    15 /* 获取字符指令 */

    16 ch=getchar();

    17 printf("接收到字符:%c\n",ch);

    18

    19 /* 根据字符指令控制RGB彩灯颜色 */

    20 switch (ch)

    21 {

    22 case '1':

    23 LED_RED;

    24 break;

    25 case '2':

    26 LED_GREEN;

    27 break;

    28 case '3':

    29 LED_BLUE;

    30 break;

    31 case '4':

    32 LED_YELLOW;

    33 break;

    34 case '5':

    35 LED_PURPLE;

    36 break;

    37 case '6':

    38 LED_CYAN;

    39 break;

    40 case '7':

    41 LED_WHITE;

    42 break;

    43 case '8':

    44 LED_RGBOFF;

    45 break;

    46 default:

    47 /* 如果不是指定指令字符,打印提示信息 */

    48 Show_Message();

    49 break;

    50 }

    51 }

    52 }

    首先我们定义一个字符变量来存放接收到的字符。

    接下来调用LED_GPIO_Config函数完成RGB彩色GPIO初始化配置,该函数定义在bsp_led.c文件内。

    调用USARTx_Config函完成USART初始化配置。

    Show_Message函数使用printf函数打印实验指令说明信息。

    getchar函数用于等待获取一个字符,并返回字符。我们使用ch变量保持返回的字符,接下来判断ch内容执行对应的程序了。

    我们使用switch语句判断ch变量内容,并执行对应的功能程序。

    20.6.3 下载验证

    保证开发板相关硬件连接正确,用USB线连接开发板"USB TO UART"接口跟电脑,在电脑端打开串口调试助手,把编译好的程序下载到开发板,此时串口调试助手即可收到开发板发过来的数据。我们在串口调试助手发送区域输入一个特定字符,点击发送按钮,RGB彩色灯状态随之改变。

    20.7 每课一问

    1、串口1实验中发送的数据都是8位的,如果要发送的数据是16位的话,怎么办,程序应该怎么修改?

    答案如下

    /***************** 发送一个16位数 **********************/

    void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)

    {

    uint8_t temp_h, temp_l;

    5

    /* 取出高八位 */

    temp_h = (ch&0XFF00)>>8;

    /* 取出低八位 */

    temp_l = ch&0XFF;

    10

    11 /* 发送高八位 */

    12 USART_SendData(pUSARTx,temp_h);

    13 while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);

    14

    15 /* 发送低八位 */

    16 USART_SendData(pUSARTx,temp_l);

    17 while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);

    18 }

    2、改写USART1指令控制RGB彩灯实验程序,把串口1换成串口2。

    开源共享,共同进步。
    展开全文
  • 物联网通讯协议介绍

    千次阅读 2015-10-16 18:07:15
    为了方便,将物联网通信协议分为两大类,一类是接入协议,一类是通讯协议。接入协议一般负责子网内设备间的组网及通信;通讯协议主要是运行在传统互联网TCP/IP协议之上的设备通讯协议,负责设备通过互联网进行数据...

    为了方便,将物联网通信协议分为两大类,一类是接入协议,一类是通讯协议。接入协议一般负责子网内设备间的组网及通信;通讯协议主要是运行在传统互联网TCP/IP协议之上的设备通讯协议,负责设备通过互联网进行数据交换及通信。本文介绍以通讯协议为主。

    先说接入协议

    市场上常见的有zigbee、蓝牙以及wifi协议等。

    一、zigbee

    zigbee目前在工业控制领域应用广泛,在智能家居领域也有一定应用。它有以下主要优势:

    1. 低成本。zigbee协议数据传输速率低,协议简单,所以开发成本也比较低。并且zigbee协议还免收专利费用~

    2. 低功耗。由于zigbee协议传输速率低,节点所需的发射功率仅1mW,并采用休眠+唤醒模式,功耗极低。

    3. 自组网。通过zigbee协议自带的mesh功能,一个子网络内可以支持多达65000个节点连接,可以快速实现一个大规模的传感网络。

    4. 安全性。使用crc校验数据包的完整性,支持鉴权和认证,并且采用aes-128对传输数据进行加密。

    zigbee协议的最佳应用场景是无线传感网络,比如水质监测、环境控制等节点之间需要自组网传输数据的工业场景中。在这些场景中zigbee协议的优势发挥的非常明显。目前国内外很多厂商也将zigbee运用在智能家居方案中,比如今年年初小米发布的“小米智能家居套装”。

    为什么厂商会抛弃使用比较广泛的wifi及蓝牙协议,而采用zigbee呢,主要有以下原因:

    1. 刚才提到zigbee协议有很强的自组网能力,可以支持几万设备,特别对于小米这种想构建智能家居生态链的企业,wifi和蓝牙的设备连接数量目前都是硬伤。

    2. 目前zigbee协议还很难轻易被破解,而其他协议在安全性上一直为人诟病。

    3. 很多智能家居产品如门磁为了使用方便,一般采用内置电池。此时zigbee的超低功耗大大提升了产品体验。

    但是zigbee协议也有不足,主要就是它虽然可以方便的组网但不能接入互联网,所以zigbee网络中必须有一个节点充当路由器的角色(比如小米智能家居套装中的智能网关),这提高了成本并且增加了用户使用门槛。同时由于zigbee协议数据传输速率低,对于大流量应用如流媒体、视频等,基本是不可能。

    相对wifi和蓝牙协议这些年的快速发展和商业普及,zigbee协议尽管在技术设计和架构上拥有很大优势,但是技术更新太慢,同时在市场推广中也被竞争对手拉开了差距。后续zigbee协议在行业领域还是有很大空间,但是家用及消费领域要挑战wifi及蓝牙协议不是那么容易了。

    二、蓝牙

    蓝牙目前已经成为智能手机的标配通信组件,其迅速发展的原因包括:

    1. 低功耗。我认为这是蓝牙4.0的大杀器~使用纽扣电池的蓝牙4.0设备可运行一年以上,这对不希望频繁充电的可穿戴设备具有十分大的吸引力。当前基本世面上的可穿戴设备基本都选用蓝牙4.0方案。

    2. 智能手机的普及。近年来支持蓝牙协议基本成为智能手机的标配,用户无需购买额外的接入模块。

    值得关注的是蓝牙4.2版本近期推出,加入mesh组网功能,向zigbee发出了强有力的挑战。

    三、wifi

    wifi协议和蓝牙协议一样,目前也得到了非常大的发展。由于前几年家用wifi路由器以及智能手机的迅速普及,wifi协议在智能家居领域也得到了广泛应用。wifi协议最大的优势是可以直接接入互联网。相对于zigbee,采用wifi协议的智能家居方案省去了额外的网关,相对于蓝牙协议,省去了对手机等移动终端的依赖。

    相当于蓝牙和zigbee,wifi协议的功耗成为其在物联网领域应用的一大瓶颈。但是随着现在各大芯片厂商陆续推出低功耗、低成本的wifi soc(如esp8266),这个问题也在逐渐被解决。

    谁将一统江湖?

    wifi协议和蓝牙协议谁会在物联网领域一统江湖?这是目前讨论比较多的一个话题。wifi和蓝牙的各自在技术的优势双方都可以在协议升级的过程中互相完善,目前两个协议都在往“各取所长”的方向发展。最终谁能占据主导,可能更重要的是商业力量和市场决定的。短期内各个协议肯定是适用不同的场景,都有存在的价值。

    再说通讯协议

    对于物联网,最重要的是在互联网中设备与设备的通讯,现在物联网在internet通信中比较常见的通讯协议包括:HTTP、websocket、XMPP、COAP、MQTT

    一、HTTP和websocket
    在互联网时代,TCP/IP协议已经一统江湖,现在的物联网的通信架构也是构建在传统互联网基础架构之上。在当前的互联网通信协议中,HTTP协议由于开发成本低,开放程度高,几乎占据大半江山,所以很多厂商在构建物联网系统时也基于http协议进行开发。包括google主导的physic web项目,都是期望在传统web技术基础上构建物联网协议标准。

    HTTP协议是典型的CS通讯模式,由客户端主动发起连接,向服务器请求XML或JSON数据。该协议最早是为了适用web浏览器的上网浏览场景和设计的,目前在PC、手机、pad等终端上都应用广泛,但并不适用于物联网场景。在物联网场景中其有三大弊端:

    1. 由于必须由设备主动向服务器发送数据,难以主动向设备推送数据。对于单单的数据采集等场景还勉强适用,但是对于频繁的操控场景,只能推过设备定期主动拉取的的方式,实现成本和实时性都大打折扣。

    2. 安全性不高。web的不安全都是妇孺皆知,HTTP是明文协议,在很多要求高安全性的物联网场景,如果不做很多安全准备工作(如采用https等),后果不堪设想…

    3. 不同于用户交互终端如pc、手机,物联网场景中的设备多样化,对于运算和存储资源都十分受限的设备,http协议实现、XML/JSON数据格式的解析,都是“mission impossible”

    当然,依然有不少厂商由于开发方便的原因,选择基于HTTP协议构架物联网系统,在设备资源允许的情况下,怎么避免上面提到的数据推送实时性低的问题呢?

    websocket是一个可行的办法。websocket是HTML5提出的基于TCP之上的可支持全双工通信的协议标准,其在设计上基本遵循HTTP的思路,对于基于HTTP协议的物联网系统是一个很好的补充。

    二、XMPP

    由于物联网设备通信的模式和互联网中的即时通讯应用非常相似,互联网中常用的即时通讯协议也被大量运用于物联网系统构建中,这其中的典型是XMPP。

    XMPP是基于XML的协议,由于其开放性和易用性,在互联网及时通讯应用中运用广泛。相对HTTP,XMPP在通讯的业务流程上是更适合物联网系统的,开发者不用花太多心思去解决设备通讯时的业务通讯流程,相对开发成本会更低。但是HTTP协议中的安全性以及计算资源消耗的硬伤并没有得到本质的解决。前段时间报出的黑客轻松破解的TCL洗衣机,正是采用XMPP协议。

    无论是HTTP、websocket还是XMPP,在设计时都是根据互联网应用场景设计的,虽然很多厂商把他们应用在物联网系统中,但是必然会水土不服,这些协议的通病就是根本无法适用物联网设备的多样性,无法适用很多物联网设备对低功耗、低成本的需求,难以在极低资源的物联网设备中运用。能不能有协议既可以借用web技术的设计思想,同时又能适应恶劣的物联网设备运行环境呢?

    COAP协议应运而生了。

    三、COAP

    COAP协议的设计目标就是在低功耗低速率的设备上实现物联网通信。coap和HTTP协议一样,采用URL标示需要发送的数据,在协议格式的设计上也基本是参考HTTP协议,非常容易理解。同时做了以下几点优化:

    1. 采用UDP而不是TCP。这省去了TCP建立连接的成本及协议栈的开销。

    2. 将数据包头部都采用二进制压缩,减小数据量以适应低网络速率场景。

    3. 发送和接收数据可以异步进行,这样提升了设备响应速度。

    COAP协议就像一个针对物联网场景的http移植品,很多设计保留了HTTP协议的影子,拥有web背景的开发者也能快速上手。但是由于很多物联网设备隐藏在局域网内部,coap设备作为服务器无法被外部设备寻址,在ipv6没有普及之前,coap只能适用于局域网内部(如wifi)通信,这也很大限制了它的发展。

    四、MQTT协议

     

    MQTT协议就很好的解决了coap存在的问题。MQTT协议是由IBM开发的即时通讯协议,相比来说比较适合物联网场景的通讯协议。MQTT协议采用发布/订阅模式,所有的物联网终端都通过TCP连接到云端,云端通过主题的方式管理各个设备关注的通讯内容,负责将设备与设备之间消息的转发。

    MQTT在协议设计时就考虑到不同设备的计算性能的差异,所以所有的协议都是采用二进制格式编解码,并且编解码格式都非常易于开发和实现。最小的数据包只有2个字节,对于低功耗低速网络也有很好的适应性。有非常完善的QOS机制,根据业务场景可以选择最多一次、至少一次、刚好一次三种消息送达模式。运行在TCP协议之上,同时支持TLS(TCP+SSL)协议,并且由于所有数据通信都经过云端,安全性得到了较好地保障。

    但是mqtt协议的局限性是不支持设备的直连,对于可直接连接(如同一个局域网内)的设备也必须通过云端进行消息转发。


    当前的物联网通信协议真的是百花齐放,没有任何协议能够在市场上占有统治地位。但要实现物联网设备互联互通(不同厂商、不同平台、不同架构),关键点并不在上述接入协议或通讯协议的统一,而在于上层业务应用层协议的统一。无论是wifi、蓝牙、亦或是mqtt、http都是设备进行数据通讯和交换的通道,规定的是通讯的格式;而通讯的内容的统一才是实现互联互通的关键。

    如果把通信协议比作声音,光有通信协议,任何人之间还是无法交流。只有统一语言,大家才能顺畅沟通。

    展开全文
  • ODrive 通讯协议

    千次阅读 2019-12-03 14:40:24
    ODrive通讯协议 与ODrive进行通讯需要对通讯端点进行一系列操作。理论上,端点上的数据可以是以任何方式序列化的任何类型的数据。数据包采用默认的序列化方式,对于您自定义的数据包,您必须自己去进行反序列化。...

    ODrive通讯协议

    与ODrive进行通讯需要对通讯端点进行一系列操作。理论上,端点上的数据可以是以任何方式序列化的任何类型的数据。数据包采用默认的序列化方式,对于您自定义的数据包,您必须自己去进行反序列化。未来我们可能会提供序列化功能。可以通过从端点0读取JSON来枚举可用的端点,从理论上讲,每个接口都可以不同(实际上并没有这么做)。每个端点都可以被用来发送和接收字节数据,有效字节数据的含义在JSON中进行了定义。
    例如,int32端点的输入和输出是4字节的小字节序表示。 通常,组合的读/写请求的约定是交换,即返回的值是旧值。 自定义的端点可能不符合这种要求。
    该协议有基于数据包的版本和基于流的变体。 适当地使用每个变体。 例如,USB默认运行基于数据包,而UART运行基于字节流。

    基于数据包的格式

    我们将ODrive称为“服务器”,将PC称为“客户端”。 请求是从PC到ODrive的消息,响应是从ODrive到PC的消息。
    每个请求-响应事务对应于一个端点操作。
    请求

    • Bytes 0, 1 数据包的序列号, MSB = 0
      • 当前,服务器不进行处理,也不过滤重复发送的数据包。
    • Bytes 2, 3 端点ID
      • 可以从JSON定义中获取所有端点的ID。 可以通过从端点0读取获得JSON定义。
        如果(且仅当)MSB设置为1时客户端期望对此请求做出响应。
    • Bytes 4, 5 预期请求返回的字节数
      • 应该返回给客户端的字节数。 如果客户端不需要任何响应数据,则可以将该值设置为0。
    • Bytes 6 to N-3 有效负载
      • 有效负载的长度由数据包大小确定。 有效负载的格式取决于端点类型。 端点类型可以从JSON定义中获取。
    • Bytes N-2, N-1
      • 对于端点0:协议版本(当前为1)。 服务器应忽略具有其他值的数据包。
      • 对于所有其他端点:通过JSON定义计算得出的CRC16。 CRC16初始值是协议版本(当前为1)。 服务器将忽略CRC错误的数据包。 有关CRC的详细信息,请参见protocol.hpp源码。

    响应

    • Bytes 0, 1 数据包的序列号, MSB = 1
      • 这是响应请求的序列号。
    • Bytes 2, 3 有效负载
      • 有效负载的长度,等于请求中指示的预期字节数。 服务器返回的字节数不能超过客户端请求的字节数大小。

    基于流的格式

    基于流的格式只是基于数据包格式的封装。

    • Byte 0 同步字节0xAA
    • Byte 1 包字节大小
      • 目前,只能发送/接受0到127个字节的包大小。
    • Byte 2 bytes 0 和 bytes 1的CRC8
      • 详情请参考 protocol.hpp 源码
    • Bytes 3 to N-3 包数据
    • Bytes N-2, N-1 CRC16
      • 详情请参考 protocol.hpp 源码

    如果您有任何问题或疑问,欢迎您加入ODrive社区或QQ群 851421965 进行交流。

    展开全文
  • IIC通讯协议解析

    万次阅读 2021-03-15 16:20:56
    IIC通讯协议解析概述接口 概述 IIC(Inter-Integrated Circuit)其实是IICBus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以...

    概述

    IIC(Inter-Integrated Circuit)其实是IICBus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。I²C的正确读法为“I平方C”(“I-squared-C”),而“I二C”(“I-two-C”)则是另一种错误但被广泛使用的读法。自2006年10月1日起,使用I²C协议已经不需要支付专利费,但制造商仍然需要付费以获取I²C从属设备地址。

    接口

    I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。

    • SCL - 串行时钟线
    • SDA - 串行数据线
    • 在这里插入图片描述

    为了避免总线信号的混乱,要求各设备连接到总线的输出端时必须是漏极开路(OD)输出或集电极开路(OC)输出。设备上的串行数据线SDA接口电路应该是双向的,输出电路用于向总线上发送数据,输入电路用于接收总线上的数据。而串行时钟线也应是双向的,作为控制总线数据传送的主机,一方面要通过SCL输出电路发送时钟信号,另一方面还要检测总线上的SCL电平,以决定什么时候发送下一个时钟脉冲电平;作为接受主机命令的从机,要按总线上的SCL信号发出或接收SDA上的信号,也可以向SCL线发出低电平信号以延长总线时钟信号周期。总线空闲时,因各设备都是开漏输出,上拉电阻Rp使SDA和SCL线都保持高电平。任一设备输出的低电平都将使相应的总线信号线变低,也就是说:各设备的SDA是“与”关系,SCL也是“与”关系。
    因此SDA和SCL 可以被拉低为低电平,但是不能被驱动为高电平,所以每条线上都要使用一个上拉电阻,默认情况下将其保持在高电平。
    在这里插入图片描述
    IIC 总线上数据的传输速率在标准模式下可达 100kbit/s 在快速模式下可达 400kbit/s 在高速模式下可达 3.4Mbit/s。

    通信协议

    SDA 线上的数据必须在时钟的高电平周期保持稳定。数据线的高或低电平状态只有在 SCL 线的时钟信号是低电平时才能改变。
    在这里插入图片描述

    空闲状态

    SDA为高电平,SCL为高电平。

    起始状态

    其中一种情况是在 SCL 线是高电平时 SDA 线从高电平向低电平切换,产生一个下降沿,这个情况表示起始条件。

    结束状态

    当 SCL 是高电平时 SDA 线由低电平向高电平切换,产生一个上升沿,这个情况表示停止条件。
    在这里插入图片描述

    传输数据

    器件地址位

    由于IIC总线上可能挂载着多台设备,所以主设备在传输有效数据之前要先指定从设备的地址,大多数从设备的地址是7位的,还有部分设备支持10位寻址,主设备如果需要向从机发送/接收数据,首先要发送对应从机的地址,然后会匹配总线上挂载的从机的地址。将数据发送至SDA数据线上即可。

    读写位

    紧接着的第 8 位是数据方向位(R/ W) ----'0’表示发送(写),'1’表示请求数据(读)。

    应答信号位

    主设备每发送完8bit数据后等待从设备的ACK。
    即在第9个clock,若从设备发ACK,SDA会被拉低。
    若没有ACK,SDA会被置高,这会引起主设备发生RESTART或STOP流程,当ACK=0时为有效应答位,说明从机已经成功接收到该字节,若为1则说明接受不成功。

    数据地址位

    当找到往哪个设备写数据之后,就开始寻址往这个设备的特定地址写数据,和上述的发送器件地址一样,直接将地址数据发送至SDA线即可。

    数据位

    发送到 SDA 线上的每个字节必须为8位,每次传输可以发送的字节数量不受限制,每个字节后必须跟一个响应位,首先传输的是数据的最高位 (MSB) 。
    在这里插入图片描述

    示例

    设置器件地址为0x78(0111 1000),数据地址为0x40(0100 0000),写入数据0xAA(1010 1010)。

    HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,data_i,1,0x100);
    

    查看HAL_I2C_Mem_Write说明可以得知,目标设备地址在调用接口之前,数据表中设备的7位地址值必须左移;即发送到从设备的数据已经右移了一位,所以0x78(0111 1000)右移一位变成0x3c(011 1100)。

    /**
     * @brief  Write an amount of data in blocking mode to a specific memory address
     * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
     *                the configuration information for the specified I2C.
     * @param  DevAddress Target device address: The device 7 bits address value
     *         in datasheet must be shifted to the left before calling the interface
     * @param  MemAddress Internal memory address
     * @param  MemAddSize Size of internal memory address
     * @param  pData Pointer to data buffer
     * @param  Size Amount of data to be sent
     * @param  Timeout Timeout duration
     * @retval HAL status
      */
    HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
                                        uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
    

    通过示波器抓取的波形如下所示。
    在这里插入图片描述

    • 在空闲状态,SDA和SCL都是处于高电平状态。
    • 在起始状态,SDA先产生一个下降沿,之后SCL也出现一个下降沿,此时数据传输开始。
    • 在传输状态,由于传输速率为100kbit/s,故SCL时钟的切换时间为5us,一个周期为10us;当SCL为1的时候,SDA不会发生改变,故检测SDA信号线的数据,当为低电平则为0,高电平则为1.
    • 在读写状态,当SDA数据为0的时候,为写状态。
    • 在应答状态,当SDA数据为0的时候,为应答状态。
      在这里插入图片描述
      上述为成功传输的例子,若不成功传输,设置器件地址为0x77(0111 0111),数据地址为0x40(0100 0000),写入数据0xAA(1010 1010)。
    HAL_I2C_Mem_Write(&hi2c1 ,0x77,0x40,I2C_MEMADD_SIZE_8BIT,data_i,1,0x100);
    

    由于地址位0x77(0111 0111)右移一位,故发送出去的为0x3B(011 1011),通过示波器抓取的波形如下所示。
    在这里插入图片描述

    • 在应答状态,由于没有连接0x77地址(实际发送为0x3B)的设备,当SDA数据为1的时候,为非应答状态,之后进入复位或者停止。
      在这里插入图片描述

    最后

    以上的代码会在Q群里分享。QQ群:615061293。
    关注微信公众号『记贴』,持续更新文章和学习资料,可加作者的微信交流学习!
    在这里插入图片描述

    展开全文
  • 基于DSP的CANopen通讯协议的实现、电子技术,开发板制作交流
  • UPS通讯协议

    2013-10-22 19:41:29
    为了学习,我们来到这里。本文档是为了学习研究交流只用,版权归EATON所有,反对以此牟利。
  • XMPP即时通讯协议

    千次阅读 2016-09-29 16:19:36
    可扩展消息与存在协议)是目前主流的四种IM(IM:instant messaging,即时消息)协议之一,其他三种分别为:即时信息和空间协议(IMPP)、空间和即时信息协议(PRIM)、针对即时通讯和空间平衡扩充的进程开始协议SIP...
  • IOT设备通讯协议MQTT

    千次阅读 2018-04-08 15:07:51
    笔者的公司最近在做IOT设备相关的业务,基于这个契机寻找学习了一下关于IOT通讯协议相关的内容,最终在技术选型上选择了使用MQTT协议并且结合EMQ上层MQTT中间件实现提供链接服务,那么本轮博文就和大家来一起探讨学习...
  • 即时通讯协议简述

    千次阅读 2010-11-08 14:18:00
    即时通讯协议简述   即时通讯协议简述 <br />一 概述 IM(Instant Messaging)正在被广泛地采用,特别是在公司与它们的客户互动联接方案上。为了解决即时通讯的标准问题,IETF成立了专门的工作小组...
  • 什么是通讯协议

    2011-03-28 14:05:00
    网络里的这个规则就是通讯协议。换句话说,通讯协议是网络社会中信息在网络的计算机之间、网络设备之间及其相互之间"通行"的交通规则。 在不同类型的网络中,应用的网络通讯协议也是不一样的。 虽然这些...
  • RS458和modbus通讯协议

    千次阅读 2019-03-09 22:01:39
    458和modbus 协议分为硬件层协议和...458通讯是在硬件层实现的通讯协议,可以使用仪表进行测量,它需要解决的是0和1传输的问题.例如MCU输出的是TTL电平(0v,5v),假设MCU使用一根先实现数据传输,而458就是把这根线的传...
  • http是指HyperText Transfer Protocol,超文本传输协议,是一种详细规定了浏览器和万维网(WWW = World Wide Web)服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。它可以使浏览器更加高效,使...
  • XMPP详解XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议。在此基础上,XMPP协议已经被用来构建大规模即时通信系统、游戏平台、协作空间...
  • RS-485通讯协议

    千次阅读 2018-05-29 19:03:14
    硬件层协议 通讯协议主要是实现两个设备之间的数据交换功能,通讯协议分硬件层协议和软件层协议。硬件层协议决定数据如何传输问题,比如要在设备1向设备2发送0x63,0x63的二进制数为0110 0011,这8个二进制数从设备...
  • 这是一个串行口RS485通讯协议通讯协议实例,遵循modbus规范亲测好用,欢迎大家下载交流学习;这是一个串行口RS485通讯协议通讯协议实例,遵循modbus规范亲测好用,欢迎大家下载交流学习;这是一个串行口RS485通讯...
  • 这是一个(完整w这是一个(完整word版)modbus通讯协议实例,亲测好用,欢迎大家下载交流
  • 水资源SZY206-2016通讯协议应用心得

    千次阅读 2019-07-19 20:14:16
    水资源SZY206-2016通讯协议是国家制定的水资源监控标准数据通讯协议,用于遥测终端机与网络平台之间数据通讯。我将此协议用于公司产品--遥测终端机上,并取得南京水文局检测报告,对于此协议的了解也算颇为熟悉。 ...
  • (IM)即时通讯协议

    千次阅读 2019-03-25 10:23:27
    文章目录1、即时通讯技术2、XMPP2.1 XMPP 简介2.2 XMPP 基本结构2.3 XMPP 工作原理2.4 XMPP 传输内容2.6 XMPP 的优缺点2.7 XMPP 开发架构3、EaseMob 环信3.1 环信简介3.2 环信开发架构 1、即时通讯技术 即时...
  • Flash Socket的基本通讯协议流程例子

    千次阅读 2010-07-25 16:45:00
    不过后来发现大家比较感兴趣的,不是具体的通讯协议,而且一些关于通讯的各种技术解决问题。呵呵。希望有继续可以和大家继续交流。大家共同前进。而我自己以后也会陆续贴出自己工作上遇到的问题(例如我自己现在...
  • 记XMPP即时通讯协议的认识

    千次阅读 2016-04-18 22:42:48
    XMPP即时通讯协议概述采用XMPP协议的即时通信应用,当数google吧,Google Talk是基于XMPP协议,而且它还允许其它IM自由使用XMPP协议。如此一来,任何IM供应商在遵循XMPP协议的前提下,都可以随时与Google Talk实现免费...
  • 威胜全电子式多功能三相交流电能表 数据通信协议(V1.0/V2.0/V2.1/ V3.0/V4.0/ V4.1) (适用于RS-485/RS-232)
  • 串口(USART)通信-串口通讯协议简介 物理层:规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。其实就是硬件部分。 协议层:协议层主要规定通讯逻辑,统一收发双方的数据打包、解包...
  • WEBQQ通讯协议分析--前言

    千次阅读 2013-11-12 13:04:53
    最近很多朋友在群里要求写一些...腾讯公司并没有把QQ的通讯协议公布,接下来的几篇文章中,将以WEBQQ协议为例,通过抓包分析,得到协议内容,最后通过JAVA设计一个可以登录,可以正常收发信息的QQ机器人,希望感兴趣
  • 前言对于应用层通讯协议而言,目前流行的协议虽然可以很好地支持业务的快速迭代,但是不可否认存在安全性、可拓展性等问题。在消息队列或者微服务框架中,利用自定义协议提高通讯效率很常见的现象。是否你也曾想...
  • 通讯协议是通讯的双方或多方在交流时遵守的规矩,包括谁先发起通讯,先交流什么,后交流什么,一方如何问,另一方如何答等。在这里通迅的双方指的是读写器和卡片。  首先是谁先发起通讯,很显然有两种,读写器先...
  • 电度表威胜规约_威胜通讯协议v4.1 全电子式多功能三相交流电能表

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,588
精华内容 13,835
关键字:

交流通讯协议