当前位置:   article > 正文

UART串行通信简介_uart串口

uart串口

一、认识UART

1.UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一种双向、串行、异步的通信总线,仅用一根数据接收线和一根数据发送线就能实现全双工通信。典型的串口通信使用3根线完成,分别是:发送线(TX)、接收线(RX)和地线(GND),通信时必须将双方的TX和RX交叉连接并且GND相连(共用同一个地)才可正常通信,如下图所示:

二、串行、并行通信

这里简单介绍一下UART使用的串行通信方式:两个MCU互相收发数据常见的通信方式主要有串行通信和并行通信两种方式!

假设我们要发送198给另一台MCU,首先需要将198转换成机器能够识别的二进制也就是11000110

1.此时使用串行通信方式,我们只需要使用一根线交叉连接两个MCU的Tx-Rx,再使用一根线进行共地,我们就可以依次将八位数据发送给另一台MCU。

2.若使用并行通信,则需要八根线分别发送八位数据,并且为了保证数据的同步性,还需要另外接一根时钟信号线!虽然发送速率较快,但线路成本较高且抗干扰能力较弱。

三、UART通信过程

1.三要素:波特率、数据长度、开始/停止位

要想使用UART收发数据,必须设置好这三个基础设置。

2.数据发送过程

设置好三要素后,我们就可以进行简单的数据发送。下面简单介绍一下发送过程中三要素的作用:

(1)波特率:不同的波特率代表着我们发送数据的速度不同,数据的收发需要波特率的同步,也就是两端的波特率要设置成相同数值。(通常使用较多的设备波特率为9600、115200等)

这里我们假设波特率为9600,也就是说设备每秒发送9600位,一个数据位就需要104微秒;

(2)数据长度:数据帧包含所传输的实际数据。如果使用奇偶校验位,数据帧长度可以是5 位到 8 位。如果不使用奇偶校验位,数据帧长度可以是9 位。在大多数情况下,数据以最低有效位优先方式发送

(3)开始/停止位:开始位以下降沿为标志,也就是从高电平转变到低电平;当不传输数据时, UART 数据传输线通常保持高电压电平。若要开始数据传输,发送UART 会将传输线从高电平拉到低电平并保持1 个时钟周期。当接收 UART 检测到高到低电压跃迁时,便开始以波特率对应的频率读取数据帧中的位。停止位以上升沿为标志,也就是从低电平转变到高电平;为了表示数据包结束,发送 UART 将数据传输线从低电压驱动到高电压并保持1 到 2 位时间。

上图的52us是指,通常在收发数据时,我们会在检测到开始位后等待52us,避免数据的不稳定性。

3.额外说一下奇偶校验位:奇偶性描述数字是偶数还是奇数。通过奇偶校验位,接收 UART判断传输期间是否有数据发生改变。电磁辐射、不一致的波特率或长距离数据传输都可能改变数据位。
校验位可以配置成 1 位偶校验或 1 位奇校验或无校验位。
接收UART 读取数据帧后,将统计数值为 1 的位,检查总数是偶数还是奇数。如果奇偶校验位为0 (偶数奇偶校验),则数据帧中的1或逻辑高位总计应为偶数。如果奇偶校验位为 1 (奇数奇偶校验),则数据帧中的1 或逻辑高位总计应为奇数。
当奇偶校验位与数据匹配时,UART 认为传输未出错。但是,如果奇偶校验位为0 ,而总和为奇数,或者奇偶校验位为 1 ,而总和为偶数,则UART 认为数据帧中的位已改变。

四、UART使用(以STM32为例)

1.接线:

        任何 UART 双向通信至少需要 3 个引脚,数据发送引脚 TXD,数据接收引脚 RXD,数 据参考地 GND。这里特别需要注意的是连接方法,设备 A 和设备 B 信号需要交叉连接。如 果电平不同,需要电平转换芯片。

 串口1的初始化:引脚为PA9\PA10;

  1. void Init_Uart1(uint32_t baud) //baud为波特率
  2. {
  3. GPIO_InitTypeDef GPIO_InitStructure;
  4. USART_InitTypeDef USART_InitStructure;
  5. #if EN_USART1_RX //如果使能了接收
  6. NVIC_InitTypeDef NVIC_InitStructure;
  7. #endif
  8. /* 串口 1 TX = PA9 RX = PA10 */
  9. /*1 步: 配置 GPIO */
  10. /* 打开 GPIO 时钟 */
  11. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  12. /* 打开 UART 时钟 */
  13. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  14. /* 配置 USART Tx 为复用功能 */ //USART1_TX GPIOA.9
  15. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  16. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  17. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  18. GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.9
  19. /* 配置 USART Rx 为复用功能 */ //USART1_RX GPIOA.10 初始化
  20. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10
  21. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  22. GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.10
  23. /*2 步: 配置串口硬件参数 */
  24. USART_InitStructure.USART_BaudRate = baud; /* 波特率 */
  25. USART_InitStructure.USART_WordLength = USART_WordLength_8b; /* 字长为 8 位数据格式 */
  26. USART_InitStructure.USART_StopBits = USART_StopBits_1; /* 一个停止位 */
  27. USART_InitStructure.USART_Parity = USART_Parity_No; /* 无奇偶校验位 */
  28. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; /* 无硬件数据流控制 */
  29. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; /* 收发模式 */
  30. USART_Init(USART1, &USART_InitStructure); /* 初始化串口 1 */
  31. #if EN_USART1_RX //如果使能了接收
  32. /*3 步: Usart1 NVIC 配置 */
  33. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  34. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级 3
  35. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 3
  36. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
  37. NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化 VIC 寄存器
  38. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* 开启串口接受中断 */
  39. USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); /* 开启串口空闲中断 */
  40. #endif
  41. /*4 步: 使能串口 1 */
  42. USART_Cmd(USART1, ENABLE); /* 使能串口 */
  43. }

中断服务函数:

  1. void USART1_IRQHandler(void) //串口 1 中断服务程序
  2. {
  3. uint8_t Res=Res;
  4. if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到一个字节数据)
  5. {
  6. USART_RX_BUF[RxCounter++]=USART1->DR;//把接收到的字节保存
  7. }
  8. if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //接收中断(接收到 1 帧数据)
  9. {
  10. Res=USART1->SR;//读 SR 寄存器
  11. Res=USART1->DR;//读 DR 寄存器(先读 SR,再读 DR,就是为了清除 IDLE 中断)
  12. ReceiveState=1;//标记接收状态置位
  13. }
  14. }

 状态清零函数:

  1. void Uart0_STA_Clr(void)
  2. {
  3. RxCounter = 0;//串口 BUF 计数清零
  4. ReceiveState = 0;//接收状态清零
  5. }

为使用printf()打印的重定向函数:(记得包含stdio.h头文件)

  1. int fputc(int ch, FILE *f)
  2. {
  3. while((USART1->SR&0X40)==0){};//;//循环发送,直到发送完毕
  4. USART1->DR = (u8) ch;
  5. return ch;
  6. }

 数据发送函数:(16进制)

  1. void USART1_Send_Data(uint8_t *buf,uint8_t len)
  2. {
  3. uint8_t t;
  4. for(t=0;t<len;t++) //循环发送数据
  5. {
  6. while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  7. USART_SendData(USART1,buf[t]);
  8. }
  9. while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  10. }

下图为常用串口助手的设置界面⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇


   

有需要源代码的朋友可以私,自己学习笔记记录,有错误欢迎大家指正!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/467858
推荐阅读
相关标签
  

闽ICP备14008679号