C6748_RTC

1.主函数流程

C6748_RTC

此程序的作用是实现RTC计时功能。运行程序后,依次设定小时、分钟、秒、日、月、年,程序会按照设定时间开始计时,并将实时时间打印出来。主函数如下:

intmain(void)

{

    // 初始化串口终端使用串口2

    UARTStdioInit();

 

// 打印串口终端信息

UARTPuts("Tronlong RTC Application......\r\n", -2);

 

    // 实时时钟初始化

    RTCInit();

 

    // DSP 中断初始化

    InterruptInit();

 

    // 实时时钟中断初始化

    RTCInterruptInit();

 

    // 主循环

    for(;;)

    {

 

    }

}

2.初始化串口终端

    主函数中,首先初始化串口终端,使用串口2,初始化串口终端函数UARTStdioInit可参考这里:

C6748_UART_EDMA

3.打印串口终端信息

    然后程序开始打印串口终端信息,进行提示,UARTPuts函数在demo\StarterWare\Source\StarterWare\Utils\uartStdio.c文件中,该API可参考这里:

C6748_I2C

4.实时时钟初始化

    实时时钟初始化函数RTCInit对RTC模块进行初始化,RTCInit函数如下:

voidRTCInit(void)

{

    unsignedint UserTime =0, UserCalendar =0;

 

// 禁用 RTC 寄存器写保护

RTCWriteProtectDisable(SOC_RTC_0_REGS);

 

// 软件复位并使能 RTC

RTCEnable(SOC_RTC_0_REGS);

 

// 延时最小3 32KH 时钟周期

Delay(0xFFFF);

 

UserTime =UserTimeInfoGet();

UserCalendar =UserCalendarInfoGet();

 

// 设置时间日期

RTCCalendarSet(SOC_RTC_0_REGS, UserCalendar);

RTCTimeSet(SOC_RTC_0_REGS, UserTime);

 

// 使能 32KHz 计数器

RTCRun(SOC_RTC_0_REGS);

}

该函数执行流程如下:

C6748_RTC

4.1 禁用RTC寄存器写保护

    禁用RTC寄存器写保护函数RTCWriteProtectDisable如下:

voidRTCWriteProtectDisable(unsignedint baseAdd)

{

HWREG(baseAdd + RTC_KICK0) = RTC_KICK0R_KEY;

HWREG(baseAdd + RTC_KICK1) = RTC_KICK1R_KEY;

}

将相应的**值(key0和key1)写往KICK0和KICK1寄存器,解锁对RTC寄存器的写保护。

C6748_RTC

(指南P1240)

4.2 软件复位并使能RTC

    RTC使能函数RTCEnable如下:

voidRTCEnable(unsignedint baseAdd)

{

volatileunsignedint splitPower =0;

 

if(RTC_REV_AM1808 ==RtcVersionGet())

{

splitPower = RTC_CTRL_SPLITPOWER;

HWREG(baseAdd + RTC_OSC) |= RTC_OSC_SWRESET;

}

 

HWREG(baseAdd + RTC_CTRL) &=~(RTC_CTRL_RTCDISABLE);

HWREG(baseAdd + RTC_CTRL) |= splitPower;

}

函数首先判断集成RTC的SOC是否为AM1808处理器,如果是,则设置CTRL寄存器的SPLITPOWER位为1,使能split power(RTC独立供电),同时设置OSC寄存器的SWRESET位为1,对RTC进行软件复位。这里RtcVersionGet函数返回的是1,所以将SPLITPOWER位置1,同时对RTC软件复位。

C6748_RTC

(指南P1251)

C6748_RTC

(指南P1256)

RtcVersionGet函数在Platform工程的RTC.c文件中,该函数如下:

unsignedintRtcVersionGet(void)

{

return1;

}

4.3 延时

    对RTC进行软件复位后,必须等待至少3个RTC时钟周期的延时。因此调用延时函数Delay

4.4 获取时间和日期

4.4.1 获取时间

    延时完成后,可以对RTC的寄存器进行访问了,首先要设置RTC的时间和日期,函数从串口获取要设置的时间和日期。UserTimeInfoGet函数获取RTC当前时间,UserCalendarInfoGet函数获取RTC当前日期。UserTimeInfoGet函数如下:

