STM32F103 series_serial port Usart transceiver function

common problem:

The first byte of the serial port is lost?

Solution: Reading USARTx->SR can avoid the loss of the beginning when the first data is sent.

Is the serial port unstable?

Solution: The transmission line should not be too long, the transmission interface should not be loose, and there should be no large interference sources near the transmission line. .

There is no problem in calling English numbers through the serial port, but Chinese garbled characters?

Solution: Close the project, find main.c in the project directory, open it with Notepad, "File" > "Save As", modify the ANSI encoding to "UTF-8", save and replace the original main.c, recompile and burn That’s it.

The serial port call conflicts with TIM and gets stuck?

Solution: Use serial port interrupt.

code

Usart.c

#include "stm32f10x.h"

//确保没有从C库链接使用半主机的函数
#pragma import(__use_no_semihosting)

//标准库需要的支持函数
struct __FILE
{
    
    
	int handle;
};

FILE __stdout;

//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
    
    
	x = x;
}

//重定义fputc函数
int fputc(int ch, FILE *f)
{
    
    
#if EN_USART1_RX

	while ((USART1->SR & 0X40) == 0)
		; //循环发送,直到发送完毕
	USART1->DR = (u8)ch;

#endif

#if EN_USART2_RX

	while ((USART2->SR & 0X40) == 0)
		; //循环发送,直到发送完毕
	USART2->DR = (u8)ch;

#endif

	return ch;
}

#if EN_USART1_RX //如果使能了串口1的接收

//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART1_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART1_RX_STA = 0; //接收状态标记

void Usart1_Init(u32 bound)
{
    
    
	//GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟

	//USART1_TX   GPIOA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化GPIOA.9

	//USART1_RX	  GPIOA.10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;			  //PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);				  //初始化GPIOA.10

	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		  //子优先级0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			  //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);							  //根据指定的参数初始化VIC寄存器

	//USART 初始化设置
	USART_InitStructure.USART_BaudRate = bound;										//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						//字长为8位数据格式
	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(USART1, &USART_InitStructure);	   //初始化串口1
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口接受中断
	USART_Cmd(USART1, ENABLE);					   //使能串口1
}

void USART1_IRQHandler(void) //串口1中断服务程序
{
    
    
	u8 Res;
	if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
    
    
		Res = USART_ReceiveData(USART1); //读取接收到的数据

		if ((USART1_RX_STA & 0x8000) == 0) //接收未完成
		{
    
    
			if (USART1_RX_STA & 0x4000) //接收到了0x0d
			{
    
    
				if (Res != 0x0a)
					USART1_RX_STA = 0; //接收错误,重新开始
				else
					USART1_RX_STA |= 0x8000; //接收完成了
			}
			else //还没收到0X0D
			{
    
    
				if (Res == 0x0d)
					USART1_RX_STA |= 0x4000;
				else
				{
    
    
					USART1_RX_BUF[USART1_RX_STA & 0X3FFF] = Res;
					USART1_RX_STA++;
					if (USART1_RX_STA > (USART_REC_LEN - 1))
						USART1_RX_STA = 0; //接收数据错误,重新开始接收
				}
			}
		}
	}
}
#endif

#if EN_USART2_RX //如果使能了串口2的接收

//串口2中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART2_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART2_RX_STA = 0; //接收状态标记

void Usart2_Init(u32 bound)
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA, ENABLE); //使能USART2,GPIOA时钟

	//USART2_TX	  GPIOA.2
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化GPIOA.2

	//USART2_RX	  GPIOA.3
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;			  //PA3
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);				  //初始化GPIOA.3

	//Usart2 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		  //子优先级1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			  //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);							  //根据指定的参数初始化VIC寄存器

	//USART 初始化设置
	USART_InitStructure.USART_BaudRate = bound;										//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						//字长为8位数据格式
	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);										//初始化串口2

	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启串口接收中断
	USART_Cmd(USART2, ENABLE);					   //使能串口2
}

void USART2_IRQHandler(void) //串口2中断服务程序
{
    
    
	u8 Res;
	if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
    
    
		Res = USART_ReceiveData(USART2); //读取接收到的数据

		if ((USART2_RX_STA & 0x8000) == 0) //接收未完成
		{
    
    
			if (USART2_RX_STA & 0x4000) //接收到了0x0d
			{
    
    
				if (Res != 0x0a)
					USART2_RX_STA = 0; //接收错误,重新开始
				else
					USART2_RX_STA |= 0x8000; //接收完成了
			}
			else //还没收到0X0D
			{
    
    
				if (Res == 0x0d)
					USART2_RX_STA |= 0x4000;
				else
				{
    
    
					USART2_RX_BUF[USART2_RX_STA & 0X3FFF] = Res;
					USART2_RX_STA++;
					if (USART2_RX_STA > (USART_REC_LEN - 1))
						USART2_RX_STA = 0; //接收数据错误,重新开始接收
				}
			}
		}
	}
}

#endif

Usart.h

#ifndef _USART_H__
#define _USART_H__

#include "stm32f10x.h"
#include "STM32F103C6T6.h"

#define USART_REC_LEN 200 //定义最大接收字节数 200
#define EN_USART1_RX 1    //使能(1)/禁止(0)串口1接收
#define EN_USART2_RX 0    //使能(1)/禁止(0)串口2接收

extern u8 USART1_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART1_RX_STA;               //接收状态标记

extern u8 USART2_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART2_RX_STA;               //接收状态标记

void Usart1_Init(u32 bound);
void Usart2_Init(u32 bound);

#endif

Instructions

1. Call the Usart.h header file in the main function to initialize the serial port 1 baud rate to 115200: Usart1_Init(115200);
2. printf("%d",123456) or printf("123456"), the serial port prints 123456;
3. printf("%d",abcdefg) or printf("abcdefg"), the serial port prints abcdefg; 4.
printf("Hello"), the serial port prints "Hello";
4. printf("\r\n" ), the serial port output presses Enter and changes to a new line;

Guess you like

Origin blog.csdn.net/xingdala/article/details/121591092