TMS320C6748_RTC

1.主函数流程

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

int main(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函数如下:

void RTCInit(void)
{
  unsigned int 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);

该函数执行流程如下:

4.1 禁用RTC寄存器写保护

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

void RTCWriteProtectDisable(unsigned int baseAdd)
{
  HWREG(baseAdd + RTC_KICK0) = RTC_KICK0R_KEY;
  HWREG(baseAdd + RTC_KICK1) = RTC_KICK1R_KEY;
}

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

(指南P1240)

4.2 软件复位并使能RTC

    RTC使能函数RTCEnable如下:

void RTCEnable(unsigned int baseAdd)
{
  volatile unsigned int 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软件复位。

 (指南P1251)

(指南P1256)

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

unsigned int RtcVersionGet(void)
{
  return 1;
}

4.3 延时

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

4.4 获取时间和日期

4.4.1 获取时间

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

unsigned int UserTimeInfoGet()
{
  unsigned char hour[2] = {0}, minute[2] = {0}, second[2] = {0};
  unsigned int hourTime = 0, minTime = 0, secTime = 0;
  unsigned int time = 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);

  return time;

}

UARTGetc函数参考这篇博文:

C6748_SPI_FLASH

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

C6748_I2C

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

unsigned char ASCIIToInt(unsigned char byte)
{
  unsigned char retVal = 0;

  // 数字 0-9
  if((byte >= 0x30) && (byte <= 0x39))
  {
    retVal = byte - 0x30;
  }

  // 字母 A-Z
  else if((byte >= 0x41) && (byte <= 0x46))
  {
    retVal = byte - 0x37;
  }

  return retVal;
}

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

4.4.2 获取日期

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

unsigned int UserCalendarInfoGet()
{
  unsigned int calendar = 0;
  unsigned char dayOfMonth[2] = {0}, monthArr[2] = {0}, yearArr[2] = {0};
  unsigned char dotwArr[2] = {0};
  unsigned int 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如下:

void RTCCalendarSet(unsigned int baseAdd, unsigned int 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再往下执行。

(指南P1252)

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

(指南P1245)

(指南P1245)

(指南P1246)

(指南P1246)

4.5.2 设置时间

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

void RTCTimeSet(unsigned int baseAdd, unsigned int time)
{

  volatile unsigned int 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码的形式存储的。

(指南P1243)

(指南P1244)

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

4.6 使能32KHz计数器

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

void RTCRun(unsigned int baseAdd)
{
  volatile unsigned int 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计数器。

(指南P1235)

5.DSP中断初始化

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

C6748_SPI_FLASH

6.实时时钟中断初始化

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

void RTCInterruptInit(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位,设置中断周期值。

(指南P1253)

RTCIntTimerEnable函数如下:

void RTCIntTimerEnable(unsigned int baseAdd, unsigned int 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如下:

void RTCIsr(void)
{
  unsigned int 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函数如下:

unsigned int RTCTimeGet(unsigned int baseAdd)
{
  unsigned int 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如下:

void TimeResolve(unsigned int timeValue)
{
  unsigned char timeArray[3] = {0};
  unsigned char bytePrint[2] = {0};
  unsigned int count = 0, i = 0;
  unsigned int asciiTime = 0;

  timeArray[0] = (unsigned char)((timeValue & MASK_HOUR) >> HOUR_SHIFT);
  timeArray[1] = (unsigned char)((timeValue & MASK_MINUTE) >> MINUTE_SHIFT);
  timeArray[2] = (unsigned char)((timeValue & MASK_SECOND) >> SECOND_SHIFT);

  while(count < 3)
  {
    i = 0;
    asciiTime = intToASCII(timeArray[count]);
    bytePrint[0] = (unsigned char)((asciiTime & 0x0000FF00) >> 0x08);
    bytePrint[1] = (unsigned char)(asciiTime & 0x000000FF);
    while(i < 2)
    {
      UARTPutc(bytePrint[i]);
      i++;
    }
    count++;
    if(count != 3)
    {
      UARTPutc(':');
    }
    else
    {
      UARTPutc(' ');
    }
  }
}

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

unsigned int intToASCII(unsigned char byte)
{
  unsigned int retVal = 0;
  unsigned char lsn = 0, msn = 0;
  lsn = (byte & 0x0F);
  msn = (byte & 0xF0) >> 0x04;

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

  return retVal;
}

7.4 读当前日期

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

unsigned int RTCCalendarGet(unsigned int baseAdd)
{
  unsigned int 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如下:

void CalendarResolve(unsigned int calendarValue)
{
  unsigned char calendarArray[3] = {0};
  unsigned int asciiCalendar = 0;
  unsigned int count = 0, j = 0;
  unsigned int dotwValue = 0;
  char bytePrint[2] = {0};
  char dotwString[3] = {0};

  calendarArray[0] = (unsigned char)((calendarValue & MASK_DAY) >> DAY_SHIFT);
  calendarArray[1] = (unsigned char)((calendarValue & MASK_MONTH) >> MONTH_SHIFT);
  calendarArray[2] = (unsigned char)((calendarValue & MASK_YEAR) >> YEAR_SHIFT);

  dotwValue = (calendarValue & MASK_DOTW);

  switch(dotwValue)
  {
    case 0x00:
         dotwString[0] = 'S';
         dotwString[1] = 'u';
         dotwString[2] = 'n';
    break;

    case 0x01:
         dotwString[0] = 'M';
         dotwString[1] = 'o';
         dotwString[2] = 'n';
    break;

    case 0x02:
         dotwString[0] = 'T';
         dotwString[1] = 'u';
         dotwString[2] = 'e';
    break;

    case 0x03:
         dotwString[0] = 'W';
         dotwString[1] = 'e';
         dotwString[2] = 'd';
    break;

    case 0x04:
         dotwString[0] = 'T';
         dotwString[1] = 'h';
         dotwString[2] = 'u';
    break;

    case 0x05:
         dotwString[0] = 'F';
         dotwString[1] = 'r';
         dotwString[2] = 'i';
    break;

    case 0x06:
         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文件中,函数如下:

void UARTprintf(const char *pcString, ...)
{
  unsigned int 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, unsigned int);

          /* 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, unsigned int);

          /* 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((const char *)" ", 1);
            }
          }
            /* This command has been handled. */
            break;
        }

        /* Handle the %u command. */
        case 'u':
        {
          /* Get the value from the varargs. */
          value = va_arg(vaArgP, unsigned int);

          /* 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, unsigned int);

          /* 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((const char *)"ERROR", 5);

           /* This command has been handled. */
           break;
         }
       }
     }
   }

  /* End the varargs processing. */
  va_end(vaArgP);
}

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

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值