前置条件
- 已创建STM32工程(本文以STM32F103ZE系列芯片为例)
- 已完成USART1的驱动程序编写(包括printf的硬件重定向)
代码示例
usart.h
#ifndef _USART_H_
#define _USART_H_
#include "stm32f10x.h"
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
void Usart_Init(void); // 对外提供的API接口
void Usart_Pin_Init(void); // 硬件端口配置(引脚输入输出方式)
void Usart_Port_Init(void); // 串口外设配置(波特率等)
#endif
usart.c
#include "usart.h"
// serial port init
void Usart_Init(void) {
Usart_Pin_Init();
Usart_Port_Init();
USART_ClearFlag(USART1, USART_FLAG_TC);
return;
}
void Usart_Pin_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // open clock
// USART1_TX,推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// USART1_RX,浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
return;
}
void Usart_Port_Init(void) {
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
USART_InitStructure.USART_BaudRate = 9600; // 波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位
USART_InitStructure.USART_Parity = USART_Parity_No; // 校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控
USART_InitStructure.USART_Mode = USART_Mode_Tx; // 收发模式
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
return;
}
// 覆盖(重写)fputc函数
PUTCHAR_PROTOTYPE {
USART_SendData(USART1, (uint8_t) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {
}
return ch;
}
main.c
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdio.h>
#include "usart.h"
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void) {
Usart_Init(); // Usart Init
// print something
printf("1. Hello, I am USART1\r\n");
printf("2. Hello, I am USART1\r\n");
printf("3. Hello, I am USART1\r\n");
printf("4. Hello, I am USART1\r\n");
printf("5. Hello, I am USART1\r\n");
return 0;
}
详情
编译通过,启动调试
打开工具栏 >> Serial Windows >> USART #1
右下角出现串口调试窗口
打开main.c,将光标定位在如图所示位置,使用调试方式 >> 运行到光标所在代码行
PS:若采用单步调试等方式,需要等待引导区的代码执行完毕,效率较低,所以此处一开始就强制调试运行到代码观察点。
等待代码执行至光标处,使用Step Over调试,逐次运行打印语句,同时观察USART1监视窗口
如下图可见,已运行的3条语句的打印结果出现在串口监视器中
问题与调试
问题描述:笔者仿真调试时字符串可以打印在调试窗口,但是把编译生成的.hex文件烧写到物理开发板之后,发现无法与上位机建立USART连接,即字符串发送不过去,解决方法如下:
点击魔棒工具,点击Target,勾选Use MicroLIB
原理与ARM的半主机模式有关,笔者后续会有专门的博客来讨论。
串口映射
下面演示一种把Target驱动的仿真串口映射到主机的物理串口(或软件虚拟串口)的方法,以方便调试。
首先进入调试模式,点击标记1的调试按钮进入调试模式,点击调试工具条标记2处的命令行按钮打开标记3所示的命令行窗口
依次输入以下两条命令:
1. MODE COM1 9600, n, 8, 1
-
2. ASSIGN COM1 <S1IN> S1OUT
PS:
- 命令1和命令2的COM1指的是主机的串口
- 命令2的S1IN和S1OUT的指的是Tartget的USART1串口
-
此方式与调试器自带的USRT1监视窗口是并行的,互不影响
至此结束。
声明
商业开发请购买正版软件和服务。