基于STM32F103ZET6串口实验

文章最后是串口中断的总结及算法
串口的重要性大家都知道!mcu外部的重要接口,也是软件调试的重要调试方式,不管是调试串口,还是通信串口,原理都是一样,这次我们将使用串口1来接收pc发出的数据,再将数据发回给pc,我们使用的是正点原子板载usb串口。
接下来我们要进行哪些大概步骤:
1)使用gpio,gpio初始化(时钟使能)
2)使用串口,串口初始化(时钟使能,复位)
3)使用中断,中断初始化(开启使能)
4)中断函数编写(包括数据接收)
5)主函数实现数据发送给pc
串口配置
先从简单的开始
定义串口的头文件usart.c

#ifndef USART_H
#define USART_H
#define len 64//接收数据的最大个数buff
#include "sys.h"//io口的操作头文件包含

extern u8 bufff[len];
extern u16 USART_RX_STA;//接收数据标志变量
extern void usart_init(u32 bound);//串口初始化
#endif

这个都没什么说的,重点是在源文件!

定义源文件usart.c

#include "sys.h"
#include "usart.h"
u8 bufff[len];
u16 USART_RX_STA=0;
void usart_init(u32 bound)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	USART_InitStructure.USART_BaudRate=bound;
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	USART_InitStructure.USART_Parity=USART_Parity_No;
	USART_InitStructure.USART_StopBits=USART_StopBits_1;
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&USART_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	USART_Cmd(USART1, ENABLE);
}
void USART1_IRQHandler(void)
{
	unsigned char res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
		res=USART_ReceiveData(USART1);
		if((USART_RX_STA&0x8000)==0)
		{
			if((USART_RX_STA&0x4000))
			{
					if(res==0x0A)
					{
						USART_RX_STA|=0x8000;
					}
					else 
					{
					USART_RX_STA=0;	
					}
			}
			else 
			{
				if(res==0x0d)
				{
					
					USART_RX_STA|=0x4000;
				}
				else 
				{
					bufff[USART_RX_STA&0x3FFF]=res;
						USART_RX_STA++;
						if(63<(USART_RX_STA&0x3FFF))
						{
							USART_RX_STA=0;
						}
				}
			}
		}
	}
}

新手看到这里都要哭了,告诉你!别慌,其实就一个函数是关键!
uint16_t USART_ReceiveData(USART_TypeDef USARTx);
也就是res=USART_ReceiveData(USART1);
*
这是中断响应接收到的一个字节数据!
其他的程序全是对这个接收到的数据进行一个数据处理!这个可以根据自己的通信协议来更改
USART_RX_STA是一个16位的二进制数据,用来保存数据的指标
如:数据的帧头,帧尾等等

当然可以根据自己的喜好,变换处理的方式,上面只是一个例子,初始化函数不用看,解释一下中断函数这个例子:
思路:如果特定数据(数据开始或者结束接收)到来,在定义的USART_RX_STA中标记出数据(数据开始或者结束接收)到来,在下一次通信(真实需要传输的)数据到来时,查看USART_RX_STA中的标志位,判断数据是否接收完毕,如果没有,此数据保存,继续接受收据,直到收到帧尾,如果已经接收完毕,抛弃该数据!
USART_RX_STA:
在这里插入图片描述
定义主函数main.c

#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include "sys.h"
#include "stdio.h"

int main(void)
{
	u16 le;
	u8 i;
	delay_init();	    	
	LED_Init();		  	     
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 
	usart_init(115200);
	 while(1)
	 {
		 if((USART_RX_STA&0x8000))
		 {
			 USART_SendData(USART1, 0x00);
			 le=(USART_RX_STA&0x3FFF);
			 for(i=0;i<le;i++)
			 {
				 USART_SendData(USART1, bufff[i]);
				 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==0)
				 {
					 ;
				 }
			 }
				 USART_RX_STA=0;
		 }
		 else
		 {
			 LED0=0;
			 delay_ms(500); 
		 }
	 }
}

USART_RX_STA中我们可以判断出数据是否接收完整,我们在main函数中用while循环一直检测该数据,一旦成功,将发出数据到pc,这里的led灯来指示系统正常工作中!
USART_GetFlagStatus(USART1,USART_FLAG_TC)是单个字节数据发送完成标志位
如果单个字节发送成功,将会被置1;跳出空循环继续进行bufff中的字节发送,发送完毕后,我们需要将USART_RX_STA的标志位清零,清零后我们的STM32才会继续进行数据的接收!
有点小伙伴就要想了,如果发送完才能接收,那要是数据过多怎么办,会不会造成数据的阻塞?所以这时候就可以更改自己的逻辑结构,算法,使得满足你自己所想的通信协议要求!
比如:我可以接收发送来的所有数据(用个定时器计时,两个中断相应的间隔时间超多多少ms停止本buff缓存数据),再用下一个buff接收下一组数据,不一定在线程中就一个数据缓存buff,就一个buff只能做一些简单的数据交互,这些的这些都等着自己去探索,希望我的讲解对你有所帮助!
其他
希望大家对于自己理解的串口多多交流,我们在生活中一般会使用一个线程在专门接收数据,这样比较耗资源,有没有更好的方法来接收数据,还请大家留言!谢谢

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值