打开工程模板文件夹里面的Template.ioc文件,启动CubeMX配置软件,在左侧配置类别Categories下面的Connectivity列表中的找到USART1串口,打开其配置对话框,操作界面如图1所示。
图1 USART1配置界面
在模式设置部分只有两个参数,分别说明如下:
Mode:用于设置USART的工作模式,有Asynchronous(异步)、Synchronous(同步)、Single Wire(半双工)、IrDA(红外通信)、SmartCard(智能卡)等工作模式,我们使用的是UART功能,所以此处选择异步模式Asynchronous。
Hardware Flow Control (RS232):硬件流控制,有Disable、CTS Only、RTS Only、CTS/RTS共4个选项,由于本项目并没有使用硬件流控制,所以应选择无硬件流控制Disable。
参数设置部分包括串口通信的4个基本参数和微控制器的2个扩展参数。4个基本参数说明如下:
Baud Rate:串口通信的波特率,初始化配置时只要给出具体的波特率数值即可,CubeMX会根据设置的波特率自动配置相关寄存器。常用的串口波特率有9600b/s、14400b/s、19200b/s、115200b/s、460800b/s、500000b/s等,此处保留其默认值115200b/s。
Word Length:字长(数据位+奇偶校验位),可以设置为8位或9位,这里设置为8位。
Parity:奇偶校验位,可选None(无)、Even(偶校验)、Odd(奇校验),此处设置为None。如果设置为奇校验或偶校验时,字长应设置为9位。
Stop Bits:停止位,可选1位或2位,这里设置为1位。
STM32 MCU扩展的两个参数说明如下:
Data Direction:数据方向,可选Receive and Transmit(接收和发送)、Receive Only(仅接收)、Transmit Only(仅发送)。此处设置为Receive and Transmit。
Over Sampling:过采样,可选16 Samples或8 Samples,这里设置为16 Samples。选择不同的过采样数值会影响波特率的可设置范围,而CubeMX会自动更新波特率的可设置范围。
2.3 初始化代码分析及用户程序编写
#include "usart.h"
UART_HandleTypeDef huart1;
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{ Error_Handler(); }
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/** USART1 GPIO Configuration PA9--> USART1_TX PA10--> USART1_RX **/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}
2.串口回调函数实现
当我们在CubeMX中启用USART1外设并使能其全局中断,则在stm32f4xx_it.c文件中会生成USART1的中断服务程序框架USART1_IRQHandler(),在其中仅调用串口通用处理函数HAL_UART_IRQHandler(),对各种中断事件进行判断,并调用各自的回调函数。对于本项目来说,当串口接收数据完成时会调用HAL_UART_RxCpltCallback()回调函数,依然选择在main.c中重新实现这一回调函数,其参考代码如下:
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
static uint8_t k=0;
if(huart->Instance==USART1)
{
k++;
switch (k%7)
{
case 1:
year= RxData;
break;
case 2:
month=RxData;
break;
case 3:
day= RxData;
break;
case 4:
WeekIndex=RxData;
break;
case 5:
hour= RxData;
break;
case 6:
minute=RxData;
break;
case 0:
second= RxData;
DateFresh=1; //更新日期、星期标志
break;
default:
break;
}
HAL_UART_Transmit(&huart1,&k,1,100);
HAL_UART_Receive_IT(&huart1,&RxData,1);
}
}
/* USER CODE END 4 */
在上述代码中,首先定义了一个静态变量k,用于记录串口中断发生的次数,随后根据数据到来的次序提取数值,另外为了不对日期和星期数据反复更新,还设置了一个全部数据接收完成标志位。最后将接收到的数据个数以阻塞方式回传上位机,并重新启动串口数据接收。
3.用户主程序编写
用户编写主程序参考代码如下:
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "fsmc.h"
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "lcd.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
uint8_t hour=9,minute=30,second=25,ShowBuff[6],RxData=0;
uint8_t year=22,month=5,day=9,WeekIndex=1,DateFresh=0,TempStr[30]; //初始时间
char *WeekName[7]={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday" };
/* USER CODE END PV */
void SystemClock_Config(void);
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t i;
/* USER CODE END 1 */
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_FSMC_Init();
MX_TIM6_Init();
MX_TIM7_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN WHILE */
LCD_Init();
HAL_TIM_Base_Start_IT(&htim6);
HAL_TIM_Base_Start_IT(&htim7);
HAL_UART_Receive_IT(&huart1,&RxData,1); //以中断方式接收1个字节数据
for(i=0;i<5;i++) //清屏0~4行
{ LCD_ShowString(0,24*i,(u8 *)" ",BLUE,WHITE,24,0); }
LCD_ShowString(4,24*1,(u8 *)"USART Between PC and STM32",BLUE,WHITE,24,0);
for(i=5;i<10;i++) //清屏5~9行
{ LCD_ShowString(0,24*i,(u8 *)" ",WHITE,BLUE,24,0); }
sprintf(TempStr,"20%02d-%02d-%02d %s",year,month,day,WeekName[WeekIndex-1]);
LCD_ShowString(40,24*7,TempStr,WHITE,BLUE,24,0);
while (1)
{
if(DateFresh==1)
{
sprintf(TempStr,"20%02d-%02d-%02d %s",year,month,day,WeekName[WeekIndex-1]);
LCD_ShowString(40,24*7,TempStr,WHITE,BLUE,24,0); //将日期和星期显示于LCD
DateFresh=0;
}
sprintf((char *)TempStr," %02d:%02d:%02d ",hour,minute,second);
LCD_ShowString(32*2+16,24*2+16,TempStr,RED,GREEN,32,0); //将时间显示于LCD
/* USER CODE END WHILE */
}
}
本项目是在第9章基本定时器应用的基础上修改的,在保持时间数码管显示方式不变的基础上,将时间、日期、星期均显示于LCD,时间实时更新,日期和星期仅当串口接收到全部7个数据才进行更新。
程序首先增加定义了本项需要用到的变量,随后对所有外设进行初始化,紧接着调用串口接收单字节函数,启动数据接收工作,数据提取和处理是在回调函数中完成的。最后在主程序中进行显示信息处理。
在上述代码中多次使用了sprintf函数,其用法十分类似于printf函数,只不过printf是将字符串输出到标准设备显示器,而sprintf函数是将字符串输出到其第一个参数所指定的字符串指针。使用上述两个函数均需要包含stdio.h文件。 |
2.4 下载调试
首先在VB6.0软件中新建一个窗体Form1,并在窗体上添加串口通信控件MSComm1,串口组合列表框cboPort,状态指示图标shpCOM,串口状态标签cmdOpenCom,当前时间标签Label10,文本框Text1~Text7,发送数据标签Label2,接收数据标签Label3,退出按钮Command2,发送时间按钮Command4,定时器Timer1以及多个信息指示标签,创建完成界面如图3所示。
图3 串口通信窗体创建
(1)在微软官网下载或从本书配套资源获取控件mscomm32.ocx。
(2)将控件放到相应文件夹内,32位系统路径为:C:\Windows\System32,64位系统路径为:C:\Windows\Syswow64。
(3)然后在对应目录下找到cmd.exe文件,单击鼠标右键,以管理员身份运行(关键),在命令窗口输入regsvr32 mscomm32.ocx。
2.MCU与PC机通信
打开开发板电源,下载串口通信程序,并复位运行。在PC机上双击运行“单片机与PC机通信.exe”程序,操作界面如图4所示,单击“发送时间”按钮,Windows系统当前日期、星期和时间共7个数据发送至微控制器。MCU收到上位机数据之后,将时间信息动态显示于数码管和LCD,日期和星期信息更新于LCD显示屏。通信软件支持手动选择串口,设置波特率,同时提供了一个附加功能,即将系统当前日期、星期和时间信息实时转化为十六进制。
4.2 串口助手调试
事实上,很多同学可能没有掌握一门可视化编程语言,解决这一问题较好的方法是使用串口调试助手,需要说明的是各种版本串口调试助手略有差别,但大同小异,可以举一反三。
具体调试步骤如下:
(1)打开开发板电源,运行微控制器程序
(2)运行串口调试助手,并打开串口通信设置对话框,设置结果如图5所示,本项目全部采用默认设置,该步骤也可以跳过。
图5 串口通信设置
(3)串口调试选项设置,设置结果如图6所示,其中重要选项如红色框线所示。
图6 串口调试选项设置
图7 串口收发数据界面
本节实验所需的上位机通信软件及所有配套资源可以通过如下方二维码获取:
5 使用教材
6 教程下载