单片机程序协助调试方法(一)串口调试(持续更新中)

这里分享一下我在调试程序时常用的方法(一):串口调试

(这部分代码只是作为调试的一种手段,只在需要测试的地方和不影响MCU和控制芯片通信的地方在使用,不可随意使用,随意使用可能会因为串口传输数据而错过MCU和控制芯片的通信数据而导致通信失败或异常,我就遇到过这样的问题,一定要注意!

/*################uart.h start ################*/

#ifndef __UART_H__
#define __UART_H__

#include "common.h"

/*用于软件复位重启,在下载时很方便,可自动下载,无需手动重启,与串口调试部分无关,无需关心*/
#define USER_ISP_COMMAND  0x11
sfr IAP_CONTR = 0xc7 ;


/*****************外部接口函数******************/
extern void UartInit(void) ;
extern void UartSendChar(UB8 dataCode) ;
extern void UartSendString(const UB8 *str) ;
extern void UartSendValue(const UB8 *string,UL32 dataCode) ;
/**********************************************/

#endif  /*__UART_H__*/


/*################uart.h end################*/


/*################uart.c start ################*/

/***************************************************************************
Module	:uart.c

Purpose	:Implementation of uart module.

Version	:0.01							2014/02/03 12:00(OK)

Complier:Keil 8051 C complier V9.01

MCU		:STC12C5A60S2

Author	:yangrui

QQ		:279729201

Email	:[email protected]


Modification:
=================
	2014/04/31 08:45
	Reason:
		1.将ul2string的核心操作:
			if(dataCode)
			{
				while(dataCode)
				{
					temp[j++]=dataCode % 10+'0';
					dataCode /=10;
				}
				j-- ;
				
				for(i=0; i<= j; i++)
				{
					str[i]=temp[j-i];
				}
			}
			else
			{//如果值为0
				str[i++] = '0' ;
			}
				str[i]='\0';
			修改为:
				do{
					temp[j++] = dataCode %10 +'0' ;
					dataCode /=10 ;
				}while(dataCode);
				j-- ;

				for(i=0 ; i<=j ; i++)
				{
					str[i] = temp[j-i] ;
				}
				
				str[i]='\0';
			这样利用do while结构代替原来的if {while(.)..}else 的结构,更加紧凑清晰。

=================

	
=================
	2014/04/13 19:45
	Reason:
		1.添加函数static void ul2string(UL32 dataCode,char *str) 
		和void UartSendValue(const UB8 *string, dataCode)
		主要为了快速测试出变量的值。

=================

=================
	2014/03/29 13:48
	Reason:
		1.修改
		void UartSendChar(UB8 dataCode)
			{
	
				ES = 0 ;
	
				SBUF = dataCode ;
				while( !TI ) ;
				TI = 0 ;
		
				ES = 1 ;
			}
		为:
		void UartSendChar(UB8 dataCode)
		{
			bit previousStatus = ES ;
				
			ES = 0 ;
			
			SBUF = dataCode ;
			while( !TI ) ;
			TI = 0 ;
			
			ES = previousStatus ;
		}
		因为在使用本函数,并不知道是否打开了串口中断使能ES,如果直接
		像上面那样操作,可能会导致错误。所以安全的做法是,用一个变量
		保存ES的初始状态,然后使用轮询法发送完字节数据后,再还原ES的
		状态。
=================

***************************************************************************/


#include <reg52.h>
#include "common.h"
#include "uart.h"

/*外部函数在uart.h中声明,这里串口中断比较傲特殊,可以不用外部声明*/

/*****************内部函数******************/
static void ul2string(unsigned long dat,char *str)  ;
/**********************************************/

/******************************************************
Function	:UartInit
Input		:N/A
Output		:N/A
Return		:N/A
Description	:11.0592MHZ,9600KPS
Note		:注意定时器1的使用,不要产生资源竞争
******************************************************/
void UartInit(void)
{
	SCON |= 0x50 ;
	PCON  = 0x00 ;
	TMOD |= 0x20 ;
	TH1   = 0xfd ;		/*11.0592MHZ,9600kps*/
	TL1   = 0xfd ;
	TR1   = 1 ;
	ES    = 1;
	EA    = 1 ;
	
	TI=0 ;
	RI=0 ;
}

/******************************************************
Function	:UartSendChar
Input		:byte-data
Output		:N/A
Return		:N/A
Description	:串口发送字节数据
Note		:这里借助于变量previousStatus先来记住ES的值,
			然后使用轮询法发送字节数据后,再将ES还原到之
			前的状态,这里的previousStatus是非常有必要的。
******************************************************/
void UartSendChar(UB8 dataCode)
{
	bit previousStatus = ES ;
	
	ES = 0 ;
	
	SBUF = dataCode ;
	while( !TI ) ;
	TI = 0 ;
	
	ES = previousStatus ;
}

/******************************************************
Function	:UartSendString
Input		:string-data
Output		:N/A
Return		:N/A
Description	:串口发送字符串数据
Note		:可以直接使用"\n"这样的用法来换行。
******************************************************/
void UartSendString(const UB8 *str)
{	
	while(*str)
	{
		UartSendChar(*str++) ;
	}
}

/******************************************************
Function	:UartISR
Input		:N/A
Output		:N/A
Return		:N/A
Description	:串口中断服务程序
Note		:N/A
******************************************************/
void UartISR(void) interrupt 4
{
	UB8 temp ;
	
	if(TI)
	{
		TI = 0 ;
	}
	if(RI)
	{
		RI = 0 ;
		temp = SBUF ;

		/*用于软件复位重启,在下载时很方便,可自动下载,无需手动重启,与程序无关,无需关心*/
		if(temp == USER_ISP_COMMAND)
		{
			IAP_CONTR = 0x60 ;
		}
		
		/*其他操作,等待补充*/
		
	}
}

/******************************************************
Function	:ul2string
Input		:data
Output		:str
Return		:N/A
Description	:N/A
Note		:将数值转为相应的字符串。比如 4567 转为 "4567" 
******************************************************/
static void ul2string(UL32 dataCode,char *str) 
{
	char idata temp[20];
	UB8  idata i=0,j=0;

	do{
		temp[j++] = dataCode %10 +'0' ;
		dataCode /=10 ;
	}while(dataCode);
	--j ;

	for(i=0 ; i<=j ; i++)
	{
		str[i] = temp[j-i] ;
	}
	
	
	str[i]='\0';
}

/******************************************************
Function	:UartSendValue
Input		:字符串,数值(在函数内部转换为字符串)
Output		:N/A
Return		:N/A
Description	:N/A
Note		:串口打印字符串string,并将数值转换为字符串打印
			主要在打印数据时使用,例如:
			unsigned char i=4 ;
			UartSendValue("i : ", i)
			在调试数据时非常方便。
******************************************************/
void UartSendValue(const UB8 *string,UL32 dataCode)
{
	UB8  temp[20];

	UartSendString(string) ;
	
	ul2string(dataCode,temp);
	UartSendString(temp);
	
	UartSendString("\r\n");
}


/*################uart.c end################*/

补充:common.h

#ifndef __COMMON_H__
#define __COMMON_H__

typedef unsigned char UB8 ;
typedef unsigned short int UW16 ;
typedef unsigned long UL32 ;

typedef char SB8;
typedef short int SW16 ;
typedef long SL32 ;
	
#define HIGH_LEVEL 1	
#define LOW_LEVEL  0


#endif	/*__COMMON_H__*/


 

猜你喜欢

转载自blog.csdn.net/yagnruinihao/article/details/22662145