通信概述
串口通信的概念
通信的概念
通信指的是 CPU 和外部设备或者计算机与计算机之间的数据交互
通信的种类
-
串行通信
传输原理:数据按位依次顺序传输(每一位都占据固定的时间长度)
优点:节约引脚资源(最少一根线)、传输成本低、传输距离远
缺点:传输速度慢
应用领域:一般用于工控设备、测量设备、少部分通信设备(USB、COM 口)
-
并行通信
传输原理:数据各个位同时进行传输(以字节或字节的倍数进行传输)
优点:传输速度快
缺点:占用引脚资源、传输成本高、传输距离近、抗干扰能力弱(串扰)
应用领域:一般用于大量数据传输、并且传输距离较近(计算机总线)
串行通信的分类
-
按照数据的传送方向,可以分为三种
- 单工: 数据只允许在一个方向上传输(收音机)
- 半双工: 数据允许在两个方向上传输,但在同一时刻只能在一个方向上传输(对讲机)
- 全双工: 数据允许同时在两个方向上传输,可以理解为两个单工通信的结合(移动电话)
-
按照数据的同步方式,可以分为两种
- 同步通信: 带时钟同步信号,如 IIC 接口或 SPI 接口都属于同步通信,要求通信双方使用同一个时钟,相当于发送数据的同时接收数据,同步通信属于连续串行传输数据,一次只传输一帧数据,相比于异步通信而言,传输效率更高,缺点是时钟必须一致
- 异步通信: 不带时钟同步信号,如 UART 接口属于异步通信,要求通信双方具有发送端和接收端,由于不要求时钟同步,所以在通信的时候,通信双方必须约定好通信格式(字符串格式)以及通信速率,异步通信以字符为单位进行传输,在传输一个字符的时候会添加起始位和停止位,通过起始位和停止位来达到同步的功能
串行接口的意义
串口是把数据按位顺序传输,但是计算机在通信的时候采用的时并行通信的方式,在硬件设备与计算机进行通信的时候涉及到串转并、并转串,实现方式有两种:软件实现/硬件实现
如果采用软件实现会增加 CPU 的负担,一般都是采用硬件实现(增加串口)
一般串口分为 9 针串口(DB-9)以及 25 针串口(DB-25),现在一般都是采用 DB-9 串口通信,分别分为公头和母头。
可以看到,一般 9 针串口在通信的时候,只会用到 3 个引脚(TXD、RXD、GND),其他的引脚一般用于握手。
硬件设备和计算机在通信的时候,需要用到电气转换芯片(如 MAX232),因为硬件平台一般采用 TTL 电平信号(采用正逻辑电平,+5V 等价于逻辑 1,0V 等价于逻辑 0),但是计算机采用 RS232 电平信号(采用负逻辑电平,-15V ~ -3V 表示逻辑 1,+3V-+15V 表示逻辑 0)。
开发平台和计算机的接口说明
一般现在的计算机(笔记本电脑)和硬件设备(STM32)都不集成 DB-9 或者 DB-25 接口,提供了另外的一种方案来实现数据交互,就是利用 USB 口和开发板的串口(4 针的拓展串口)进行通信(利用 USB 转串口),就必须在 STM32 开发板集成 USB 转串口芯片(CH340G)。
串口通信的参数
USART 或者 UART 都是全双工异步通信,由于不需要时钟同步,所以就必须要求通信双方要约定字符格式和通信速率。
字符格式
字符格式一般都是采用字符帧的形式进行传输,字符帧由起始位、数据位、校验位、停止位组成。
- 起始位:指的是一帧数据的开始 规定为 1bit 的低电平
- 数据位:指的是有效的信息,可以为 7bit(标准 ASCII 码)或者 8bit(拓展 ASCII 码)
- 校验位:指的是对于数据位的简单校验,可以确保数据正常发送,也可以避免噪声的影响,校验分为奇校验、偶校验,校验位也只占 1bit。一般不使用校验位。
- 停止位:指的是一帧数据传输完成 停止位一般选择 1bit,规定为高电平
通信速率
通信速率指的是单位时间内传输的有效的二进制数的个数,也被称为波特率,单位为 bps。常用的波特率有 9600bps1 、115200bps。 可以根据实际需求进行修改。
串口通信的流程
对于 STM32F407 芯片而言,一共提供了 6 个串口,包括 4 个 USART 和 2 个 UART,USART 指的是通用同步异步收发器,而 UART 指的是通用异步收发器,相比于 USART 而言,UART 裁剪掉同步功能,一般平时在使用串口的时候都是使用异步通信。
USART
通用同步异步收发器 (USART) 能够灵活地与外部设备进行全双工数据交换,满足外部设备对
工业标准 NRZ 2异步串行数据格式的要求。USART 通过小数波特率发生器提供了多种波特率。
它支持同步单向通信和半双工单线通信;还支持 LIN(局域互连网络)、智能卡协议与 IrDA
(红外线数据协会)SIR ENDEC 规范,以及调制解调器操作 (CTS/RTS)。而且,它还支持
多处理器通信。
通过配置多个缓冲区使用 DMA 可实现高速数据通信。
实例5
9600bps
举个例子:一般采用的波特率是 9600bps,字符格式选择 8bit 数据位、无校验、1bit 停止位,然后再加上 1bit 的起始位,所以一帧字符占 10bit,所以单位时间可以传输 960 帧。
↩
NRZ
不归零码(NON-Return-Zero),指的是传输 1bit 数据后电平不需要归零
RZ:归零码,指的是每传输 1bit 数据之后电平必须归零
↩
USART 初始化结构体
↩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)
USART 中断
ST 公司提供了一个函数可以设置串口中断源,调用 USART_ITConfig()函数
一般在中断服务函数中需要检测中断是否发生(检测中断状态)以及清除中断状态即可。
/* 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)
实例
↩/* 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****/
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于