使用hal库方式实现对于stm32的串口通信
stm32 在给pc机发送不断的hello windows语句时,我们可以使用中断服务程序来反向控制,是否继续发送,这里使用‘*’代表继续发送‘#’表停止发送。
首先我们需要对应的环境,使用hal库,我们就需要cubemx,可以在st公司官网上下载。我们使用的flymcu只能烧录软件,不能发送信息,所以还需要下载sscom 串口助手来帮助调试。
首先让我们进入cubemx,并且新建一个工程。
选择我们使用的stm32f103c8芯片,
先设置sys
然后我们调节rcc
调整usart1的串口设置。
最后调节nvic
在code manege 里面记得调整你使用的IDE 我们用的是keil5
上面就是项目位置 和名称。
这样直接创建代码就行。
直接打开main.c
在代码main函数的while 循环中,就是我们需要写入的输出函数,
但是在这之前,我们需要定义全局变量,把我们预计要发送的语句提前定义上去。
char c;//开始指令 A:停止 B:开始
char message[]=" hello windows\n";//输出目标信息
char error[]="commanderror\n";
char tips1[]="startcmd...\n";
char tips2[]="stopcmd...\n";
char flag=1;//中断标志 #:停止发送 *.开始发送
好的,第一个c 表示pc机给stm32 发送的变量,是用来触发中断函数的。可以看到message 就是我们要不断发送的hello windows,第二个error是表示在指令不存在时的回馈,tips1 表示*继续或者开始发送。
tips2 则表示# 停止发送。
下面的flag=1时表示是否在发送的状态,1为发送,2为停止。
这里初始定义为1 ,所以串口会在一开始就不断发送message。
接下来回到我们的while语句之前,我们还需要定义中断服务函数
如下
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1); //设置变量为c的中断,也就是c会承接一个指令执行我们的中断服务函数
//在中断服务函数里面,我们可以设置根据c的不同指令出现的不同操作,比如让flag变化 注意flag变化会直接影响是否正常发送
好的,让我解释这三个量是什么,首先,这个函数是一个中断函数,它可以让程序在接受数据时还可以执行其他操作。
第一个&huart1 这是一个指向uart 结构体的指针。
第二个(uint8_t *)&c 首先&c表示取c的地址,也就是它的指针,前面的括号表示将这个指针强制类型转换为uint8_t 这是一个中断函数要求的类型。
第三个 ‘ 1’ 表示要接受的字符长度,同时他也是个条件,当接收到对应长度的字符,此中断才会启用。
接下来说明启动中断过后会如何。
首先,中断条件一旦满足,就会进入中断服务函数,这个函数内,我们可以实现正常的所有函数操作,比如最基本的条件判断if语句,使用这个语句我们就可以判断是否继续发送。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//当输入的指令为#时,发送提示并改变flag
if(c=='#')
{
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF);
}
//当输入的指令为*时,发送提示并改变flag
else if(c=='*'){
flag=1;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF);
}
//当输入不存在指令时,发送提示并改变flag
else {
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&error, strlen(error),0xFFFF);
}
//重新设置中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1); //这样中断就不止执行一次了,只需要在中断服务末尾再使用中断就行。
}
好的,可以看到里面有一个transmis函数,这个就是stm32 发送到pc机的函数,我们可以看到,在c分别为#和*时,我们直接在if语句里面发送给pc机了tips1 和tips2 以及error语句。
那么怎么操控我们的message语句呢。
在主函数的while 循环中,我们这样写。
//code start
if(flag==1)
{
//发送信息
HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF);
//延时
HAL_Delay(1000);
}
//每次发送完成后检测,如果变量c进入到目标长度字符,就会触发中断服务函数,再利用中断服务来操作是否继续发送所需字符。
好的,可以看到在主函数中,我们使用if语句判断flag是否为1来判断需不需要发送,而我们又将flag定义为全局变量,各个函数的数值改变flag都会导致所有的flag数值改变,所以我们只需要在中断服务函数里面,不断给flag赋值1或者0 就行,只要赋值1 ,则全局变量改变,导致主函数flag数值变化,再导致我们继续发送。
但是注意在中断服务函数的末尾我们还需要定义一次中断函数,因为一个中断函数只会中断一次,导致的是我们只能执行一次指令,所以在中断服务函数在定义一次,就可以一直执行指令。
总体的顺序如下。
定义中断
stm32 发送message
检测中断,检测到变量c出现对应长度的字符。
触发中断>进入中断服务函数,实现我们需要的功能
中断服务函数末尾再次定义中断。
这样达成一个循环。
在烧录程序之前,我们线使用keil的逻辑分析仪看一下usart1串口的变化情况。
如下
可以看到单位是十秒。
我们再次缩小单位,进入到单个跳变的帧发送情况。
如下
然后我们使用sscom串口助手在pc上进行调试。
进去先打开串口,可以看到stm32开始不断发送hello windows语句。
这是因为我们给flag初始赋值为1.
我们先发送#,使其停止。
可以看到我们收到了预先设定的stopcmd语句,这代表中断服务程序被正确的执行了。
我们再使用* 在继续发送。
可以看到我们先收到 设定的startcmd 语句 然后stm32 开始不断向pc机发送我们需要的hello windows语句。
由此可以表示我们程序完全成功。
参考文献
- https://www.pianshen.com/article/8285571527/
- https://blog.youkuaiyun.com/qq_47281915/article/details/121053903