本文主要讲述基于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(ret20)
{
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