嵌入式UART的研究

嵌入式串口通信研究

 

一、       通信过程:

通信方将信息编码 → 传输信息 → 接收方接收信号并解码

串口使用的图

二、       串口通信基本概念:

1)    同步通信和异步通信的区别

同步(USART):发送方和接收方按照统一的时序传输,适合通信时间不固定

USART是全双工。

异步(UART):发送方和接收房按照各自的时序工作,适合通信频率固定

UART是半双工。

2)    电平信号和差分信号

电平信号:有参考电平(GND)

差分信号:没有参考电平,两根电线的电压差,差分信号传输质量好。

3)    并行接口和串行接口

4)    波特率、数据格式

波特率:双方协商好的每秒传输的二进制位,常用9600、115200

波特率的设置:


FCLK:外设输入时钟

OSRVAL:过采样率,决定了一个采样一个数据需要几个时钟

BRGVVAL:波特率发生器值,决定外设时钟分频多少后用于串口外设

数据格式:起始位+数据位+奇偶校验位+停止位

5)    串口通信的基本框图

异步通信UART 


同步通信USART



三、       协议介绍

概述:传输过程中,传输双方需要协商好,这个协商出的方案就是协议

目前使用较多的是UART,下面我们先介绍UART

 

1.     UART传输时序:

UART是一种通用串行数据总线,数据传输过程是在数据线上一位一位的传输的。数据格式如下

2.     USART时钟极性

时钟极性控制位---CPOL

决定了总线空闲时,SCK时钟线的电平状态

CPOL = 0 当数据总线空闲时,SCK时钟线为低电平

CPOL = 1 当数据总线空闲时,SCK时钟线为高电平

时钟相位控制位---CPHA

决定了总线上数据采样位置

CPHA = 0 总线在时钟线第一个跳变沿采样数据。

CPHA = 1 总线在时钟线第二个跳变沿采样数据。

3.     USART传输时序

USART通过一根时钟线进行同步

4.     硬件流控

流控的目的就是可以保证数据发送和接受正好配合(因为如果发送方比接收方速度快,可能会导致数据丢失)。

目前流控使用很少,因为现在硬件水平很高,接受方速度很快。目前串口更多是用来测试调试信息。

5.     软件流控

6.     传输协议

传输协议在应用所处的位置如下图所示:

串口通讯中经常使用的几种文件传输协议:

l  Xmodem

l  1KXmodem

l  Ymodem

l  Zmodem

l  KERMIT

串口通讯中经常使用的总线协议:

Modbus协议

RS232

RS484

这里不详细论述

四、       芯片中的UART外设

1.     UART外设

UART外设串口控制器,串口控制器分为transmitter和receiver两部分,两部分彼此独立,且这两部分都由缓冲区和移位器组成(缓冲区是关键,移位器是硬件控制的)。

1)    FIFO模式

典型的串口设计,每次发送/接收只能处理一字节,这样效率低下,CPU要不断切换上下文,于是比较高级的CPU扩展了发送缓冲器(Transmit FIFO Register,FIFO是一种数据结构,队列:先进先出),FIFO模式始终轻量级的解决方案

2)    DMA模式

直接内存访问。DMA本身是DSP中的一种技术,DMA技术的核心就是在交换数据时不需要CPU参与,模块自己完成。DMA模式适合大量数据迸发式的发送/接收时。

3)    IrDA模式及其用法

IrDA就是红外通信,某些芯片支持红外模式,我盟只需向串口写数据,这些数据就会以红外光的方式向外发射出去,后接收方接收这些红外数据即可解码得到我们的发送信息。

2.     串口通信与中断的关系

一般使用中断来接收数据

五、       配置举例    

    如果使用固件库变成或者原厂提供的工具生成的库例如ST的STM32Cube、NXP的MCUconfigtool等等,你只需知道一些重要的参数及其意义即可,很多都已经写好了,如果为了提高效率使用寄存器直接开发的话,需要对照参考手册(也叫用户手册)去逐一配置了

1)    使用流程概述

2)    STM32的使用举例(HAL库)

串口初始化

void MX_USART2_UART_Init(void)
{

  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}
引脚模式配置
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(uartHandle->Instance==USART2)
  {
  /* USER CODE BEGIN USART2_MspInit 0 */

  /* USER CODE END USART2_MspInit 0 */
    /* USART2 clock enable */
    __HAL_RCC_USART2_CLK_ENABLE();
  
    /**USART2 GPIO Configuration    
    PA2     ------> USART2_TX
    PD6     ------> USART2_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  /* USER CODE BEGIN USART2_MspInit 1 */

  /* USER CODE END USART2_MspInit 1 */
  }
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{


  if(uartHandle->Instance==USART2)
  {
  /* USER CODE BEGIN USART2_MspDeInit 0 */


  /* USER CODE END USART2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART2_CLK_DISABLE();
  
    /**USART2 GPIO Configuration    
    PA2     ------> USART2_TX
    PD6     ------> USART2_RX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2);


    HAL_GPIO_DeInit(GPIOD, GPIO_PIN_6);


  /* USER CODE BEGIN USART2_MspDeInit 1 */


  /* USER CODE END USART2_MspDeInit 1 */
  }
} 

将debug信息通过串口输出

/* Includes ------------------------------------------------------------------*/
#include "usart.h"
#include <stdio.h>
#include "gpio.h"

///* USER CODE BEGIN 0 */
//  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
///* USER CODE END 0 */

	#ifdef __GNUC__  
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf 
     set to 'Yes') calls __io_putchar() */  
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)  
#else  
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)  
#endif /* __GNUC__ */ 
	
	
UART_HandleTypeDef huart2;

/* USART2 init function */

/* USER CODE BEGIN 1 */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{

    huart2.Instance->DR = (uint8_t) ch;  
  
  /* Loop until the end of transmission */  
    while(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TC) == RESET){}  
  
  return ch;  
	
}

六、       注意事项

l  使用USART时需要区分主从模式;

l  使用硬件流控制时需要根据实际芯片介绍连接RTS与CTS

l  使用软件流控制时,若传输的是二进制数据,标志字符也有可能在数据流中出现;

l  引脚配置时注意,所使用的引脚是不是开漏引脚;

l  普通电线和RS232的布线距离不易过长,如果使用长距离通讯建议选择RS485或RS422;

l  过采样率设置的越小,抑制噪声能力越差

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值