STM32F103系列_串口Usart收发函数

常见问题:

串口第一个字节丢失?

解决方法:读取USARTx->SR能避免首个数据发送时开头丢失。

串口不稳定?

解决方法:传输线不要过长,传输接口不要松动,传输线附近不要有大的干扰源。。

串口调用英文数字没问题,但中文乱码?

解决方法:关闭工程,在工程目录找到main.c,用记事本打开,“文件”>“另存为”,修改ANSI编码为“UTF-8”,另存替换原来的main.c,重新编译烧录即可。

串口调用与TIM冲突,卡住?

解决方法:用串口中断。

代码

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

使用方法

1、在mian函数里调用Usart.h头文件,初始化串口1波特率为115200:Usart1_Init(115200);
2、printf("%d",123456)或printf(“123456”),串口打印123456;
3、printf("%d",abcdefg)或printf(“abcdefg”),串口打印abcdefg;
4、printf(“你好”),串口打印“你好”;
4、printf("\r\n"),串口输出回车换一行;

猜你喜欢

转载自blog.csdn.net/xingdala/article/details/121591092