1.串口的定义最核心的定义数据在一根传输线上按位bit为单位一个接一个地顺序传送的通信方式。注意1.串口规定了每一帧的数据格式数据格式指的是每一个数据帧的内部结构。2.数据协议是不同的概念数据协议指的是通信协议比如modbus通信。2.RS-232属于物理层面的重定义1.属于串口通信只是定义了更多的引脚以及电平大小。2.电平的波动为15V到-15V。3.RS-232 的标准规定只要电压在3V ~ 15V之间就代表逻辑“0”在-3V ~ -15V之间就代表逻辑“1”中间 -3V 到 3V 是一个无效区间死区。3.USART通用同步/异步收发器1.属于串口通信使用TTL电平2.电平的波动为5V到0V。4.数据格式与数据协议并不相同1.波特率异步通讯中由于没有时钟信号所以两个通讯设备之间需要约定好波特率即每个数据位的时间长度以便对信号 进行解码 比如115200波特率 就是每秒能表示115200个数据位单个数据位时间长度计算 例如115200 1/115200 0.000008680555556 s2.起始位一帧串口通讯的开始在没有信息传输时电平信号保持为高起始信号由一个逻辑0的 数据位表示。2.数据位在数据包的起始位之后紧接着的就是要传输的主体数据内容也称为有效数据有效数据的长度 常被约定为8或9位长。 一帧数据刚好传输一个8位2进制等一个8位大小的变uint8_t3.校验位校验数据有奇校验(odd)、偶校验 (even)、0 校验 (space)、1 校验 (mark) 以及无校验(noparity)。4.停止位一帧串口通讯的结束当一帧数据传送完成时停止信号由一个逻辑1的数据位表示。5.串口功能框图总框图在我看来完全可以从配置结构体中倒推框图帮助大家记忆。1.第一部分与GPIO引脚相关TX发送数据输出引脚。RX接收数据输入引脚。SW_RX数据接收引脚只用于单线和智能卡模式属于内部引脚没有具体外部引脚。nRTS请求以发送(Request To Send)n 表示低电平有效。如果使能RTS流控制当USART接 收器准备好接收新数据时就会将nRTS变成低电平当接收寄存器已满时nRTS将被设置为高 电平。该引脚只适用于硬件流控制。nCTS清除以发送(ClearToSend)n表示低电平有效。如果使能CTS流控制发送器在发送下 一帧数据之前会检测nCTS引脚如果为低电平表示可以发送数据如果为高电平则在发送完 当前数据帧之后停止发送。该引脚只适用于硬件流控制。SCLK发送器时钟输出引脚。这个引脚仅适用于同步模式。UART只是异步传输功能所以没有SCLK、nCTS和nRTS功能引脚。2.第二部分发送与接收逻辑可以搭配发送与接收库函数搭配看更加便于记忆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。3.第三部分发送与接收的控制发送器 当USART_CR1寄存器的发送使能位TE置1时启动数据发送发送移位寄存器的数据会在TX 引脚输出如果是同步模式SCLK也输出时钟信号。接收器如果将USART_CR1 寄存器的 RE 位置 1使能 USART 接收使得接收器在RX线开始搜索 起始位。在确定到起始位后就根据RX线电平状态把数据存放在接收移位寄存器内。接收完成 后就把接收移位寄存器数据移到RDR内并把USART_SR寄存器的RXNE位置1同时如果 USART_CR2 寄存器的RXNEIE置1的话可以产生中断。4.第四部分波特率发生单元1.fPLCK 为USART时钟2.OVER8为USART_CR1寄存器的OVER8位对应的值3. USARTDIV 是一个存放在波特率寄存器(USART_BRR)的一个无符号定点数,其中DIV_Mantissa[11:0]位定 义USARTDIV的整数部分DIV_Fraction[3:0]位定义USARTDIV的小数部分DIV_Fraction[3]位 只有在OVER8位为0时有效否则必须清零4.实例讲解即fPLCK84MHz。 当我们使用16倍过采样时即OVER80为得到115200bps的波特率此时解得USARTDIV45.57可算得DIV_Fraction0x90.57*249.12 取整在 BRR寄存器中表示 小数位的有4位DIV_Mantissa0x2D即应该设置USART_BRR的值为0x2D9。6.代码实现我并没有记那些配置从每个结构体定义的注释中都可以找到参数1.思路总结1.GPIOS初始化 (因为复用串口对引脚配置有要求所以写的详细)启动时钟-配置推挽输出-上拉模式-速度-引脚复用-设置复用的功能2.USART初始化启动时钟-配置结构体-是否使能串口中断-开启txrx功能3.中断配置设置中断控制器-配置中断结构体2.GPIO初始化GPIO_InitTypeDef GPIO_InitStructure;/*启动时钟*/stm32f4xx_rcc.c 文件中RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);/* GPIO初始化 推挽 上拉 速度 */stm32f4xx_gpio.c 文件中GPIO_InitStructure.GPIO_OType GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_UP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;/* 配置Tx引脚为复用功能 */GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF;GPIO_InitStructure.GPIO_Pin DEBUG_USART_TX_PIN ;GPIO_Init(DEBUG_USART_TX_GPIO_PORT, GPIO_InitStructure);/* 配置Rx引脚为复用功能 */GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF;GPIO_InitStructure.GPIO_Pin DEBUG_USART_RX_PIN;GPIO_Init(DEBUG_USART_RX_GPIO_PORT, GPIO_InitStructure);//设置复用功能stm32f4xx_gpio.c 文件/* 连接 PXx 到 USARTx_Tx*/GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_USART1);/* 连接 PXx 到 USARTx__Rx*/GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_USART1);3.usart初始化/* 使能 USART 时钟 */RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);//配置usart结构体/* 波特率设置DEBUG_USART_BAUDRATE */USART_InitStructure.USART_BaudRate DEBUG_USART_BAUDRATE;/* 字长(数据位校验位)8 */USART_InitStructure.USART_WordLength USART_WordLength_8b;/* 停止位1个停止位 */USART_InitStructure.USART_StopBits USART_StopBits_1;/* 校验位选择不使用校验 */USART_InitStructure.USART_Parity USART_Parity_No;/* 硬件流控制不使用硬件流 */USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;/* USART模式控制同时使能接收和发送 */USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx;/* 完成USART初始化配置 */USART_Init(DEBUG_USART, USART_InitStructure);/* 嵌套向量中断控制器NVIC配置 */NVIC_Configuration();/* 使能串口接收中断 */USART_ITConfig(DEBUG_USART, USART_IT_RXNE, ENABLE);/* 使能串口 */USART_Cmd(DEBUG_USART, ENABLE);}4.nvic配置//对于static在大型嵌入式项目中不同模块往往会有功能相似的辅助函数。比如你的串口驱动里有NVIC_Configuration定时器驱动里可能也想写一个叫NVIC_Configuration的函数来配置定时器的中断。如果不加 static编译器在最终链接时会发现两个同名的全局函数从而报错重复定义。加了 static这两个同名函数就被隔离在各自的.c文件中互不干扰完美避免了命名污染。static void NVIC_Configuration(void){NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中断控制器组选择 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置nvic结构体/* 配置USART为中断源 */NVIC_InitStructure.NVIC_IRQChannel DEBUG_USART_IRQ;/* 抢断优先级为1 */NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;/* 子优先级为1 */NVIC_InitStructure.NVIC_IRQChannelSubPriority 1;/* 使能中断 */NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;/* 初始化配置NVIC */NVIC_Init(NVIC_InitStructure);}4.排错问题如果碰见串口发送数据发不对检查时钟设置外部晶振是否与库函数的25M相同如果不相同则需要修改如下1.#define PLL_M 从25M改成8M在system_stm32f4xx.c2. #define HSE_VALUE 从25M改成8M在stm32f4xx.h中