KEIL 增加自定义的DEBUG_PRINTF , 使用WATCH窗口显示

概述

使用M0内核的单片机,无法使用J-LINK的RTT功能,产品又没有对外的串口可以用,调试起来很不方便,自己想了个歪脑子,来实现打印DEBUG信息的功能,具体实现效果如下图所示。
在这里插入图片描述

使用说明

包含DEBUG.h文件之后
使用DEBUG_PRINTF打印想要显示的内容,
然后将DEBUG_PRINTF_BUF数组添加到watch窗口中
打印的数据会在watch串口显示

//显示记录的条数
#define QUEUE_DEPTH 20

//每条记录的最大长度
#define QUEUE_BUF_SIZE 50

正式发布的时候,注释掉这个
#define BOOT_DEBUG

DEBUG.c

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

#ifdef BOOT_DEBUG

typedef char *  va_list;
#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) 
#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) ) 
#define va_arg(ap,t)    ( *(t *)( ap=ap + _INTSIZEOF(t), ap- _INTSIZEOF(t)) ) 
#define va_end(ap)      ( ap = (va_list)0 )


#define QUEUE_DEPTH 20
#define QUEUE_BUF_SIZE 50
char DEBUG_PRINTF_BUF[QUEUE_DEPTH][QUEUE_BUF_SIZE] = {0};
/*
 *  value: 要转换的整数,string: 转换后的字符串,radix: 转换进制数,如2,8,10,16 进制等。
 */
static char* itoa(int num,char* str,int radix)
{
	char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//索引表
	unsigned unum;//存放要转换的整数的绝对值,转换的整数可能是负数
	int i=0,j,k;//i用来指示设置字符串相应位,转换之后i其实就是字符串的长度;转换后顺序是逆序的,有正负的情况,k用来指示调整顺序的开始位置;j用来指示调整顺序时的交换。
 
	//获取要转换的整数的绝对值
	if(radix==10&&num<0)//要转换成十进制数并且是负数
	{
		unum=(unsigned)-num;//将num的绝对值赋给unum
		str[i++]='-';//在字符串最前面设置为'-'号,并且索引加1
	}
	else unum=(unsigned)num;//若是num为正,直接赋值给unum
 
	//转换部分,注意转换后是逆序的
	do
	{
		str[i++]=index[unum%(unsigned)radix];//取unum的最后一位,并设置为str对应位,指示索引加1
		unum/=radix;//unum去掉最后一位
 
	}while(unum);//直至unum为0退出循环
 
	str[i]='\0';//在字符串最后添加'\0'字符,c语言字符串以'\0'结束。
 
	//将顺序调整过来
	if(str[0]=='-') k=1;//如果是负数,符号不用调整,从符号后面开始调整
	else k=0;//不是负数,全部都要调整
 
	char temp;//临时变量,交换两个值时用到
	for(j=k;j<=(i-1)/2;j++)//头尾一一对称交换,i其实就是字符串的长度,索引最大值比长度少1
	{
		temp=str[j];//头部赋值给临时变量
		str[j]=str[i-1+k-j];//尾部赋值给头部
		str[i-1+k-j]=temp;//将临时变量的值(其实就是之前的头部值)赋给尾部
	}
 
	return str;//返回转换后的字符串
}


/*
 *  str传入的数组基础地址,offset数组的偏移,c传入的字符
 *  返回填入字符后的偏移值
 */
static uint8_t load_c(char *str,uint8_t offset ,char c)
{
	* (str + offset) = c;
	offset ++;
	return offset;
}
/*
 *  str传入的数组基础地址,offset数组的偏移,data传入的数字
 *  返回填入字符后的偏移值
 */
static uint8_t load_data(char *str,uint8_t offset ,uint32_t data,uint8_t mode)
{
  char datastr[17] = {0};
	itoa(data,datastr,mode);
	uint8_t len = strlen(datastr);
	
	for(uint8_t i = 0 ; i < len ; i ++)
	{
		* (str + offset) = datastr[i];
		offset ++;
	}
	return offset;
}
/*
 *  str传入的数组基础地址,offset数组的偏移,data传入的数字
 *  返回填入字符后的偏移值
 *  与load_data不同的是,这个函数会吧数字保留一位小数装填
 */
static uint8_t load_fdata(char *str,uint8_t offset ,uint32_t data)
{
  char datastr[17] = {0};
	itoa(data,datastr,10);
	uint8_t len = strlen(datastr);
	if(len == 1)
	{
		* (str + offset++) = datastr[0]; 
		* (str + offset++) = '.';
		* (str + offset++) = '0';
	}
	else if(len > 1)
	{
			for(uint8_t i = 0 ; i < len ; i ++)
			{
				* (str + offset++) = datastr[i];
				if( i == (len - 2))
				 * (str + offset++)  = '.';
			}
	
	}
  return offset;
}

/*
 *  str传入的数组基础地址,offset数组的偏移,addstr传入的字符串
 *  返回填入字符后的偏移值
 */
static uint8_t load_string(char *str,uint8_t offset ,char *addstr)
{
	uint8_t len = strlen(addstr);
	for(uint8_t i = 0 ; i < len ; i ++)
	{
		* (str + offset) = addstr[i];
		offset ++;
	}
	return offset;
	
}
#endif
//将DEBUG信息打印在DEBUG_PRINTF_BUF中,通过WATCH信息查看
#ifdef BOOT_DEBUG
void DEBUG_PRINTF(char * fmt,...)
{
	

	
	char str[QUEUE_BUF_SIZE + 1] = {0};
	uint8_t offset = 0;
	va_list ap;
	va_start(ap, fmt); 

	
	 for(; *fmt != '\0'; fmt++)
	 {
				if (*fmt != '%') {
					offset = load_c(str,offset,*fmt);
					continue;
				}
				
			 fmt++;
				
			switch(*fmt)
			{
				case 'u':
					offset = load_data(str,offset ,va_arg(ap, unsigned int),10);
					break;
				case 's':
					offset = load_string(str,offset ,va_arg(ap, char *));
					break;
				case 'f':
					offset = load_fdata(str,offset ,va_arg(ap, unsigned int));
					break;
				default:
					offset = load_c(str,offset,*fmt);
					break;
			}
			
			if(offset >= QUEUE_BUF_SIZE)
				break;
	}
	 
	va_end(ap);
	

	
	static uint8_t i = 0 ; 
		
	
	strcpy(DEBUG_PRINTF_BUF[i],str);
	
	if(i < (QUEUE_DEPTH - 1))
		i++;
	else
		i = 0;
	
	memset(DEBUG_PRINTF_BUF[i],0,QUEUE_BUF_SIZE);

	
}

#endif



DEBUG.h

#ifndef _DEBUG_H
#define _DEBUG_H

typedef unsigned          char uint8_t;
typedef unsigned short     int uint16_t;
typedef unsigned           int uint32_t;


#define BOOT_DEBUG

#ifdef BOOT_DEBUG
void DEBUG_PRINTF(char * fmt,...);
#else
#define DEBUG_PRINTF(x,...) ;
#endif

#endif




猜你喜欢

转载自blog.csdn.net/tiantangmoke/article/details/103240342
今日推荐