keil使用虚拟的调试串口给调试助手发送数据

[1]下载: https://sourceforge.net/projects/com0com/

[2]安装com0com

[3]安装完成,打开设备管理器,如下图所示,没有黄色感叹号
        安装之后有人会出现带黄色感叹号这种,操作系统设置-高级启动-禁用强制驱动程序签名就可以,或者找其他博主的解决方案,因为我的电脑没出现,所以没办法验证方法的可行性。

在我的电脑里面看到com7,com8

[4]打开两个调试助手,第一个选择com7,第二个选择com8

[5]第一个调试助手发送,第二个调试助手收到消息

[6]关掉两个调试助手

[7]创建一个空文件usart_debug.ini-->输入内容:
MODE   COM8   9600,  0,  8,  1
ASSIGN COM8 <S1IN> S1OUT

[8]打开keil
[9]点击魔法棒-->Debug-->(*)Use Simulator-->[*]Limit Speed to Real-Time

[*]Load Speed to Real-Time  [*]Run to main()
-->Initialization File:...,点击三个点-->选择usart_debug.ini-->OK

[10]假设你原来重定向的文件名usart.c,注释掉原来的内容,添加下面的内容,如下:
#if 0
extern UART_HandleTypeDef huart2;

#define DEBUG_SERIAL_HANDLE huart2
#define DEBUG_SERIAL_NUMBER USART2

//重定向
int fputc(int ch, FILE *f)
{
    HAL_UART_Transmit(&DEBUG_SERIAL_HANDLE, (uint8_t *)&ch, 1, 1000);
    return ch;
}
int fgetc(FILE *f)
{
    uint8_t ch;
    while(HAL_UART_Receive(&DEBUG_SERIAL_HANDLE, (uint8_t *)&ch, 1, 0xffff) != HAL_OK){}
    return (int)ch;
}

#endif


#include <stdio.h>
#include <string.h>

// 1. 彻底关闭半主机模式(兼容新旧编译器)
#define __NO_SEMIHOSTING 1
#pragma import(__use_no_semihosting)

// 2. 定义标准输入输出流(输入必须定义__stdin)
struct __FILE {
    int handle;
};
FILE __stdout;  // 标准输出(若需同时输出可保留)
FILE __stdin;   // 标准输入(核心:对应输入函数)

// 3. 补充半主机相关空函数(避免链接错误)
void _sys_exit(int x) { x = x; }
int _sys_open(const char *name, int mode) { return 0; }
void _ttywrch(int ch) { (void)ch; }

// 4. 重定向fputc(可选:若需同时输出调试信息,保留此函数)
int fputc(int ch, FILE *f) {
    volatile uint32_t *USART1_SR = (volatile uint32_t *)(0x40013800);
    volatile uint8_t *USART1_DR = (volatile uint8_t *)(0x40013804);
    uint32_t timeout = 100000;
    
    while ( ((*USART1_SR) & 0x40) == 0 && timeout-- > 0 );
    if (timeout == 0) return -1;
    
    *USART1_DR = (uint8_t)ch;
    return ch;
}

// 5. 核心:重定向fgetc函数(从Keil内部UART #1读取字符,对应真实串口数据)
int fgetc(FILE *f) {
    // 明确定义USART1寄存器地址(STM32F103 USART1)
    volatile uint32_t *USART1_SR = (volatile uint32_t *)(0x40013800); // 状态寄存器
    volatile uint8_t *USART1_DR = (volatile uint8_t *)(0x40013804);   // 数据寄存器
    uint32_t timeout = 500000; // 延长超时,确保能捕获到输入数据
    uint8_t recv_ch = 0;
    
    // 等待RXNE位(bit5)置1:表示接收数据寄存器非空(有数据可读)
    while ( ((*USART1_SR) & 0x20) == 0 && timeout-- > 0 ) {
        // 空循环等待,直到收到数据或超时
    }
    
    // 若超时,返回0(可自定义错误标识);若收到数据,读取DR寄存器
    if (timeout > 0) {
        recv_ch = *USART1_DR; // 读取接收到的字符
        // 可选:回显字符(发送到输出窗口,便于确认接收成功)
        fputc(recv_ch, stdout);
    }
    
    return (int)recv_ch;
}

[11]打开调试助手,选择com7

[12]keil进入调试状态,执行printf函数,发现已经输出到调试助手了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值