通信协议

通信概述

串口通信的概念

通信的概念

通信指的是 CPU 和外部设备或者计算机与计算机之间的数据交互

通信的种类

  • 串行通信

    传输原理:数据按位依次顺序传输(每一位都占据固定的时间长度)

    优点:节约引脚资源(最少一根线)、传输成本低、传输距离远

    缺点:传输速度慢

    应用领域:一般用于工控设备、测量设备、少部分通信设备(USB、COM 口)

  • 并行通信

    传输原理:数据各个位同时进行传输(以字节或字节的倍数进行传输)

    优点:传输速度快

    缺点:占用引脚资源、传输成本高、传输距离近、抗干扰能力弱(串扰)

    应用领域:一般用于大量数据传输、并且传输距离较近(计算机总线)

串行通信的分类

  • 按照数据的传送方向,可以分为三种

    • 单工: 数据只允许在一个方向上传输(收音机)
    • 半双工: 数据允许在两个方向上传输,但在同一时刻只能在一个方向上传输(对讲机)
    • 全双工: 数据允许同时在两个方向上传输,可以理解为两个单工通信的结合(移动电话)

    串行通信方式【海量 it 资源 dbbp.net】

  • 按照数据的同步方式,可以分为两种

    • 同步通信: 带时钟同步信号,如 IIC 接口或 SPI 接口都属于同步通信,要求通信双方使用同一个时钟,相当于发送数据的同时接收数据,同步通信属于连续串行传输数据,一次只传输一帧数据,相比于异步通信而言,传输效率更高,缺点是时钟必须一致
    • 异步通信: 不带时钟同步信号,如 UART 接口属于异步通信,要求通信双方具有发送端和接收端,由于不要求时钟同步,所以在通信的时候,通信双方必须约定好通信格式(字符串格式)以及通信速率,异步通信以字符为单位进行传输,在传输一个字符的时候会添加起始位和停止位,通过起始位和停止位来达到同步的功能

    串行通信标准特点【海量 it 资源 dbbp.net】

串行接口的意义

串口是把数据按位顺序传输,但是计算机在通信的时候采用的时并行通信的方式,在硬件设备与计算机进行通信的时候涉及到串转并、并转串,实现方式有两种:软件实现/硬件实现

如果采用软件实现会增加 CPU 的负担,一般都是采用硬件实现(增加串口)

一般串口分为 9 针串口(DB-9)以及 25 针串口(DB-25),现在一般都是采用 DB-9 串口通信,分别分为公头和母头。

image

image

可以看到,一般 9 针串口在通信的时候,只会用到 3 个引脚(TXD、RXD、GND),其他的引脚一般用于握手

硬件设备和计算机在通信的时候,需要用到电气转换芯片(如 MAX232),因为硬件平台一般采用 TTL 电平信号(采用正逻辑电平,+5V 等价于逻辑 1,0V 等价于逻辑 0),但是计算机采用 RS232 电平信号(采用负逻辑电平,-15V ~ -3V 表示逻辑 1,+3V-+15V 表示逻辑 0)。

image

开发平台和计算机的接口说明

一般现在的计算机(笔记本电脑)和硬件设备(STM32)都不集成 DB-9 或者 DB-25 接口,提供了另外的一种方案来实现数据交互,就是利用 USB 口和开发板的串口(4 针的拓展串口)进行通信(利用 USB 转串口),就必须在 STM32 开发板集成 USB 转串口芯片(CH340G)。

image

串口通信的参数

USART 或者 UART 都是全双工异步通信,由于不需要时钟同步,所以就必须要求通信双方要约定字符格式和通信速率

字符格式

字符格式一般都是采用字符帧的形式进行传输,字符帧由起始位、数据位、校验位、停止位组成。

  1. 起始位:指的是一帧数据的开始 规定为 1bit 的低电平
  2. 数据位:指的是有效的信息,可以为 7bit(标准 ASCII 码)或者 8bit(拓展 ASCII 码)
  3. 校验位:指的是对于数据位的简单校验,可以确保数据正常发送,也可以避免噪声的影响,校验分为奇校验、偶校验,校验位也只占 1bit。一般不使用校验位。
  4. 停止位:指的是一帧数据传输完成 停止位一般选择 1bit,规定为高电平

通信速率

通信速率指的是单位时间内传输的有效的二进制数的个数,也被称为波特率,单位为 bps。常用的波特率有 9600bps1 、115200bps。 可以根据实际需求进行修改。

串口通信的流程

对于 STM32F407 芯片而言,一共提供了 6 个串口,包括 4 个 USART2 个 UART,USART 指的是通用同步异步收发器,而 UART 指的是通用异步收发器,相比于 USART 而言,UART 裁剪掉同步功能,一般平时在使用串口的时候都是使用异步通信

USART

通用同步异步收发器 (USART) 能够灵活地与外部设备进行全双工数据交换,满足外部设备对
工业标准 NRZ 2异步串行数据格式的要求。USART 通过小数波特率发生器提供了多种波特率。
它支持同步单向通信和半双工单线通信;还支持 LIN(局域互连网络)、智能卡协议与 IrDA
(红外线数据协会)SIR ENDEC 规范,以及调制解调器操作 (CTS/RTS)。而且,它还支持
多处理器通信。
通过配置多个缓冲区使用 DMA 可实现高速数据通信。

  • 通过 USART 初始化结构体3设置串口通信的字符格式以及通信速率
  • USART 中断4:编写中断服务函数,一般需要提前设置好串口中断的触发条件,一般触发条件都会设置为接收到数据就发生中断。

