欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

stm32串口输出

程序员文章站 2022-03-21 21:29:49
...

STM32开发板上是如何实现串口通信的,我以实现printf重定向为例来进行分析!

先看代码:

main.c:

#include "printf.h"


int main()

{

printf_init();

printf("\nhello!every body!\n");

printf("I am zoulei\n");

printf("serial communications is so mystical and interesting!\n");

printf("keep striving!\n");


}

printf.c:



#include "printf.h"

#include "stm32f10x.h"

#include "stm32f10x_rcc.h"

#include "stm32f10x_gpio.h"

#include "stm32f10x_usart.h"

#include "misc.h"

int fputc(int ch,FILE *f)

{

while(USART_GetFlagStatus(USART2,USART_FLAG_TC) != SET);

USART_SendData(USART2,(unsigned char)ch);

while(USART_GetFlagStatus(USART2,USART_FLAG_TC) != SET);

return (ch);

}


void printf_init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;


/*config USART clock*/

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);

RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2,ENABLE);

/*USART1 GPIO config*/

GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2;

GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP; //复用推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&GPIO_InitStructure);


GPIO_InitStructure.GPIO_Pin= GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //复用开漏输入

GPIO_Init(GPIOA,&GPIO_InitStructure);

/*USART1 mode Config*/

USART_InitStructure.USART_BaudRate = 115200;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART2,&USART_InitStructure);

USART_Cmd(USART2,ENABLE);

printf.h:

#ifndef __printf_H

#define __printf_H


#include "stm32f10x.h"

#include <stdio.h>

void printf_init(void);

int fputc(int ch,FILE *f);


#endif

代码分析:

1.串口初始化配置

学了STM串口通信之后,我们知道配置串口通信至少要配置:字长(一次传送的数据长度),波特率(每秒传输的数据位数),奇偶校验位,还有停止位。当然我在

配置过程中把他们分别设为8,115200,No ,1。

串口的配置主要与USART_InitTypeDef这个结构体有关,里面存放了控制参数成员:

typedef struct

{

uint32_t USART_BaudRate; //波特率

uint16_t USART_WordLength; //字长

uint16_t USART_StopBits; //停止位

uint16_t USART_Parity; //奇偶校验位

uint16_t USART_Mode; // 收发数据使能或失能

uint16_t USART_HardwareFlowControl; //硬件控制流


} USART_InitTypeDef;

其实在学习32的时候,一般如果要用到32的内设或者外设,都要进行相应的初始化,也就是相应的结构体成员进行配置,而我们本次要实现的printf重定向,也

就用到了串口,所以也要对串口进行初始化!而我是用的USART2,所以要对其进行相应的配置。

查看STM32硬件原理图:

stm32串口输出

由原理图可知,这个串口是支持TTL电平的,接收数据RX是接在PA3管脚上的,发送数据是接在PA2上的。由于我是要输出到PC上的串口终端,所以PA2要

设为复用推挽输出模式,PA3设为复用开漏输入模式。

查看stm32f10x_it.c这个代码可知USART2是挂接在APB1总线上的,GPIO是挂在APB2总线上的,如下所示:

stm32串口输出

stm32串口输出

所以我们在进行时钟初始化的时候要特别注意。

2.printf重定向

其实printf重定向就是我们将printf重新定向到串口,也就是我们可以自己重写C的库函数,当连接器检查到用户编写了与C库函数相同的名字,优先采用

用户编写的函数这样用户就可以实现对库的修改了。

 printf函数实际是一个宏,最终调用的是 fputc(int ch,FILE *f)这个函数,所以我们需要修改这个函数。

下面我们着重分析一下fputc函数:

    这个库函数调用了两个ST库函数,分别是:USART_GetFlagStatus()与USART_SendData(),形参ch表示串口将要发送的数据,也就是说。当使用printf()时,它先调用fpuc()函数,然后使用ST库的串口发送函数USART_SendData(),把数据转移到发送数据寄存器TDR.触发我们的串口向PC发送一个相应的数据,调用完USART_SendData()之后,

使用 while(USART_GetFlagStatus(USART2,USART_FLAG_TC) != SET)语句不停的检查串口的数据是否发送完成的标志位TC,一直检查到标志为“完成”,才进行下一步操作,

要注意的是USART_SendData()每次只发送一个字节的数据!

注意:由于fputc()函数的形参调用了C库的FILE,所以在程序中加入stdio.h这个头文件,便且在keil的编译器的设置中勾选Use MicroLIB(使用微库)

3.硬件连接

首先硬件上我们将USB转串口线的TXD,RXD,GND,分别接在32开发板USART2上的RXD,TXD,GND。

由于USART2是TTL电平,所以我们用的usb转串口线一定要是支持TTL电平的,否则串口通信不上!

4.效果图

串口调试助手显示:

stm32串口输出