STM32串口通信和DMA应用实例

一、stm32tubemx使用中断模式编程完成实验

(1)实验要求

用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。

用引脚PA1来控制LED的亮与灭,当PA1接入3V3电压时,PA1读到低电平,接入GND时PA1读到高电平。

高电平变成低电平时(接入GND)会产生下降沿,同理低电平变回高电平(接入3V3)时会产生上升沿,LED灯的变化由上升沿或下降沿控制,此处我们采用上升沿来控制灯亮。

(2)项目创建

1、在stm32tubemx创建新项目
2、设置引脚
将引脚PB5输出模式设置为GPIO_Output
将引脚PA1输出模式设置为GPIO_EXIT1

在这里插入图片描述
3、设置名称
点击PB5,将其User Label命名为LED
点击PA1,将其User Label命名为A1

在这里插入图片描述
4、设置A1引脚为上升沿触发
要注意PA1的GPIO mode,设置成External Interrupt Mode with Rising edge trigger detection上升沿触发

External Interrupt Mode with Falling edge trigger detection下降沿
External Interrupt Mode with Rising/Falling edge trigger detection上升沿和下降沿

这样PA1接收到上升沿信号就会亮灯

在这里插入图片描述
5、设置使能对应外部中断线
点击NVIC
在下列选项中有一个Enabled,将其勾选上
在这里插入图片描述

6、配置中断设置的优先级
默认设置即可,大部分不需要设置其他东西。

在这里插入图片描述
7、设置时钟为36MHz
将*PLLMul参数设置为×9,选择PLLCLK
而后的参数将会变成36
在这里插入图片描述

8、完成项目建立
选择Project Name,自己命名
选择Project Location,点击Browse,设置该项目的路径
选择Toolchain/IDE,将其设置成MDK-ARM
在这里插入图片描述

点击Code Generator,勾选如下选项后,点击GENERATE CODE,完成项目的建立。

在这里插入图片描述

(3)代码编写

打开LED项目

1、重写weak虚函数:打开main.c文件,将下列代码放入main.c中

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    
    
	if( GPIO_Pin == A1_Pin)//判断外部中断源
	{
    
    
		HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);//翻转LED状态
	}
}

在这里插入图片描述

2、运行结果
运行成功,准备烧录代码。

在这里插入图片描述
3、烧录代码

烧录之前要将芯片的BOOT0置1,不然烧录会失败

在这里插入图片描述

烧录成功!

4、连接线路

LED的长脚端连接3V3
LED的断脚端连接PB5
PA1:
连接3V3时,灯光亮起
连接GND时,灯光熄灭

5、观测实验结果

在这里插入图片描述
杜邦线插入时,灯光亮起
拔出时,灯光熄灭
实验成功

二、串口通信

要求:采用串口中断方式重做上周的串口通信作业,分别实现:1)当stm32接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”(提示:采用一个全局标量做信号灯);2)当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”(提示:要将接收到的连续字符保存到一个字符数组里,进行判别匹配。写一个接收字符串的函数。

(1)项目创建

1、打开STM32CubeMx创建项目
上面步骤有详细解说

2、设置RCC
进入RCC界面,将(HSE)设置为如下选项

在这里插入图片描述

3、设置SYS
选择Debug选项,将其换位Serial Wire选项
在这里插入图片描述

4、设置USART1
将Mode选项更改为Asynchronous

在这里插入图片描述

5、设置NVIC
勾选USART1 global interrupt
如下图:
在这里插入图片描述

6、建立项目即可

(2)编写代码

1、打开项目
在main.c里声名全局变量

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.开始发送

在这里插入图片描述

2、在main函数中的while循环了加入传输代码

if(flag==1){
    
    
			//发送信息
			HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF); 
			
			//延时
			HAL_Delay(1000);
		}

在这里插入图片描述

3、重写中断函数

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、运行代码

在这里插入图片描述
运行无误!

5、烧录代码

在这里插入图片描述

烧录成功!

6、打开串口通信
发送t,开始发送hello Windows
在这里插入图片描述

输入s,停止发送hello Windows

在这里插入图片描述
实验成功!

三、串口DAM实践

要求:STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据。

(1)简介

1、简介
DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。

2、传输方式

DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:

(1)外设到内存
(2)内存到外设
(3)内存到内存
(4)外设到外设

普通模式
传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若
开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输。
循环模式
可用于处理环形缓冲区和连续数据流(例如ADC扫描模式)。当激活循
环模式后,每轮传输结束时,要传输的数据数量将自动用设置的初始值
进行加载, 并继续响应DMA请求。

3、数据传输需要:

(1) 数据的源地址
(2)数据传输位置的目标地址
(3)传递数据多少的数据传输量
(4)进行多少次传输的传输模式

当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时 达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式 当到达传输终点时会重新启动DMA传输。

4、四要素

(1)传输源 :DMA数据传输的来源
(2)传输目标:DMA数据传输的目的
(3)传输数量:DMA传输数据的数量
(4)触发信号:启动一次DMA数据传输的动作

5、工作框图

在这里插入图片描述
在发生一个事件后,外设向DMA控制器发送一个请求信号。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问发出请求的外设时,DMA控制器立即发送给它一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。DMA传输结束,如果有更多的请求时,外设可以启动下一个周期。

6、接口函数

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

(2)项目创建

1、设置RCC
点击RCC,找到(HSE)选项,将其选项选如下选项

在这里插入图片描述

2、设置串口
点击USART 1,设置Mode为Asynchronous

在这里插入图片描述

3、设置使能中断
点击NVIC Settings选项,勾选Enabled选项

在这里插入图片描述

4、设置DMA
点击DMA Setting选项,选择Add,添加USART1_RX和USART1_TX,将速率设置为Medium

在这里插入图片描述

勾选Memory

在这里插入图片描述

点击System View选项,选择DMA,然后点击Add,添加如下选项

在这里插入图片描述

5、时钟设置
设置时钟为如下设置

在这里插入图片描述

6、导出项目,在Keil里面编写程序

(3)编写代码

1、在main.c中加入如下代码

uint8_t Senbuff[] = "Hello world!";  //定义数据发送数组

在这里插入图片描述

  HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
  HAL_Delay(1000);

在这里插入图片描述

2、运行代码

在这里插入图片描述

代码运行无误!

3、烧录代码

在这里插入图片描述

烧录成功!

4、串口通信

在这里插入图片描述

实验成功!

四、总结

通过此次实验,我对嵌入式开发有了更好的理解,实验难度适中,实验完成后对后面的实验有了指导性的帮助。

五、参考博客

https://blog.csdn.net/qq_46467126/article/details/121055475?spm=1001.2014.3001.5501

猜你喜欢

转载自blog.csdn.net/m0_58406663/article/details/127467534