【嵌入式实验2】中断方式控制LED+单个字符/字符串控制串口通信+DMA方式向上位机连续发送数据

发布于:2022-10-23 ⋅ 阅读:(643) ⋅ 点赞:(0)

本文主要讲述基于STM32F103C8T6的中断方式控制LED、单个字符/字符串控制串口通信、DMA方式向上位机连续发送数据这几个实验的具体操作过程。

一、中断控制LED亮灭

(一)题目要求

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

(二)STM32CubeMX设置

1.新建工程,选择STM32F103C8T6芯片。
在这里插入图片描述

2.点击SYS,选择Serial Wire
在这里插入图片描述
3.点击RCC,选择Crystal…
在这里插入图片描述

4.配置中断优先级
在这里插入图片描述

5.点击GPIO,此处将PA4脚设为GPIO_Output,与LED灯负极相连;PB9设置为GPIO_EXTI9,用作开关。将PB9的GPIO mode设置为上升沿触发,即“External interrupt Mode with Rising edge trigger detection”


使能对应的外部中断线,点击enable。
在这里插入图片描述
6.时钟配置,这里设置成72M
在这里插入图片描述

后面生成工程即可。

(三)代码撰写

在main.c文件中的主函数下方添加以下代码

/* USER CODE BEGIN 4 /
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/
Prevent unused argument(s) compilation warning /
if(GPIO_Pin==(GPIOB,GPIO_PIN_9))
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4); //翻转电平
/
NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}

/* USER CODE END 4 */

在这里插入图片描述

(四)编译烧录

1.编译结果如下所示
在这里插入图片描述
2.烧录将生成的hex文件进行烧录
在这里插入图片描述

(五)电路连接及结果展示

1.电路连接

STM32F103C8T6 USB to TTL
3V3 3V3
A9 RXD
A10 TXD
GND GND
STM32F103C8T6 LED
A4 LED负极
3V3 LED正极

在这里插入图片描述
(2)结果展示
LED灯亮的时候出现抖动是正常的,注意杜邦线接触不良的情况。

stm32f103c8t6中断方式控制LED

二、单个字符控制串口通信

(一)题目要求

当stm32接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”(提示:采用一个全局标量做信号灯);

(二)STM32CubeMX设置

(1)设置RCC
在这里插入图片描述

(2)设置SYS
在这里插入图片描述
(3)设置NVIC
在这里插入图片描述
(4)设置USART
在这里插入图片描述
(5)时钟设置
在这里插入图片描述
后面创建项目,打开至keil即可。

(二)代码编写

在main.c文件中添加头文件和以下内容

#include “string.h”
#include “stdio.h”
char s;
char message[]=“hello windows!\r\n”;
char tips[]=“ERROR!\r\n”;
char tips1[]=“Start!\r\n”;
char tips2[]=“Stop!\r\n”;
int flag=1;

在主函数的while循环上添加

HAL_UART_Receive_IT(&huart1, (uint8_t *)&s, 1);

在while循环内部添加

if(flag==1)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF);
HAL_Delay(1000);
}

在main.c文件中主函数下方添加以下函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//当输入的指令为s时,发送提示并改变flag
if(s==‘s’){
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF);
}
//当输入的指令为t时,发送提示并改变flag
else if(s==‘t’){
flag=1;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF);
}
//重新设置中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&s, 1);
}

(三)编译烧录

编译
在这里插入图片描述
烧录
在这里插入图片描述

(四)电路连接及结果展示

(1)电路连接
在这里插入图片描述

(2)结果。尝试同时发送st可以看到先出现"stop!"然后"start!“重新开始"hello windows!”,由此可知串口通信中上位机发送是单个字符发送,中间产生中断。
在这里插入图片描述

三、字符串控制串口通信

(一)题目要求

当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”(提示:要将接收到的连续字符保存到一个字符数组里,进行判别匹配。写一个接收字符串的函数。)

(二)STM32CubeMX配置

参照上述“单个字符控制串口通信”的步骤。

(三)代码撰写