unsignedintUserTimeInfoGet()

{

unsignedchar hour[2] = {0}, minute[2] = {0}, second[2] = {0};

unsignedint hourTime =0, minTime =0, secTime =0;

unsignedinttime=0;

int i =0;

 

UARTPuts("\n\nEnter the time in 24 hour format.\r\n", -1);

UARTPuts("Example (hh:mm:ss) 20:15:09\r\n", -1);

 

UARTPuts("\r\nEnter Hours: \r\n", -2);

 

do

{

hour[i] =UARTGetc();

UARTPutc(hour[i]);

i++;

}while((i <2) && (hour[i-1] !='\r'));

 

UARTPuts("\r\nEnter Minutes:\r\n", -2);

i =0;

 

do

{

minute[i] =UARTGetc();

UARTPutc(minute[i]);

i++;

}while((i <2) && (minute[i-1] !='\r'));

 

UARTPuts("\r\nEnter Seconds:\r\n", -1);

i =0;

 

do

{

second[i] =UARTGetc();

UARTPutc(second[i]);

i++;

}while((i <2) && (second[i-1] !='\r'));

 

if(hour[0] !='\r')

{

hourTime = (ASCIIToInt(hour[0]) <<0x04);

if(hour[1] !='\r')

{

hourTime |=ASCIIToInt(hour[1]);

}

else

{

hourTime = hourTime >>0x04;

}

}

 

if(minute[0] !='\r')

{

minTime = (ASCIIToInt(minute[0]) <<0x04);

if(minute[1] !='\r')

{

minTime |=ASCIIToInt(minute[1]);

}

else

{

minTime = minTime >>0x04;

}

}

 

if(second[0] !='\r')

{

secTime = (ASCIIToInt(second[0]) <<0x04);

if(second[1] !='\r')

{

secTime |=ASCIIToInt(second[1]);

}

else

{

secTime = secTime >>0x04;

}

}

 

time= (hourTime << HOUR_SHIFT);

time|= (minTime << MINUTE_SHIFT);

time|= (secTime << SECOND_SHIFT);

 

returntime;

 

}

UARTGetc函数参考这篇博文:

C6748_SPI_FLASH

UARTPutc函数和UARTPuts函数参考这篇博文:

C6748_I2C

函数首先依次获取时、分、秒数据(由用户输入),然后将从串口获取的ASCII码形式的时间信息转换为整型数据。ASCII码转整型数据函数ASCIIToInt如下:

unsignedcharASCIIToInt(unsignedchar byte)

{

unsignedchar retVal =0;

 

// 数字 0-9

if((byte >=0x30) && (byte <=0x39))

{

retVal = byte -0x30;

}

 

// 字母 A-Z

elseif((byte >=0x41) && (byte <=0x46))

{

retVal = byte -0x37;

}

 

return retVal;

}

最后将时分秒(一共24位数据,各8位)一起拼接到time变量中并返回。

4.4.2 获取日期

    UserCalendarInfoGet函数获取用户设置的日期,函数如下:

unsignedintUserCalendarInfoGet()