实例5


  1. 9600bps

    举个例子:一般采用的波特率是 9600bps,字符格式选择 8bit 数据位、无校验、1bit 停止位,然后再加上 1bit 的起始位,所以一帧字符占 10bit,所以单位时间可以传输 960 帧。

    image

  2. NRZ

    不归零码(NON-Return-Zero),指的是传输 1bit 数据后电平不需要归零

    RZ:归零码,指的是每传输 1bit 数据之后电平必须归零

    image

  3. USART 初始化结构体

    image

    typedef struct
    {
      uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.
                                               The baud rate is computed using the following formula:
                                                - IntegerDivider = ((PCLKx) / (8 * (OVR8+1) * (USART_InitStruct->USART_BaudRate)))
                                                - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 8 * (OVR8+1)) + 0.5 
                                               Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */
    
      uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
                                               This parameter can be a value of @ref USART_Word_Length */
    
      uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.
                                               This parameter can be a value of @ref USART_Stop_Bits */
    
      uint16_t USART_Parity;              /*!< Specifies the parity mode.
                                               This parameter can be a value of @ref USART_Parity
                                               @note When parity is enabled, the computed parity is inserted
                                                     at the MSB position of the transmitted data (9th bit when
                                                     the word length is set to 9 data bits; 8th bit when the
                                                     word length is set to 8 data bits). */
         
      uint16_t USART_Mode;                /*!< Specifies whether the Receive or Transmit mode is enabled or disabled.
                                               This parameter can be a value of @ref USART_Mode */
    
      uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
                                               or disabled.
                                               This parameter can be a value of @ref USART_Hardware_Flow_Control */
    } USART_InitTypeDef;
    
    (1) USART_BaudRate指的是波特率   常用9600bps  115200bps
    (2) USART_WordLength指的是数据位   常用8bit   低位先出
    #define USART_WordLength_8b                  ((uint16_t)0x0000)
    #define USART_WordLength_9b                  ((uint16_t)0x1000)
    (3)USART_StopBits		指的是停止位	常用1bit
    #define USART_StopBits_1                     ((uint16_t)0x0000)
    #define USART_StopBits_0_5                   ((uint16_t)0x1000)
    #define USART_StopBits_2                     ((uint16_t)0x2000)
    #define USART_StopBits_1_5                   ((uint16_t)0x3000)
    (4)USART_Parity		指的是校验位	常用无校验
    #define USART_Parity_No                      ((uint16_t)0x0000)
    #define USART_Parity_Even                    ((uint16_t)0x0400)
    #define USART_Parity_Odd                     ((uint16_t)0x0600)
    (5)USART_Mode		指的是串口模式 常用收发模式  USART_Mode_Rx | USART_Mode_Tx
    #define USART_Mode_Rx                        ((uint16_t)0x0004)
    #define USART_Mode_Tx                        ((uint16_t)0x0008)
    (6)USART_HardwareFlowControl	指的是硬件流控制   常用无
    #define USART_HardwareFlowControl_None       ((uint16_t)0x0000)
    #define USART_HardwareFlowControl_RTS        ((uint16_t)0x0100)
    #define USART_HardwareFlowControl_CTS        ((uint16_t)0x0200)
    #define USART_HardwareFlowControl_RTS_CTS    ((uint16_t)0x0300)
    
  4. USART 中断

    image

    ST 公司提供了一个函数可以设置串口中断源,调用 USART_ITConfig()函数

    image

    一般在中断服务函数中需要检测中断是否发生(检测中断状态)以及清除中断状态即可。

    /* Interrupts and flags management functions **********************************/
    void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
    FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
    void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
    ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
    void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
    
    

    发送数据

    /**
      * @brief  Transmits single data through the USARTx peripheral.
      * @param  USARTx: where x can be 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or 
      *         UART peripheral.
      * @param  Data: the data to transmit.
      * @retval None
      */
    void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
    

    接收数据(需要在中断服务函数中调用该函数来接收数据)

    /**
      * @brief  Returns the most recent received data by the USARTx peripheral.
      * @param  USARTx: where x can be 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or 
      *         UART peripheral.
      * @retval The received data.
      */
    uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
    
  5. 实例

    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    
    
    //串口输出重定向,keil-target中勾选use microlib
    int fputc(int ch, FILE *f) 
    {
    	USART_SendData(USART1, ch);
    	while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET );
    	return ch;
    }
    
    int main(void)
    {
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    	GPIO_InitStruct.GPIO_PuPd 	= GPIO_PuPd_NOPULL;
    	GPIO_InitStruct.GPIO_OType 	= GPIO_OType_PP;
    	GPIO_InitStruct.GPIO_Speed	= GPIO_Speed_100MHz;
    	GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_9|GPIO_Pin_10;
    	GPIO_Init(GPIOA,&GPIO_InitStruct);
    	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_USART1);
    	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_USART1);
    
    
    	USART_InitTypeDef USART_InitStruct;
    	USART_InitStruct.USART_BaudRate = 9600;
    	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    	USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    	USART_InitStruct.USART_Parity = USART_Parity_No;
    	USART_InitStruct.USART_StopBits = USART_StopBits_1;
    	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    	USART_Init(USART1,&USART_InitStruct);
    
    	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    
    
    	NVIC_InitTypeDef NVIC_InitStruct;
    	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
    	NVIC_Init(&NVIC_InitStruct);
    
    	USART_Cmd(USART1, ENABLE);
    
    	while(1)
    	{
    
    	}
    
    }
    
    void USART1_IRQHandler(void)
    {
    	uint16_t recv_data = 0;
    	if( USART_GetITStatus(USART1,USART_IT_RXNE) != RESET )
    	{
    		USART_ClearITPendingBit(USART1,USART_IT_RXNE); 
    
    		recv_data = USART_ReceiveData(USART1);
    
    		USART_SendData(USART1,recv_data);
    		while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET );
    	}
    }
    
    /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
    
    

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...