Board logo

标题: 一个调试输出函数(KEIL,LPC21XX) [打印本页]

作者: lenglx    时间: 2006-7-5 17:17     标题: 一个调试输出函数(KEIL,LPC21XX)

如果你想输出一些调试信息,怎么办?
一般使用的是printf(..)函数.
但有几个缺点:
1.你只是想调试时输出信息而已,做成release版本时,不需要输出调试信息.
这样势必要更改源程序,不方便.
2.printf(..)使用的函数putchar(..)一般要等待UART发送寄存器空时,才发送数据.
采用的查询-等待的方式,在某些场合会阻塞主程序的运行.

所以,我把putchar(..)函数改了下,采用中断的方式.

使用方法:
如果在调试状态: 定义1个宏 __TRACE__.
如果要生产realease版本,去掉这个宏.

在主程序开始,调用InitTrace();
之后,在要输出调试信息的地方,用如trace("output info : %d",n);的语句就可以了.
#include "trace.h"
void main()
{
 int i;
 InitTrace();
 trace("************************\r");
 for(i=0; i<600; i++)
 {
  dly();
     trace("This is line: %d\r",i);
 }
}
在"trace.c"中,可以定制 串口号,波特率等等.


 


 


 



附带1个uvision下的工程.

//*********** trace.h ***************************
#ifndef __trace_header_file
#define __trace_header_file
  #ifdef __TRACE__
   extern void InitTrace(void);
 #define trace printf
  #else
    #define InitTrace()
 #define trace
  #endif
#endif

/*******************************************************************
* 文 件 名:    trace.c
*版本/时间: 
* 描    述: 
* 作    者: 
*-------------------------------------------------------------------
* 修改记录:
* 修改时间:
* 描    述:
* 修 改 人:
*******************************************************************/

//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
//  <h> 参数设定
//  <o> 使用UART
//   <0=> UART0 <1=>UART1
//  <o1> 外设频率(PCLK) (unit:Hz)
//   <1000000-60000000>
//  <o2> 通讯波特率
//   <96-115200>
//  <o3> 缓冲区大小(bytes)
//   <256=> 256 <512=> 512 <1024=>1024 <2048=>2048
//  </h>
#define __uart 1
#define Fpclk  11059200
#define __baud  115200
#define __bufsize 1024 /* 必须是2^n,如:512,1024,2048 */
 
//------------ <<< end of configuration section >>> ----------------------

typedef unsigned char  uchar;
typedef unsigned int uint;

#include <LPC213X.H>

#ifdef __TRACE__
  #if __uart != 0 && __uart != 1
    #error "must use uart0 or uart1."
  #endif

uchar __tracebuffer[__bufsize];
volatile uint first, next;

#if __uart==0
  #define UXTHR   U0THR
  #define UXLSR  U0LSR
  #define UXIIR  U0IIR
#else
  #define UXTHR  U1THR
  #define UXLSR  U1LSR
  #define UXIIR  U1IIR;
#endif

// 中断,将缓冲区中还未发送的数据发送出去.
void UartTraceIrq(void) __irq
{
 uchar c = UXIIR;
 if(first != next)
 {
  UXTHR = __tracebuffer[first];
  first ++;
  first &= (__bufsize - 1);
 }
 VICVectAddr = 0;
}

// printf(..)函数将要调用此函数,此函数将ch放入缓冲区中
int putchar (int ch) 
{  
 if(next+1 == first)
  return ch;

 __tracebuffer[next] = ch;
 next ++;
 next &= (__bufsize - 1);

 if(UXLSR & 0x40) 
 // 如果缓冲区的数据以前已经发送完了,新的数据添加到缓冲后,因中断不会产生,
 //这些新数据不会被发送,所以先发送1个字符,启动中断.
 {
  ch = __tracebuffer[first];
  first ++;
  first &= (__bufsize -1);
  UXTHR = ch;
 }
 return ch;

}

#define BAUD_DIVOR(baud) ( ((Fpclk/baud/8)%2) ? (Fpclk/baud/16+1) : (Fpclk/baud/16))
#if __uart == 0
  #define SET_BAUD(baud) U0DLM = BAUD_DIVOR(baud) / 256; \
      U0DLL = BAUD_DIVOR(baud) % 256;
#else
  #define SET_BAUD(baud) U1DLM = BAUD_DIVOR(baud) / 256; \
      U1DLL = BAUD_DIVOR(baud) % 256;
#endif

void  InitTrace (void)
{
  #if __uart == 0
 INSEL0 = (PINSEL0 & (~0x0f)) | 0x05; // set p0[1..0] for uart0
 U0LCR = 0x83;      // uart0 setting: "xxxx,n,8,1"
 SET_BAUD(__baud)    
 U0LCR = 0x03;
 U0IER = 0x02;   //  enable tx interrupt.
 VICVectAddr14 = (unsigned long)UartTraceIrq;
 VICVectCntl14 = 0x20 | 6;                   
 VICIntEnable = 1 << 6 ;
  #else
    INSEL0 = (PINSEL0 & (~0x0f0000)) | 0x050000; // set p0[9..8] for uart1
 U1LCR = 0x83;      // uart0 setting: "xxxx,n,8,1"
 SET_BAUD(__baud)    
 U1LCR = 0x03;
 U1IER = 0x02;   //  enable tx interrupt.
 VICVectAddr14 = (unsigned long)UartTraceIrq;
 VICVectCntl14 = 0x20 | 7;                   
 VICIntEnable = 1 << 7 ;
   #endif
}
#else  // #if not define __TRACE__
  #pragma WA disable = 38 /*避免编译警告--空源文件*/
#endif

[此贴子已经被作者于2006-7-5 17:17:57编辑过]






欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0