{

unsignedint calendar =0;

unsignedchar dayOfMonth[2] = {0}, monthArr[2] = {0}, yearArr[2] = {0};

unsignedchar dotwArr[2] = {0};

unsignedint dom =0, month =0, year =0, dotw =0;

int j =0;

 

UARTPuts("\r\n\r\nEnter the calendar information.\r\n", -2);

UARTPuts("Example (DD:MM:YY) 31:03:73\r\n", -2);

 

UARTPuts("\r\nEnter the day of the month: \r\n", -2);

 

do

{

dayOfMonth[j] =UARTGetc();

UARTPutc(dayOfMonth[j]);

j++;

}while((j <2) && (dayOfMonth[j-1] !='\r'));

 

j =0;

UARTPuts("\r\nEnter the month (Jan=01, Dec=12):\r\n", -2);

 

do

{

monthArr[j] =UARTGetc();

UARTPutc(monthArr[j]);

j++;

}while((j <2) && (monthArr[j-1] !='\r'));

 

j =0;

UARTPuts("\r\nEnter the year (Ex: 2010=10, 1987=87:):\r\n", -1);

 

do

{

yearArr[j] =UARTGetc();

UARTPutc(yearArr[j]);

j++;

}while((j <2) && (yearArr[j-1] !='\r'));

 

j =0;

UARTPuts("\r\nEnter the Day of the Week (Ex:Sun=00, Sat=06):\r\n", -3);

 

do

{

dotwArr[j] =UARTGetc();

UARTPutc(dotwArr[j]);

j++;

}while((j <2) && (dotwArr[j-1] !='\r'));

 

if(dayOfMonth[0] !='\r')

{

dom = (ASCIIToInt(dayOfMonth[0]) <<0x04);

if(dayOfMonth[1] !='\r')

{

dom |=ASCIIToInt(dayOfMonth[1]);

}

else

{

dom = dom >>0x04;

}

 

}

 

if(monthArr[0] !='\r')

{

month = (ASCIIToInt(monthArr[0]) <<0x04);

if(monthArr[1] !='\r')

{

month |=ASCIIToInt(monthArr[1]);

}

else

{

month = month >>0x04;

}

}

 

if(yearArr[0] !='\r')

{

year = (ASCIIToInt(yearArr[0]) <<0x04);

if(yearArr[1] !='\r')

{

year |=ASCIIToInt(yearArr[1]);

}

else

{

year = year >>0x04;

}

}

 

if(dotwArr[0] !='\r')

{

dotw = (ASCIIToInt(dotwArr[0]) <<0x04);

if(dotwArr[1] !='\r')

{

dotw |=ASCIIToInt(dotwArr[1]);

}

else

{

dotw = dotw >>0x04;

}

}

 

calendar = dom << DAY_SHIFT;

calendar |= month << MONTH_SHIFT;

calendar |= year << YEAR_SHIFT;

calendar |= dotw;

 

UARTPuts("\r\n\r\n", -1);

 

return calendar;

}

    获取日期函数与获取时间函数基本一样,不再细述。

4.5 设置时间日期

4.5.1 设置日期

    设置RTC的时间和日期,设置日期函数RTCCalendarSet如下:

voidRTCCalendarSet(unsignedint baseAdd, unsignedint calendar)

{

 

while(IS_RTC_BUSY);

 

/* Writing to YEAR register.*/

HWREG(baseAdd + RTC_YEAR) = (calendar & YEAR_MASK) >> YEAR_SHIFT;

 

/* Writing to MONTH register.*/

HWREG(baseAdd + RTC_MONTH) = (calendar & MONTH_MASK) >> MONTH_SHIFT;

 

/* Writing to DAY register.*/

HWREG(baseAdd + RTC_DAY) = (calendar & DAY_MASK) >> DAY_SHIFT;

 

/* Writing to DOTW register.*/

HWREG(baseAdd + RTC_DOTW) = (calendar & DOTW_MASK);

 

}

函数首先判断STATUS寄存器的BUSY位是否为1,如果是,则RTC正忙,等待RTC为free再往下执行。

C6748_RTC

(指南P1252)

从calender变量中分别提取出年、月、日信息,对YEAR、MONTH、DAY寄存器进行设置,并设置DOTW寄存器,设置日期是星期几。这四个寄存器都是以BCD码的形式存储的。

C6748_RTC

(指南P1245)

C6748_RTC

(指南P1245)

C6748_RTC

(指南P1246)

C6748_RTC

(指南P1246)

4.5.2 设置时间

设置时间函数RTCTimeSet函数如下:

voidRTCTimeSet(unsignedint baseAdd, unsignedint time)

{

 

volatileunsignedint splitPower =0;

 

if(RTC_REV_AM1808 ==RtcVersionGet())

{

splitPower = RTC_CTRL_SPLITPOWER;

}

 

/* Stop the RTC.*/

HWREG(baseAdd + RTC_CTRL) &=~(RTC_CTRL_RUN);

/* Enable split power mode.*/

HWREG(baseAdd + RTC_CTRL) |= splitPower;

 

/* Writing to SECOND register.*/

HWREG(baseAdd + RTC_SECOND) = (time& SECOND_MASK) >> SECOND_SHIFT;

 

/* Writing to MINUTE register.*/

HWREG(baseAdd + RTC_MINUTE) = (time& MINUTE_MASK) >> MINUTE_SHIFT;

 

/* Writing to HOUR register.*/

HWREG(baseAdd + RTC_HOUR) = (((time& HOUR_MASK) >> HOUR_SHIFT) |

(time& MERIDIEM_MASK));

 

}

    函数首先设置CTRL[RUN]位为0,停止RTC计数器。接着设置CTRL[SPLITPOWER]位为1,使能RTC独立供电模式(split power mode,用板载纽扣电池供电)。然后从time变量中分别提取出时、分、秒数据,对时分秒寄存器进行设置。时分秒寄存器都是以BCD码的形式存储的。

