这里分享一下我在调试程序时常用的方法(一):串口调试
(这部分代码只是作为调试的一种手段,只在需要测试的地方和不影响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__*/