在 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 处理可变参数。
|