C6748_RTC

C6748_RTC

(指南P1243)

C6748_RTC

(指南P1244)

    在设置时寄存器时,设置MERIDIEM位,在使能12小时模式(12-hour mode)时,该位指示当前小时值是AM还是PM。

4.6 使能32KHz计数器

    完成对RTC相关寄存器的设置后,可以使能RTC的32KHz计数器,让RTC开始计时了。RTCRun函数使能RTC32KHz计数器,函数如下:

voidRTCRun(unsignedint baseAdd)

{

volatileunsignedint splitPower =0;

 

if(RTC_REV_AM1808 ==RtcVersionGet())

{

splitPower = RTC_CTRL_SPLITPOWER;

}

 

/*

** BUSY bit in STATUS register should be checked for being low

** only when RTC is running. The current function is invoked when

** RTC is stopped. Thus, BUSY status need not be checked.

*/

 

/* Setting the RUN bit in CTRL register.*/

HWREG(baseAdd + RTC_CTRL) |= (RTC_CTRL_RUN | splitPower);

}

    函数设置CTRL[RUN]位为1,运行RTC计数器。

C6748_RTC

(指南P1235)

5.DSP中断初始化

    DSP中断初始化函数InterruptInit参考这里:

C6748_SPI_FLASH

6.实时时钟中断初始化

    RTC有2路中断源,一路为Alarm Interrputs,用于设置闹钟;另一路为Periodic Interrputs,用于定时中断。实时时钟中断初始化函数RTCInterruptInit如下:

voidRTCInterruptInit(void)

{

    // 注册中断服务函数

    IntRegister(C674X_MASK_INT4, RTCIsr);

 

    // 映射中断到 DSP 可屏蔽中断

    IntEventMap(C674X_MASK_INT4, SYS_INT_RTC_IRQS);

 

    // 使能 DSP 可屏蔽中断

    IntEnable(C674X_MASK_INT4);

 

// 使能实时时钟中断每秒产生一次中断

RTCIntTimerEnable(SOC_RTC_0_REGS, RTC_INT_EVERY_SECOND);

}

函数首先注册CPU可屏蔽中断INT4的中断服务函数为RTCIsr,然后将RTC中断SYS_INT_RTC_IRQS#63映射到INT4,再使能INT4。最后,设置RTC的INTERRUPT寄存器的INTERRUPT[TIMER]位为1,使能RTC周期中断,同时设置EVERY位,设置中断周期值。

C6748_RTC

(指南P1253)

RTCIntTimerEnable函数如下:

voidRTCIntTimerEnable(unsignedint baseAdd, unsignedint timerPeriod)

{

/*

** Writing to INTERRUPT register requires that BUSY bit in STATUS register

** is low.

*/

while(IS_RTC_BUSY);

 

HWREG(baseAdd + RTC_INTERRUPT) |= RTC_INTERRUPTS_TIMER;

HWREG(baseAdd + RTC_INTERRUPT) |= (timerPeriod & RTC_INTERRUPTS_EVERY);

}

7.中断服务函数

7.1 清除中断标志

    中断服务函数RTCIsr如下:

voidRTCIsr(void)

{

unsignedint timeValue =0, calendarValue =0;

 

IntEventClear(SYS_INT_RTC_IRQS);

 

// 读当前时间

timeValue =RTCTimeGet(SOC_RTC_0_REGS);

 

// 解析时间

TimeResolve(timeValue);

 

// 读当前日期

calendarValue =RTCCalendarGet(SOC_RTC_0_REGS);

 

UARTPuts(" ", -2);

 

// 解析日期

CalendarResolve(calendarValue);

 

UARTPuts("\r", -2);

}

    函数首先清除中断标志,IntEventClear函数参考这两篇博文:

