中断及串口通信进阶

一、STM32外部中断模式控制灯亮灭

1.环境配置

  • 软件版本:
    STM32CubeMX 6.1.1
    KEIL:5.37.0.0
    FlyMcu:0.188
  • 硬件:
    STM32F103C8T6

2. 使用STM32CubeMX创建项目

(1)新建项目

新建一个项目,并选择芯片型号,此处我们的型号是STM32F103C8T6
在这里插入图片描述
在这里插入图片描述

(2)设置项目

此处设置PB5为output,PA1为exit1
在这里插入图片描述
设置PB5引脚名字为LED
在这里插入图片描述
设置PA1引脚触发方式为上升沿触发
在这里插入图片描述
使能对应的外部中断线,勾选Enabled
在这里插入图片描述
配置中断优先级
在这里插入图片描述
时钟配置
在这里插入图片描述
工程文件设置
在这里插入图片描述
在这里插入图片描述

(3)设置代码

我们可以在创建的文件中找到中断服务函数
在这里插入图片描述
我们可以看到下面有一个虚函数,__weak开头的函数为虚函数,需要我们重写,所以我们到main.c中重写这个函数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if( GPIO_Pin == GPIO_PIN_1)
	{
		HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
	}
}

在这里插入图片描述

(4)烧录程序及效果

①硬件连接

在这里插入图片描述
LED长脚——3V3
LED短脚——PB5
PA1——3V3亮灯
PA1——GND熄灯

②烧录程序

在这里插入图片描述

③运行效果

二、中断方式串口通讯

1.功能需求

(1)当stm32接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”;
(2)当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”。

2.第一个功能实现

(1)新建项目

在这里插入图片描述
在这里插入图片描述

(2)设置项目

①设置RCC

在这里插入图片描述

②设置SYS

在这里插入图片描述

③设置USART

在这里插入图片描述

④设置NVIC

在这里插入图片描述

⑤创建项目

在这里插入图片描述
在这里插入图片描述
然后就可以生成项目了。

(3)设置代码

①设置全局变量

打开刚才生成的项目,在main函数前定义全局变量

char c;//指令 0:停止  1:开始
char message[]="hello Windows\n";//输出信息
char tips[]="CommandError\n";//提示1
char tips1[]="Start.....\n";//提示2
char tips2[]="Stop......\n";//提示3
int flag=0;//标志 0:停止发送 1.开始发送
②设置接收中断

函数原型为:

 HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

函数功能为:串口中断接收,以中断方式接收指定长度数据。
各项参数为:

  • UART_HandleTypeDef *huart UATR的别名
  • huart1 *pData 接收到的数据存放地址
  • Size 接收的字节数
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);
③while循环代码
if(flag==1){
			//发送信息
			HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF); 
			
			//延时
			HAL_Delay(1000);
		}
④需要在main函数下面重写的代码
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	
	//当输入的指令为s时,发送提示并改变flag
	if(c=='s'){
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF); 
	}
	
	//当输入的指令为t时,发送提示并改变flag
	else if(c=='t'){
		flag=1;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF); 
	}
	
	//当输入不存在指令时,发送提示并改变flag
	else {
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF); 
	}

	//重新设置中断
		HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);  
}

(4)烧录程序及效果

①电路连接

②程序烧录

选择刚才生成的HEX文件,进行烧录
在这里插入图片描述

③运行效果

在这里插入图片描述

3.第二个功能实现

接受字符串和单独字符的区别是要将接收到的连续字符保存到一个字符数组里。因此我们要做的是写一个接收字符串的函数,只需要修改keil中的代码即可。

(1)设置代码

①定义全局变量
int i=0;int ch;
uint8_t ucTemp[20];//定义了字符数组指令 "go stm32!"开始,"stop stm32!"停止
char message[]="hello Windows\n";//输出信息
char tips[]="CommandError\n";//提示1
char tips1[]="Start.....\n";//提示2
char tips2[]="Stop......\n";//提示3
int flag=0;//标志 0:停止发送 1.开始发送
②设置接收中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);
③在while循环中添加代码
if(flag==1){
			//发送信息
			HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF); 
			
			//延时
			HAL_Delay(1000);
		}
④重写中断函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//当输入的指令为“sto stm32!"时,发送提示并改变flag
	if(ucTemp[10] == '!'&&ucTemp[9] == '2'&&ucTemp[8] == '3'&&ucTemp[7] == 'm'&&ucTemp[6] == 't'&&ucTemp[5] == 's'
		&&ucTemp[4] == ' '&&ucTemp[3] == 'p'&&ucTemp[2] == 'o'&&ucTemp[1] == 't'&&ucTemp[0] == 's'){
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF); 
	}
	
	//当输入的指令为"go stm32!"时,发送提示并改变flag
	else if(ucTemp[8] == '!'&&ucTemp[7] == '2'&&ucTemp[6] == '3'&&ucTemp[5] == 'm'&&ucTemp[4] == 't'&&ucTemp[3] == 's'
		&&ucTemp[2] == ' '&&ucTemp[1] == 'o'&&ucTemp[0] == 'g'){
		flag=1;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF); 
	}
	
	//当输入不存在指令时,发送提示并改变flag
	else {
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF); 
	}

	//重新设置中断
		HAL_UART_Receive_IT(&huart1, (uint8_t *)&ucTemp[20], 1);  
}

(2)运行效果

在这里插入图片描述

三、DMA连续发送数据

同样是使用STM32CubeMx进行项目配置。

(1)新建并设置项目

①配置HSE

在这里插入图片描述

②配置串口

也就是配置USART1,按照下图配置
在这里插入图片描述

③时钟源设置

在这里插入图片描述

④生成代码

在这里插入图片描述
在这里插入图片描述

(2)设置代码

我们将要使用两个函数

HAL_UART_Transmit_DMA();串口DMA模式发送
HAL_Delay();延迟毫秒

HAL_UART_Transmit_DMA()用于使用DMA发送指定长度的数据,需要依次传入串口句柄,数据起始位置,发送数据数量。

故主函数可以写为:

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
	uint8_t data[] = "hello world!\n";
  while (1)
  {
		HAL_UART_Transmit_DMA(&huart1,data,sizeof(data));
		HAL_Delay(1000);
  }
}

(3)运行效果

在这里插入图片描述

四、总结

本次实验要做的东西比较多,学习了中断和DMA的串口通信方式,每种方式都有各自的好处,可以灵活运用,做的途中开发板出现了故障无法往回发送数据,尝试换了一下串口,发现没用,换了一个开发板才解决,以后也要注意保护一下板子。

五、参考链接

【嵌入式12】DMA通信原理及编程实验,DMA方式向上位机连续发送数据
【嵌入式11】HAL库实验中断开关点灯及串口通信

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值