1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
- 串行通讯和并行通讯 [tr]特性串行通讯并行通讯[/tr]
[tr]通讯方式说明[/tr]
在同步通讯中,收发设备双方会使用一根信号线表示时钟信号,在时钟信号的驱动下双方进行协调,同步数据。通讯中通常双方会统一规定在时钟信号的上升沿或下降沿对数据线进行采样。 在异步通讯中不使用时钟信号进行数据同步,它们直接在数据信号中穿插一些同步用的信号位,或者把主体数据进行打包,以数据帧的格式传输数据。某些通讯中还需要双方约定数据的传输速率,以便更好地同步。 在同步通讯中,数据信号所传输的内容绝大部分就是有效数据,而异步通讯中会包含有帧的各种标识符,所以同步通讯的效率更高,但是同步通讯双方的时钟允许误差较小,而异步通讯双方的时钟允许误差较大。 - 通讯速率 Bitrate—比特率:每秒钟传输的二进制位数,单位为比特每秒(bit/s) 。(I2C、SPI)(同步) Baudrate—波特率:表示每秒钟传输的码元个数。(USART)(异步) 一般一个码元用一个二进制表示,如: 但是当码元有多个时,需要多位的二进制表示,如: 串口通讯协议简介 协议(计算机学科概念) 对于通讯协议,我们以分层的方式来理解,分为物理层和协议层。 物理层 规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。(硬件) RS-232标准
电平标准不同 TTL电平一般是芯片里面出来的电平 [tr]通讯标准电平标准(发送端)[/tr]
协议层 主要规定通讯逻辑,统一收发双方的数据打包、解包标准。(软件) 串口数据包的基本组成
STM32—USART / UART 简介 STM32有5个串口,其中有三个通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter),简称USART(USART1、USART2、USART3),两个通用异步收发器(Universal Asynchronous Receiver and Transmitter),简称UART(UART4、UART5)。USART1在APB2上,计算波特率的时候,fck 为72MHZ,其他的在APB1上,计算波特率的时候,fck 为36MHZ。 USART 功能框图 功能引脚 TX: 发送数据输出引脚。 RX: 接收数据输入引脚。 SW_RX: 数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚。 nRTS: 请求以发送(Request To Send),n 表示低电平有效。如果使能RTS 流控制,当USART 接收器准备好接收新数据时就会将nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。 nCTS: 清除以发送(Clear To Send),n 表示低电平有效。如果使能CTS 流控制,发送器在发送下一帧数据之前会检测nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。 SCLK: 发送器时钟输出引脚。这个引脚仅适用于同步模式。 USART 引脚在STM32F103ZET6 芯片具体分布见下表: [tr]引脚APB2 总线APB1 总线APB1 总线APB1 总线APB1 总线[/tr]
数据寄存器 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 数据。 TDR 和RDR 都是介于系统总线和移位寄存器之间。串行通信是一个位一个位传输的,发送时把TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接收时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到RDR。 控制寄存器 和 状态寄存器 控制寄存器有三个,为USART_CR1、USART_CR2、USART_CR3,对于每一位的功能可查看STM32F10x-参考手册第25章第6节。 为了便于理解,从发送和接受的过程对控制寄存器和状态寄存器的相关位功能进行学习 发送
当使用校验位时,串口传输的长度将是 8 位的数据帧加上 1 位的校验位总共 9 位,此时USART_CR1 寄存器的M位需要设置为 1,即 9 位数据位。 相关寄存器位: 控制寄存器1(USART_CR1)PCE位:检验控制使能,软件对它置’1’或清’0’。一旦设置了该位,当前字节传输完成后,校验控制才生效。0:禁止校验控制;1:使能校验控制。 控制寄存器1(USART_CR1)PS位:校验选择,当校验控制使能后,该位用来选择是采用偶校验还是奇校验。软件对它置’1’或清’0’。当前字节传输完成后,该选择生效。0:偶校验;1:奇校验。 控制寄存器1(USART_CR1)PEIE位:PE中断使能,该位由软件设置或清除。0:禁止产生中断;1:当USART_SR中的PE为’1’时,产生USART中断。 使能了奇偶校验控制后,每个字符帧的格式将变成:起始位+数据帧+校验位+停止位。 中断控制 USART 有多个中断请求事件,具体见下表: [tr]中断事件事件标志使能控制位[/tr]
USART 初始化结构体详解 USART 初始化结构体 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;
该结构体内容也只有在同步模式才需要设置。 typedef struct { uint16_t USART_Clock; // 时钟使能控制 uint16_t USART_CPOL; // 时钟极性 uint16_t USART_CPHA; // 时钟相位 uint16_t USART_LastBit; // 最尾位时钟脉冲 } USART_ClockInitTypeDef;
初始化串口需要用到的GPIO /* USART GPIO 引脚宏定义 */ #define DEBUG_USART_GPIO_CLK RCC_APB2Periph_GPIOA #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10 /*-------------------------- USART 相关参数配置 --------------------------*/ void USART_Config(void){ GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; /*** 初始化串口需要用到的GPIO ***/ /* 打开串口GPIO的时钟 */ DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); /* 将USART Tx的GPIO配置为推挽复用模式 */ GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure); /* 将USART Rx的GPIO配置为浮空输入模式 */ GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); } 配置 USART 的工作参数 /*-------------------------- USART 相关参数配置 --------------------------*/ void USART_Config(void){ /*** 配置 USART 的工作参数 ***/ /* 打开串口外设的时钟 */ DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE; // 配置波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 配置一帧数据字长 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 配置停止位 USART_InitStructure.USART_Parity = USART_Parity_No; // 配置校验位 USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 配置工作模式,收发一起 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 配置硬件流控制 USART_Init(DEBUG_USARTx, &USART_InitStructure); // 完成串口的初始化配置 } 中断配置(接收中断、中断优先级) /*------------------------ 配置 USARTx 中断优先级 -----------------------*/ static void NVIC_Configuration(void){ NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 配置中断优先级分组 NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ; // 配置中断源 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 配置抢占优先级(主优先级) NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 配置子优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断 NVIC_Init(&NVIC_InitStructure); } /*-------------------------- USART 相关参数配置 --------------------------*/ void USART_Config(void){ /*** 中断配置 ***/ NVIC_Configuration(); // 串口中断优先级配置 USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE); // 使能串口接收中断 } 使能串口 /*-------------------------- USART 相关参数配置 --------------------------*/ void USART_Config(void){ /*** 使能串口 ***/ USART_Cmd(DEBUG_USARTx, ENABLE); } |
|||||
|
|||||
发送函数 /*-------------- 发送数据,由上位机(串口调试助手)接受并显示 -------------*/ /*-------------------- 注意:数据以 字符 形式传输 -----------------------*/ /* 发送一个字节的数据 */ void Usart_SendByte(USART_TypeDef* USARTx, uint8_t data){ USART_SendData(USARTx, data); // 发送一个字节数据到USART while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET ); // 等待发送数据寄存器为空 } /* 发送两个字节的数据 */ void Usart_SendHalfWord(USART_TypeDef* USARTx, uint16_t data){ uint8_t temp_h, temp_l; temp_h = (data & 0xff00) >> 8; // 将 data 的高八位赋值给 temp_h temp_l = data & 0xff; // 将 data 的低八位赋值给 temp_l USART_SendData(USARTx, temp_h); // 发送 data 的高八位 到USART while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET ); // 等待发送数据寄存器为空 USART_SendData(USARTx, temp_l); // 发送 data 的低八位 到USART while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET ); // 等待发送数据寄存器为空 } /* 发送八位数据的数组 */ void Usart_SendArray(USART_TypeDef* USARTx, uint8_t *arr, uint8_t num){ uint8_t i; /* 循环发送 */ for(i=0 ; i /* 注意: * 此处调用的是 void Usart_SendByte(USART_TypeDef* USARTx, uint8_t data) 函数 * 若调用 void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) 函数 * 还需 while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET ) 保证一个8位的数据传完后,再传下一个数据 */ Usart_SendByte(USARTx, arr); } while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET ); // 等待发送完毕 } /* 发送字符串 */ void Usart_SendString(USART_TypeDef* USARTx, uint8_t *str){ /* 循环发送 */ do{ Usart_SendByte(USARTx, *(str++)); }while(*str != ' |