C6748_ECAP_APWM

C6748_EDMA_GPIO_中断学习笔记

7.2 读当前时间

然后函数读出当前时间,RTCTimeGet函数如下:

unsignedintRTCTimeGet(unsignedint baseAdd)

{

unsignedint sec =0, min =0, hour =0, mer =0;

 

/* Reading from SECOND register.*/

sec =HWREG(baseAdd + RTC_SECOND);

sec = (sec & (RTC_SECOND_SEC1 | RTC_SECOND_SEC0)) << SECOND_SHIFT;

 

/* Reading from MINUTE register.*/

min =HWREG(baseAdd + RTC_MINUTE);

min = (min & (RTC_MINUTE_MIN1 | RTC_MINUTE_MIN0)) << MINUTE_SHIFT;

 

/* Reading from HOUR register.*/

hour =HWREG(baseAdd + RTC_HOUR);

hour = (hour & (RTC_HOUR_HOUR1 | RTC_HOUR_HOUR0)) << HOUR_SHIFT;

 

/* Reading MERIDIEM bit in HOUR register.*/

mer = (HWREG(baseAdd + RTC_HOUR) & RTC_HOUR_MERIDIEM);

 

 

return ( sec | min | hour | mer);

}

函数读取时分秒寄存器并将时分秒以及Meridiem值拼接到一起返回给timeValue。

7.3 解析时间

再对时间进行解析,解析时间函数TimeResolve如下:

voidTimeResolve(unsignedint timeValue)

{

unsignedchar timeArray[3] = {0};

unsignedchar bytePrint[2] = {0};

unsignedint count =0, i =0;

unsignedint asciiTime =0;

 

timeArray[0] = (unsignedchar)((timeValue & MASK_HOUR) >> HOUR_SHIFT);

timeArray[1] = (unsignedchar)((timeValue & MASK_MINUTE) >> MINUTE_SHIFT);

timeArray[2] = (unsignedchar)((timeValue & MASK_SECOND) >> SECOND_SHIFT);

 

while(count <3)

{

i =0;

asciiTime =intToASCII(timeArray[count]);

bytePrint[0] = (unsignedchar)((asciiTime &0x0000FF00) >>0x08);

bytePrint[1] = (unsignedchar)(asciiTime &0x000000FF);

while(i <2)

{

UARTPutc(bytePrint[i]);

i++;

}

count++;

if(count !=3)

{

UARTPutc(':');

}

else

{

UARTPutc(' ');

}

}

}

该函数将时分秒信息分别从timeValue中提取出来,并将它们由整型(int型)转换为ASCII码型,再输出到串口。数字转换为ASCII码函数intToASCII如下:

unsignedintintToASCII(unsignedchar byte)

{

unsignedint retVal =0;

unsignedchar lsn =0, msn =0;

lsn = (byte &0x0F);

msn = (byte &0xF0) >>0x04;

 

retVal = (lsn +0x30);

retVal |= ((msn +0x30) <<0x08);

 

return retVal;

}

7.4 读当前日期

    接着读当前日期,读当前日期函数RTCCalendarGet如下:

unsignedintRTCCalendarGet(unsignedint baseAdd)

{

unsignedint calVal =0;

 

/* Reading from the DAY register.*/

calVal = (HWREG(baseAdd + RTC_DAY) & (RTC_DAY_DAY1 | RTC_DAY_DAY0)) <<\

DAY_SHIFT;

 

/* Reading from MONTH register.*/

calVal |= (HWREG(baseAdd + RTC_MONTH) & (RTC_MONTH_MONTH1 |

RTC_MONTH_MONTH0)) << MONTH_SHIFT;

 

/* Reading from YEAR register.*/

calVal |= (HWREG(baseAdd + RTC_YEAR) & (RTC_YEAR_YEAR1 |

RTC_YEAR_YEAR0)) << YEAR_SHIFT;

 

/* Reading from DOTW register.*/

calVal |= (HWREG(baseAdd + RTC_DOTW) & RTC_DOTW_DOTW);

 

return calVal;

}

    函数从DAY、MONTH、YEAR、DOTW寄存器中分别读取日、月、年、星期值,并拼接到calVal变量中,再返回。

