yuzhongzhen 发表于 2018-3-29 14:20:09

STM32——串口通信

转载请注明出处:http://blog.csdn.net/wqx521
STM32——串口通信
宗旨:技术的学习是有限的,分享的精神是无限的。

一、异步串口通信协议      STM32 的串口非常强大,它不仅支持最基本的通用串口同步、异步通信,还具有 LIN 总线功能(局域互联网)、IRDA 功能(红外通信)、SmartCard 功能。一般我们利用串口打印调试信息。https://img-blog.csdn.net/20160330161109717 二、串口工作过程分析      我们只需要大概了解串口发送的过程即可。从下至上,我们看到串口外设主要由三个部分组成,分别是波特率控制、收发控制和数据存储转移。https://img-blog.csdn.net/201603301611189671、 波特率      波特率,即每秒传输的二进制位数,用 b/s (bps)表示,通过对时钟的控制可以改变波特率。在配置波特率时,我们向波特比率寄存器 USART_BRR 写入参数,修改了串口时钟 的分 频 值USARTDIV 。USART_BRR 寄存 器 包括 两 部分 , 分别 是 DIV_Mantissa(USARTDIV 的整数部分)和 DIV_Fraction(USARTDIV 的小数)部分,最终,计算公式为 USARTDIV=DIV_Mantissa+(DIV_Fraction/16)。USARTDIV 是对串口外设的时钟源进行分频的,对于 USART1,由于它挂载在 APB2总线上,所以它的时钟源为 f PCLK2 ;而 USART2、3 挂载在 APB1 上,时钟源则为 fPCLK1,串口的时钟源经过 USARTDIV 分频后分别输出作为发送器时钟及接收器时钟,控制发送和接收的时序。2、 收发控制      寄存器 :CR1、CR2、CR3 和 SR,即USART 的三个控制寄存器(Control Register)及一个状态寄存器(Status Register)。通过向寄存器写入各种控制参数来控制发送和接收,如奇偶校验位、停止位等,还包括对USART 中断的控制;串口的状态在任何时候都可以从状态寄存器中查询得到。具体的控制和状态检查,我们都是使用库函数来实现的。3、 数据存储转移      收发控制器根据我们的寄存器配置,对数据存储转移部分的移位寄存器进行控制。当我们需要发送数据时,内核或 DMA 外设(一种数据传输方式,在后面介绍)把数据从内存(变量)写入到发送数据寄存器 TDR 后,发送控制器将适时地自动把数据从 TDR 加载到发送移位寄存器,然后通过串口线 Tx,把数据一位一位地发送出去,当数据从 TDR转移到移位寄存器时,会产生发送寄存器 TDR 已空事件 TXE,当数据从移位寄存器全部发送出去时,会产生数据发送完成事件 TC,这些事件可以在状态寄存器中查询到。而接收数据则是一个逆过程,数据从串口线 Rx 一位一位地输入到接收移位寄存器,然后自动地转移到接收数据寄存器 RDR,最后用内核指令或 DMA
三、UART串口配置流程:(1)      使能串口1的时钟(2)      配置串口1的I/O(3)      配置串口1的工作模式,具体为波特率为 115200 、8 个数据位、1 个停止位、无硬件流控制。即 115200 8-N-1。
view plain copy



[*]void USART1_Config(void)
[*]{
[*]GPIO_InitTypeDef GPIO_InitStructure; // 串口IO结构体
[*]USART_InitTypeDef USART_InitStructure;
[*]
[*]/* 配置串口时钟 */
[*]RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
[*]
[*]/* TX --PA9 -- 通用推挽式输出 -- 50MHZ */
[*]GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
[*]GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
[*]GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
[*]GPIO_Init(GPIOA, &GPIO_InitStructure);
[*]
[*]/* RX --PA10 -- 输入*/
[*]GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
[*]GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
[*]GPIO_Init(GPIOA, &GPIO_InitStructure);
[*]
[*]/* 串口初始化 -- 115200-8-1 */
[*]USART_InitStructure.USART_BaudRate = 115200; // 波特率115200
[*]USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据位
[*]USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1位停止位
[*]USART_InitStructure.USART_Parity = USART_Parity_No ; // 无奇偶校验位
[*]USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowC ontrol_None; // 无硬件流
[*]USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 配置串口的模式。为了配置双线全双工通信,需要把 Rx 和 Tx 模式都开启。
[*]USART_Init(USART1, &USART_InitStructure); // 填充完结构体, 向寄存器写入配置参数
[*]USART_Cmd(USART1, ENABLE); // 使能 USART1 外设
[*]}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>


      要想 printf() 函数工作的话,我们需要把 printf() 重新定向到串口中。为了实现重定向 printf() 函数,我们需要重写 fputc() 这个 C 标准库函数,因为 printf()在C 标准库函数中实质是一个宏,最终是调用了 fputc() 这个函数。
view plain copy



[*]// 重定向到串口
[*]int fputc(int ch, FILE *f)
[*]{
[*]/* 发送一个字节数据到 串口 */
[*]USART_SendData(USART1, (uint8_t) ch);
[*]
[*]/* 等待发送完毕 */
[*]while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
[*]
[*]return (ch);
[*]}
----------------------------------华丽的分界线-----------------------------北京万邦易嵌科技有限公司:专业提供单片机、M3/M4、linux、Android、QT技术服务、技术培训。详细咨询请加QQ:715493858


页: [1]
查看完整版本: STM32——串口通信