打印
[技术问答]

实现printf

[复制链接]
1005|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
minzisc|  楼主 | 2023-5-21 15:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


#define va_start(ap, v) ap = (va_list)&v  // 把ap指向第一个固定参数v
#define va_arg(ap, t) *((t*)(ap += 4))          // ap指向下一个参数并返回其值
#define va_end(ap) ap = NULL                  // 清除ap

/* 将整型转换成字符(integer to ascii) */
static void itoa(uint32_t value, char** buf_ptr_addr, uint8_t base) {
   uint32_t m = value % base;            // 求模,最先掉下来的是最低位   
   uint32_t i = value / base;            // 取整
   if (i) {                            // 如果倍数不为0则递归调用。
      itoa(i, buf_ptr_addr, base);
   }
   if (m < 10) {      // 如果余数是0~9
      *((*buf_ptr_addr)++) = m + '0';          // 将数字0~9转换为字符'0'~'9'
   } else {              // 否则余数是A~F
      *((*buf_ptr_addr)++) = m - 10 + 'A'; // 将数字A~F转换为字符'A'~'F'
   }
}

/* 将参数ap按照格式format输出到字符串str,并返回替换后str长度 */
uint32_t vsprintf(char* str, const char* format, va_list ap) {
   char* buf_ptr = str;
   const char* index_ptr = format;
   char index_char = *index_ptr;
   int32_t arg_int;
   char* arg_str;
   while(index_char) {
      if (index_char != '%') {
         *(buf_ptr++) = index_char;
         index_char = *(++index_ptr);
         continue;
      }
      index_char = *(++index_ptr);         // 得到%后面的字符
      switch(index_char) {
         case 's':
            arg_str = va_arg(ap, char*);
            strcpy(buf_ptr, arg_str);
            buf_ptr += strlen(arg_str);
            index_char = *(++index_ptr);
            break;

         case 'c':
            *(buf_ptr++) = va_arg(ap, char);
            index_char = *(++index_ptr);
            break;

         case 'd':
            arg_int = va_arg(ap, int);
      /* 若是负数, 将其转为正数后,再正数前面输出个负号'-'. */
            if (arg_int < 0) {
               arg_int = 0 - arg_int;
               *buf_ptr++ = '-';
            }
            itoa(arg_int, &buf_ptr, 10);
            index_char = *(++index_ptr);
            break;

         case 'x':
            arg_int = va_arg(ap, int);
            itoa(arg_int, &buf_ptr, 16);
            index_char = *(++index_ptr); // 跳过格式字符并更新index_char
            break;
      }
   }
   return strlen(str);
}

/* 格式化输出字符串format */
uint32_t printf(const char* format, ...) {
   va_list args;
   va_start(args, format);               // 使args指向format
   char buf[1024] = {0};               // 用于存储拼接后的字符串
   vsprintf(buf, format, args);
   va_end(args);
   return write(buf);
}


使用特权

评论回复
沙发
单片小菜| | 2023-5-22 10:21 | 只看该作者
这个代码,写的漂亮

使用特权

评论回复
板凳
yorkbarney| | 2023-6-10 09:40 | 只看该作者
如何写出多串口共用printf函数语句

使用特权

评论回复
地板
houjiakai| | 2023-6-10 09:54 | 只看该作者
用printf打印usart串口数据

使用特权

评论回复
5
lzmm| | 2023-6-10 10:02 | 只看该作者
重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口

使用特权

评论回复
6
phoenixwhite| | 2023-6-10 10:38 | 只看该作者
习惯使用printf这一函数进行数据输出和调试

使用特权

评论回复
7
sdlls| | 2023-6-10 10:43 | 只看该作者
使用微库,因为使用微库的话,不会使用半主机模式

使用特权

评论回复
8
pmp| | 2023-6-10 12:13 | 只看该作者
使用jlink ,代替串口printf输出

使用特权

评论回复
9
chenci2013| | 2023-6-10 12:38 | 只看该作者
如果你用的是arm芯片的单片机,重定向函数

使用特权

评论回复
10
benjaminka| | 2023-6-10 13:08 | 只看该作者
在使用printf之前添加重定向代码  

使用特权

评论回复
11
robertesth| | 2023-6-10 13:23 | 只看该作者
关闭半主机模式,并重定向printf #pragmaimport(__use_no_semihosting)//不使用半主机模式

使用特权

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

本版积分规则

61

主题

5402

帖子

4

粉丝