7.5 解析日期

    解析日期函数CalendarResolve如下:

voidCalendarResolve(unsignedint calendarValue)

{

unsignedchar calendarArray[3] = {0};

unsignedint asciiCalendar =0;

unsignedint count =0, j =0;

unsignedint dotwValue =0;

char bytePrint[2] = {0};

char dotwString[3] = {0};

 

calendarArray[0] = (unsignedchar)((calendarValue & MASK_DAY) >> DAY_SHIFT);

calendarArray[1] = (unsignedchar)((calendarValue & MASK_MONTH) >> MONTH_SHIFT);

calendarArray[2] = (unsignedchar)((calendarValue & MASK_YEAR) >> YEAR_SHIFT);

 

dotwValue = (calendarValue & MASK_DOTW);

 

switch(dotwValue)

{

case0x00:

dotwString[0] ='S';

dotwString[1] ='u';

dotwString[2] ='n';

break;

 

case0x01:

dotwString[0] ='M';

dotwString[1] ='o';

dotwString[2] ='n';

break;

 

case0x02:

dotwString[0] ='T';

dotwString[1] ='u';

dotwString[2] ='e';

break;

 

case0x03:

dotwString[0] ='W';

dotwString[1] ='e';

dotwString[2] ='d';

break;

 

case0x04:

dotwString[0] ='T';

dotwString[1] ='h';

dotwString[2] ='u';

break;

 

case0x05:

dotwString[0] ='F';

dotwString[1] ='r';

dotwString[2] ='i';

break;

 

case0x06:

dotwString[0] ='S';

dotwString[1] ='a';

dotwString[2] ='t';

 

default:

break;

 

}

 

while(count <3)

{

j =0;

asciiCalendar =intToASCII(calendarArray[count]);

bytePrint[0] = (char)((asciiCalendar &0x0000FF00) >>0x08);

bytePrint[1] = (char)(asciiCalendar &0x000000FF);

while(j <2)

{

UARTPutc(bytePrint[j]);

j++;

}

count++;

if(count !=3)

{

UARTPutc('-');

}

else

{

UARTPutc(' ');

}

 

}

UARTprintf("%s ", dotwString);

}

    函数从calenderValue中分别将年月日提取出来存到calenderArray数组中,将星期值提取处理到dotwValue中,根据星期值设置要打印星期信息数组dotwString。再将日期数组各个元素从整型转到ASCII码型,并将它们打印出来。最后将星期值打印出来,UARTprintf函数在\demo\StarterWare\Source\StarterWare\Utils工程下的uartStdio.c文件中,函数如下:

voidUARTprintf(constchar*pcString, ...)

