一、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库实验中断开关点灯及串口通信