打印
[牛人杂谈]

如何自己实现一个类似printf的函数

[复制链接]
190|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
598330983|  楼主 | 2025-2-15 10:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在 ARM 单片机上实现一个简单的 printf 函数,可以通过自定义 putchar 或 fputc 函数来重定向输出。以下是一个简单的实现示例,假设你将输出重定向到串口(UART)。
1. 实现 putchar 函数
首先,实现一个简单的 putchar 函数,用于将字符发送到串口。

#include "stm32f4xx_hal.h"  // 根据你的芯片型号包含对应的 HAL 库

// 实现 putchar 函数
int putchar(int ch) {
    // 发送字符到串口
    HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}
2. 实现简单的 printf 函数
接下来,实现一个简单的 printf 函数,支持基本的格式(如 %d, %s, %c, %x 等)。

#include <stdarg.h>  // 用于可变参数处理

// 简单的 printf 函数实现
void my_printf(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);  // 初始化可变参数列表

    while (*fmt) {
        if (*fmt == '%') {
            fmt++;  // 跳过 '%'
            switch (*fmt) {
                case 'd': {  // 处理整数
                    int val = va_arg(args, int);
                    if (val < 0) {
                        putchar('-');
                        val = -val;
                    }
                    char buffer[10];
                    int i = 0;
                    do {
                        buffer[i++] = (val % 10) + '0';
                        val /= 10;
                    } while (val > 0);
                    while (i > 0) {
                        putchar(buffer[--i]);
                    }
                    break;
                }
                case 's': {  // 处理字符串
                    char *str = va_arg(args, char *);
                    while (*str) {
                        putchar(*str++);
                    }
                    break;
                }
                case 'c': {  // 处理字符
                    char ch = va_arg(args, int);
                    putchar(ch);
                    break;
                }
                case 'x': {  // 处理十六进制
                    unsigned int val = va_arg(args, unsigned int);
                    char buffer[8];
                    int i = 0;
                    do {
                        int digit = val % 16;
                        buffer[i++] = (digit < 10) ? (digit + '0') : (digit - 10 + 'A');
                        val /= 16;
                    } while (val > 0);
                    while (i < 8) {
                        buffer[i++] = '0';  // 补齐 8 位
                    }
                    while (i > 0) {
                        putchar(buffer[--i]);
                    }
                    break;
                }
                default:
                    putchar(*fmt);  // 未知格式,直接输出
                    break;
            }
        } else {
            putchar(*fmt);  // 普通字符,直接输出
        }
        fmt++;  // 移动到下一个字符
    }

    va_end(args);  // 结束可变参数处理
}
3. 使用示例
在你的主程序中,可以像标准 printf 一样使用 my_printf 函数。

int main(void) {
    // 初始化 HAL 库和串口
    HAL_Init();
    SystemClock_Config();
    MX_USART2_UART_Init();

    // 使用自定义的 printf 函数
    my_printf("Hello, World!\n");
    my_printf("Integer: %d\n", 1234);
    my_printf("String: %s\n", "ARM Cortex-M");
    my_printf("Character: %c\n", 'A');
    my_printf("Hexadecimal: 0x%x\n", 0xABCD);

    while (1) {
        // 主循环
    }
}
4. 代码说明
putchar: 将字符发送到串口。

my_printf: 支持 %d(整数)、%s(字符串)、%c(字符)和 %x(十六进制)等基本格式。

可变参数处理: 使用 va_list、va_start、va_arg 和 va_end 处理可变参数。


使用特权

评论回复
沙发
gaoyang9992006| | 2025-2-16 17:30 | 只看该作者
用自己实现的可以解决内存。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

253

主题

5464

帖子

22

粉丝