{

unsignedint idx, pos, count, base, neg;

char*pcStr, pcBuf[16], cFill;

va_list vaArgP;

int value;

 

/* Start the varargs processing. */

va_start(vaArgP, pcString);

 

/* Loop while there are more characters in the string. */

while(*pcString)

{

/* Find the first non-% character, or the end of the string. */

for(idx =0; (pcString[idx] !='%') && (pcString[idx] !='\0'); idx++)

{

}

 

/* Write this portion of the string. */

UARTwrite(pcString, idx);

 

/* Skip the portion of the string that was written. */

pcString += idx;

 

/* See if the next character is a %. */

if(*pcString =='%')

{

/* Skip the %. */

pcString++;

 

/* Set the digit count to zero, and the fill character to space

* (i.e. to the defaults). */

count =0;

cFill =' ';

 

/* It may be necessary to get back here to process more characters.

* Goto's aren't pretty, but effective. I feel extremely dirty for

* using not one but two of the beasts. */

again:

 

/* Determine how to handle the next character. */

switch(*pcString++)

{

/* Handle the digit characters. */

case'0':

case'1':

case'2':

case'3':

case'4':

case'5':

case'6':

case'7':

case'8':

case'9':

{

/* If this is a zero, and it is the first digit, then the

* fill character is a zero instead of a space. */

if((pcString[-1] =='0') && (count ==0))

{

cFill ='0';

}

 

/* Update the digit count. */

count *=10;

count += pcString[-1] -'0';

 

/* Get the next character. */

goto again;

}

 

/* Handle the %c command. */

case'c':

{

/* Get the value from the varargs. */

value =va_arg(vaArgP, unsignedint);

 

/* Print out the character. */

UARTwrite((char*)&value, 1);

 

/* This command has been handled. */

break;

}

 

/* Handle the %d command. */

case'd':

{

/* Get the value from the varargs. */

value =va_arg(vaArgP, unsignedint);

 

/* Reset the buffer position. */

pos =0;

 

/* If the value is negative, make it positive and indicate

* that a minus sign is needed. */

if((int)value <0)

{

/* Make the value positive. */

value =-(int)value;

 

/* Indicate that the value is negative. */

neg =1;

}

else

{

/* Indicate that the value is positive so that a minus

* sign isn't inserted. */

neg =0;

}

 

/* Set the base to 10. */

base =10;

 

/* Convert the value to ASCII. */

goto convert;

}

 

/* Handle the %s command. */

case's':

{

/* Get the string pointer from the varargs. */

pcStr =va_arg(vaArgP, char*);

 

/* Determine the length of the string. */

for(idx =0; pcStr[idx] !='\0'; idx++)

{

}

 

/* Write the string. */

UARTwrite(pcStr, idx);

 

/* Write any required padding spaces */

if(count > idx)

{

count -= idx;

while(count--)

{

UARTwrite((constchar*)" ", 1);

}

}

/* This command has been handled. */

break;

}

 

/* Handle the %u command. */

case'u':

{

/* Get the value from the varargs. */

value =va_arg(vaArgP, unsignedint);

 

/* Reset the buffer position. */

pos =0;

 

/* Set the base to 10. */

base =10;

 

/* Indicate that the value is positive so that a minus sign

* isn't inserted. */

neg =0;

 

/* Convert the value to ASCII. */

goto convert;

}

 

/* Handle the %x and %X commands. Note that they are treated

* identically; i.e. %X will use lower case letters for a-f

* instead of the upper case letters is should use. We also

* alias %p to %x. */

case'x':

case'X':

case'p':

{

/* Get the value from the varargs. */

value =va_arg(vaArgP, unsignedint);

 

/* Reset the buffer position. */

pos =0;

 

/* Set the base to 16. */

base =16;

 

/* Indicate that the value is positive so that a minus sign

* isn't inserted. */

neg =0;

 

/* Determine the number of digits in the string version of

* the value. */

convert:

for(idx =1;

(((idx * base) <= value) &&

(((idx * base) / base) == idx));

idx *= base, count--)

{

}

 

/* If the value is negative, reduce the count of padding

* characters needed. */

if(neg)

{

count--;

}

 

/* If the value is negative and the value is padded with

* zeros, then place the minus sign before the padding. */

if(neg && (cFill =='0'))

{

/* Place the minus sign in the output buffer. */

pcBuf[pos++] ='-';

 

/* The minus sign has been placed, so turn off the

* negative flag. */

neg =0;

}

 

/* Provide additional padding at the beginning of the

* string conversion if needed. */

if((count >1) && (count <16))

{

for(count--; count; count--)

{

pcBuf[pos++] = cFill;

}

}

 

/* If the value is negative, then place the minus sign

* before the number. */

if(neg)

{

/* Place the minus sign in the output buffer. */

pcBuf[pos++] ='-';

}

 

/* Convert the value into a string. */

for(; idx; idx /= base)

{

pcBuf[pos++] = g_pcHex[(value / idx) % base];

}

 

/* Write the string. */

UARTwrite(pcBuf, pos);

 

/* This command has been handled. */

break;

}

 

/* Handle the %% command. */

case'%':

{

/* Simply write a single %. */

UARTwrite(pcString -1, 1);

 

/* This command has been handled. */

break;

}

 

/* Handle all other commands. */

default:

{

/* Indicate an error. */

UARTwrite((constchar*)"ERROR", 5);

 

/* This command has been handled. */

break;

}

}

}

}

 

/* End the varargs processing. */

va_end(vaArgP);

}

    该函数以格式字符串所指定的形式将信息打印到串口。