STM32 的 USART 串口中断通讯---输出 hello windows(实现 STM32 与主机的通讯)

文章内容
STM32 的 USART 串口通讯—汇编输出 hello windows!的基础上,学习 stm32 串口中断,采用串口中断方式重做汇编输出 hello windows!要求
1)设置波特率为115200,1 位停止位,无校验位。
2)STM32 系统给上位机( win10 )连续发送“hello windows!”。win10 采用“串口助手”工具接收。
3)当上位机给 stm32 发送 “ stop,stm32! ” 后,STM32 停止发送。

1 USART 接发通信

1.1 任务说明

在上一篇文章中,我们实现了 STM32 将数据传输给主机,我们不仅仅可以将数据发送到串口调试助手,我们还可以在串口调试助手发送数据给 STM32,控制器程序根据接收到的数据进行下一步工作。

首先,我们来编写一个程序实现 STM32 开发板与电脑通信,在开发板上电时通过 USART 发送一串字符串给电脑,然后开发板进入中断接收等待状态,如果电脑有发送数据过来,开发板就会产生中断,我们在中断服务函数接收数据,并马上把数据返回发送给电脑

1.2 USART 控制器

SART 有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等等。使用 USART 之前需要向 USART_CR1 寄存器的 UE 位置 1 使能 USART,UE 位用来开启供给给串口的时钟。发送或者接收数据字长可选 8 位或 9 位,由 USART_CR1 的 M 位控制。

1.2.1 发送器

当发送使能位 TE 置 1 之后,发送器开始会先发送一个空闲帧(一个数据帧长度的高电平),接下来就可以往 USART_DR 寄存器写入要发送的数据。在写入最后一个数据后,需要等待 USART 状态寄存器(USART_SR)的 TC 位为 1,表示数据传输完成,如果 USART_CR1 寄存器的 TCIE 位置 1,将产生中断。
字符发送时序图:
在这里插入图片描述

1.2.2 接收器

如果将 USART_CR1 寄存器的 RE 位置 1,使能 USART 接收,使得接收器在 RX 线开始搜索起始位。在确定到起始位后就根据 RX 线电平状态把数据存放在接收移位寄存器内。接收完成后就把接收移位寄存器数据移到 RDR 内,并把 USART_SR 寄存器的 RXNE 位置 1,同时如果 USART_CR2 寄存器的 RXNEIE 置 1 的话可以产生中断。
在这里插入图片描述

2 串口中断实验过程

2.1 实验准备

2.2 代码分析

全部代码可以从上面的链接里获取。

在编写代码时,只需要对三个文件进行修改即可,其他都是库文件,不用更改。这里做简单分析:
在这里插入图片描述

  • GPIO 和 USART 宏定义
/*串口1-USART1 */
#define  DEBUG_USARTx                   USART1  //定义串口一
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200  //设置波特率为 115200

/*USART GPIO 引脚宏定义*/
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler

使用宏定义方便程序移植和升级。
这里我们使用 USART1,设定波特率为115200,选定 USART 的 GPIO 为 PA9 和 PA10。

  • 中断控制器 NVIC 配置与字符发送
    这两个函数的具体解释在代码中也已标注,不再过多赘述。

  • USART 中断服务函数

// 串口中断服务函数
void DEBUG_USART_IRQHandler(void)
{
  uint8_t ucTemp;
	//串口一接收中断
	if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
	{
		//获取接收到的数据
		ucTemp = USART_ReceiveData(DEBUG_USARTx);
		//如果接收标志为 0 ,则执行下面的部分
		if((USART_RX_FLAG & 0x8000) == 0)
		{
			//接收到了0x0d
			if(USART_RX_FLAG & 0x4000)
			{
				//接收错误,重新开始
				if(ucTemp != 0x0a)
					USART_RX_FLAG=0;
				//接收完成
				else
					USART_RX_FLAG |= 0x8000;
			}
			//还未接收到0x0d
			else
			{
				//接收到回车
				if(ucTemp == 0x0d)
				{
					USART_RX_FLAG |= 0x4000;
				}
				else
				{
					USART_RX_BUF[USART_RX_FLAG & 0x3FFF] = ucTemp;
					USART_RX_FLAG++;
					//接收数据错误,重新开始接收
					if(USART_RX_FLAG > 99)
						USART_RX_FLAG = 0;
				}
			}
		}
	}	 
}

