一、功能需求分析
在中断机制实现按键检测的案例之后,我们介绍串行通信,而使用串行通信的方式采用中断方式实现,即在完成发送或者接收数据后,会触发串行通信的发送和接收callback函数,执行回调函数功能。
在单片机通信方式中,通常有两种,串行通信和并行通信。
串行通信即一次只发送一位数据,多次发送完成。
并行通信即一次发送多位数据,一次完成。
下面有一张关于两种通信方式的基础知识点,概括很全面,大家可以自己理解。
需求分析:
- 仿真方式,实现COM1和COM2的通信,COM2发送命令,COM1执行命令并返回结果;
- 接线方式,COM1连接STM32,RXD和TXD并联,STM32使用第一组串口线,PA9(TXD)PA10(RXD);PA0-PA2分别连接LED1-LED3;
- 通信协议:
COM2发送字符a,LED1熄灭;
COM2发送字符b,LED1点亮;
COM2发送字符c,LED2熄灭;
COM2发送字符d,LED2点亮;
COM2发送字符e,LED3熄灭;
COM2发送字符f,LED3点亮;
使用到的工具:
工具软件 | 功能 |
---|---|
Proteus | 绘制原理图 |
STM32CubeMX | 图形化配置生成MDK项目 |
MDK | 编写下位机代码 |
XCOM | 串口调试住手 |
VSPD | 虚拟串口驱动 |
用到的工具比较多,这里梳理一下思路:
本案例的功能是通过串口通信实现命令下发和命令执行以及结果反馈的功能。
具体实现选择的是通过单个字符,比如‘a’命令,点亮LED1;
但是如果想实现串口通信,需要提供两个物理串口,而且是不同PC机的,同一台PC机无法实现自己的两个串口通信。
所以,这里使用到了VSPD,它可以将一台PC的两个端口虚拟连接,实现数据收发,解决了我们硬件的限制。
二、Proteus绘制电路原理图
绘制电路原理图的步骤:创建画布=》芯片选型及放置=》元器件选型及放置=》连接电路=》修改元器件参数=》仿真运行。
下图为所需元器件清单,其中比较重要的是COMPIM,它可以将Proteus中的虚拟元器件连接到PC机实际的串口,这个元器件是我们实现仿真串行通信的关键。
下图为电路原理图。
绘制完成后,双击COMPIM配置串行通信参数,注意,这个地方配置的参数,需要我们在CubeMX中配置相同参数,而且在串口助手测试时,也是用相同参数,即8N1+115200。
三、STMCubeMX 配置引脚及模式,生成代码
接下来,根据原理图绘制,创建CubeMX项目,配置引脚及工作模式,生成MDK项目代码。
创建项目,在Pinout配置模块,点击PA0,选择GPIO_Output推挽输出模式,同理,配置PA1、PA2。
配置串口引脚及参数,PA9和PA10配置成TX和RX模式,在连接选项处,配置通信模式为asynchronous异步通信模式,8N1+115200的串口通信参数。
在clock单元,配置系统时钟为72MHz。
在Project单元,填写项目名称、保存路径、IDE和版本。
在 code generator中,配置添加库的方式为所需库,用户代码在每次项目重新生成时保留。
配置完成,通过以上步骤,完成了2个LED引脚的模式配置及时钟配置,接下来,点击GENERATE,生成项目代码。
找到生成路径,可以看到项目目录文件。
四、MDK打开生成项目,编写HAL库的功能代码
从上面步骤中,生成了MDK项目。
在MDK-ARM目录中,找到项目快捷方式(.uvprojx),打开项目。
找到main.c文件,添加两部分代码。
在此之前,查阅API手册,解释下面的函数。
HAL_UART_Transmit(&huart1, (uint8_t )pCmd, len, 0xFFFF);
函数功能为发送串口数据,里面四个参数,&huart1为串口的指针, (uint8_t )pCmd发送数据数组首地址,len数据长度,超市时间0xFFFF。
HAL_UART_Receive_IT(&huart1, (uint8_t )&Rx_Byte, 1);
函数功能为在非阻塞状态下接收串口数据,里面三个参数,串口指针,接收数组首地址,数据大小。
1. 用户变量声明
/ Private variables ---------------------------------------------------------/
/ USER CODE BEGIN PV /
uint8_t Rx_Byte;
uint8_t Rx_Buff[256];
uint8_t Rx_Count;
/ USER CODE END PV */
2. 串口接收中断回调函数
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
unsigned char *pCmd = NULL;
int len = 0;
UNUSED(huart);
switch(Rx_Byte)
{
case 'a':
pCmd = "command a\r\n";
len = strlen(pCmd);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
break;
case 'b':
pCmd = "command b\r\n";
len = strlen(pCmd);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
break;
case 'c':
pCmd = "command c\r\n";
len = strlen(pCmd);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
break;
case 'd':
pCmd = "command d\r\n";
len = strlen(pCmd);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
break;
case 'e':
pCmd = "command e\r\n";
len = strlen(pCmd);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
break;
case 'f':
pCmd = "command f\r\n";
len = strlen(pCmd);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
break;
default:
pCmd = "command cmd\r\n";
len = strlen(pCmd);
break;
}
HAL_UART_Transmit(&huart1, (uint8_t *)pCmd, len, 0xFFFF);
HAL_UART_Receive_IT(&huart1, (uint8_t *)&Rx_Byte, 1);
}
/* USER CODE END 4 */
在项目中勾选生成HEX选项,HEX文件就是MDK编译生成的十六进制文件,作为烧录到开发板的源程序文件使用,当然,这里我们使用仿真,在Proteus中加载HEX即可。
点击编译程序,生成HEX文件。在编译窗口显示生成了以下信息,则编译成功,保证 0 errors再进行下一步。
五、运行仿真程序,调试代码
在Proteus中,双击芯片,选择加载程序路径。
01_LED\LED-MDK\MDK-ARM\LED-MDK
上面是我的项目的HEX文件目录路径。
测试步骤略显复杂,需要一点耐心:
- 使用VPSD工具COM1和COM2配对,这样就可以用XCOM和Proteus来模拟两个串口了。
2. 打开XCOM串口助手,配置串口参数,打开COM2。
3. 打开Proteus,启动仿真开始测试。
可以看到,六个字符发送后,会对应控制LED状态,并返回执行信息,功能正常。
代码链接:STM32-05基于HAL库(CubeMX+MDK+Proteus)串行通信案例(中断方式接收命令)
至此,我们已经完成了STM32的串口通信案例,后面,会给大家介绍更多的功能。