根据上述单个字符控制串口通信的实验同时发送“st”的情况可以看出串口通信过程中发送的字符串是以单个字符接收的,中间产生了中断。
因此需要写一个接收字符串的函数,再与字符串进行对比。以下操作主要针对main.c文件的内容。
1.添加头文件

#include “string.h”
#include “stdio.h”

2.增加全局变量

uint8_t aRxBuffer; //接收中断缓冲
uint8_t Uart1_RxBuff[256]; //接收缓冲
uint8_t Uart1_Rx_Cnt = 0; //接收缓冲计数
uint8_t cAlmStr[] = “数据溢出(大于256)\r\n”;
char s[];
char s1[]=“stop stm32!”;
char s2[]=“go stm32!”;
uint8_t message[]=“hello windows!\r\n”;
uint8_t tips[]=“ERROR!\r\n”;
uint8_t tips2[]=“Start!\r\n”;
uint8_t tips1[]=“Stop!\r\n”;
int flag=1;

3.主函数中while循环上方添加

HAL_UART_Receive_IT(&huart1,(uint8_t*)&aRxBuffer,1);//开启接收中断

在循环内添加

if(flag==1)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&message, sizeof(message),0xFFFF);
HAL_Delay(1000);
}

4.在主函数下添加

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
if(Uart1_Rx_Cnt >= 255) //溢出判断
{
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));
HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
}
else
{
Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer; //接收数据转存
if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
{
HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
strcpy(s,Uart1_RxBuff);
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff)); //清空数组
}
ret1=strcmp(s,s1);
ret2=strcmp(s,s2);
if(ret10)
{
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&s, strlen(s),0xFFFF);
HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, sizeof(tips1),0xFFFF);
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}
else if(ret2
0)
{
flag=1;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, sizeof(tips2),0xFFFF);
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}

(四)编译烧录

编译结果:
在这里插入图片描述

烧录:
在这里插入图片描述

(五)电路连接及结果展示

1.电路连接
与上述单个字符控制串口通信结果相同。
2.结果展示
该实验仅实现了字符串的接受,无法进行字符串接收后判断是否继续串口通信的步骤。
在这里插入图片描述

四、串口DMA方式向上位机连续发送数据。

(一)题目要求

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

(二)CubeMX设置

SYS设置
在这里插入图片描述
RCC设置
在这里插入图片描述

USART设置,确保波特率的正确。在这里插入图片描述
使能中断选择:
在这里插入图片描述
在USART1中点击DMA Settings,然后点击add,添加USART1_RX和USART1_TX,修改传输速率Priority为中速率Medium。

在这里插入图片描述
保证mode为Normal,Memory勾选。
在这里插入图片描述

在System view 下点击DMA,然后点击Add,添加MEMTOMENT。
在这里插入图片描述
时钟设置
在这里插入图片描述
后面创建工程打开keil即可.

(三)代码撰写

在main.c文件中的主函数中添加以下代码

/* USER CODE BEGIN Init /
uint8_t Senbuff[]=“hello windows!”;
/
USER CODE END Init */

在main.c文件中的主函数中的while循环中添加以下代码

/* USER CODE END WHILE 
*/HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
HAL_Delay(1000);
/* USER CODE BEGIN 3 */

(四)编译烧录

编译结果如下
在这里插入图片描述
烧录:
在这里插入图片描述

(五)电路连接以及结果展示

1.电路连接同第二部分单个字符控制串口通信的电路连接。
2.结果展示
如果想要“hello windows!”换行出现,可将上述代码撰写部分的“hello windows!\n”改成“hello windows!\r\n”.
在这里插入图片描述

五、总结

通过本次实验操作,能够清楚地了解STM32F103C8T6的串口通信以及中断方式,特别是针对字符串控制串口通信的实验,开发板无法一次性接受一整个字符串,而是每接收一个字符就会产生中断,针对字符串则需要写一个数组将每个字符存到数组中然后进行对比。

六、参考文献

https://blog.csdn.net/qq_53112972/article/details/127442694
https://blog.csdn.net/qq_47281915/article/details/121024427
https://blog.csdn.net/qq_47281915/article/details/121053903

本文含有隐藏内容,请 开通VIP 后查看

微信公众号

今日签到

点亮在社区的每一天
去签到