USART_GetITStatus 函数与 USART_GetFlagStatus 函数类似用来获取标志位状态,但 USART_GetITStatus 函数是专门用来获取中断事件标志的,并返回该标志位状态。使用 if语句来判断是否是真的产生 USART数据接收这个中断事件,如果是真的就使用 USART 数据读取函数 USART_ReceiveData 读取数据到指定存储区。然后再调用 USART 数据发送函数 USART_SendData 把数据又发送给串口。

  • 延时函数
//毫秒级的延时函数
void delay_ms(uint16_t delay_ms)
{    
  volatile unsigned int num;
  for (num = 0; num < delay_ms; num++)
  {
    delay_us(1000);
  }
}
  • 发送数据函数
//连续发送数据
void Usart_SendString(void)
{
	uint8_t i = 0;
	
	while(1)
	{
		if(USART_RX_FLAG & 0x8000)
		{
			// 获取接收到的数据长度
			len = USART_RX_FLAG & 0x3FFF;
			Usart_SendStr(DEBUG_USARTx, "\n");
			for(i=0; i<len;i++)
			{
				// 向串口发送数据
				USART_SendData(DEBUG_USARTx, USART_RX_BUF[i]);
				//等待发送结束
				while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TC)!=SET);
			}
			Usart_SendStr(DEBUG_USARTx, "\n\n");
			//比较字符串
			if(strcmp((char *)USART_RX_BUF,"stop,stm32!")==0)
			{
				Usart_SendStr(DEBUG_USARTx, "stm32已停止发送!");
				break;//退出循环
			}
			//初始化
			USART_RX_FLAG=0;
			memset(USART_RX_BUF,0,sizeof(USART_RX_BUF));
		}
		else
		{
			//循环发送数据
			Usart_SendStr(DEBUG_USARTx, "hello windows!\n");
			delay_ms(800);
		}
	}
}

在发送数据中,添加了接收数据语句,当 STM32 收到上位机发来的数据后,它会将数据回传给串口,并结束发送。

  • 主函数
int main(void)
{	
	USART_Config();
	
	Usart_SendString();  //调用连续发送数据函数
	return 0;
}

主函数什么都不做,只是静静地等待 USART 接收中断的产生,并在中断服务函数把数据回传。

2.3 编译形成 hex 文件

点击编译形成 hex 文件,警告可忽略。
在这里插入图片描述

2.4 串口中断通讯结果

  • 硬件连接
    只需要完成USB转TTL模块stm32f103c8t6的连接。

GND-G
3V3-3.3
RXD-A9
TXD-A10

  • 烧录
    使用 mcuisp 软件打开 hex 文件,将板子的 boot0 置 1,boot1 置 0,成功烧写进 STM32F103C8T6 板子中。
    在这里插入图片描述
  • 串口调试效果
    烧录成功后,切记要将板子断电(直接拔掉),将板子的 boot0 置 0,再上电。
    设置好串口调试助手的各个参数,打开 hex 文件,如下图:
    在这里插入图片描述
    打开串口,并发送 stop,stm32! ,效果如下:
    在这里插入图片描述

3 总结

整篇文章的编写还是比较顺利的,许多代码都是库文件里的,需要编写的代码并不是很多。通过串口中断完成 STM32 与上位机的通讯,代码主要实现是在发送数据函数这里,在发送数据中,添加了接收数据语句,当 STM32 收到上位机发来的数据后,它会将数据回传给串口,并结束发送。
文章内容知识串口中断通讯的一个小例子,读者可以继续学习,下面附有学习资料。

4 参考资料

1、基于 stm32 的应用实例 —— USART 串口通讯(stm32 与主机通讯)
2、《零死角玩转STM32—F103指南者》第 21 章:USART串口通讯
提取码:luha
3、STM32串口通信USART学习笔记

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值