This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ccs studio里面如何使用printf函数

Other Parts Discussed in Thread: MSP430G2553, CCSTUDIO

我实时仿真msp430芯片,用库里面的printf函数输出,串口调试助手没有输出信息,请问该如何弄

  • printf 和scanf函数是C语言中最常用的输入出函数,从学习C语言开始,就开始使用这两个函数,然而当写用C语言写单片机程序时却不能使用这两个函数,总觉得单片机的C语言和一般的C语言差别很大,写起来不大方便;其实,单片机的C语言也是标准C语言上扩展或是改动的,都支持格式化输入输出函数(printf 和scanf);事实上,printf,scanf只负责格式化输入输出的字符,至于从哪儿输入,输出到哪儿,他们分别依靠getchar和putchar函数,只要实现单片机上的getchar函数和putchar函数,即可正常使用printf函数和scanf函数,这可以给我们单片机的信息交互带来很多方便。下面我们就来实现他们的移置。

    1. 硬件介绍:

      硬件部分只需字符型输入输出设备:scanf从输入字符型设备读取字符,printf输出到字符型输出设备。在这里,我选用的字符型输入设备是超级终端,通过串口与单片机连接,输入字符;输出设备是超级终端和12864的液晶。scanf从串口读入字符,printf输出字符到串口和液晶。

      有关串口的预提信息参考:MSP430程序库<二>UART异步串口

      有关液晶的具体信息参考:MSP430程序库<三>12864液晶程序库

      scanf还可以从按键读取信息,可以参考移置方法自行移置。

    2. 程序实现:
      • printf

        单片机在调用printf时,printf是负责将数据解析成ASCII码流,通过调用putchar函数依次将字符发出。如果在putchar内编写从串口发送一字节数据,则printf的结果将从单片机串口发送出;如果putchar是向液晶写字符,让液晶显示一个字符,则printf的结果将显示在液晶上。本程序实现putchar同时向串口和液晶同时发送一个字符(液晶是显示一个字符)。

        putchar函数如下:

        int putchar(int ch)
        {
            putchar2Com(ch);
            putchar2Lcd(ch);
            return (ch);
        }

        程序先向串口发送一个字符,然后像向晶发送字符。

        其中:putchar2Com,向串口发送一个字符,代码如下:

        int putchar2Com(int ch)
        {
            if (ch == '\n')           // '\n'(回车)扩展成 '\n''\r' (回车+换行) {
                UartWriteChar('\r') ;   //0x0d 换行 }
            UartWriteChar(ch);        //从串口发出数据 return (ch);
        }

        代码仅仅调用向串口写字符的函数UartWriteChar(ch)(详见Uart.c,在<二>中有介绍),当要输出换行时,需先输出’\n’将光标移至本行首位置,还需要’\r’(换行)才能将光标置于下一行起始位置,即将’\n’扩展为’\r’,’\n’两个字节依次发出。

        purchar2Lcd函数比较复杂,因为我所使用的12864液晶是中文字库的液晶,每行8个地址,可以显示8个中文字符或16个英文字符,而putchar只发出一个字节,需要判断每个地址的前半字还是后半字(因为每个字可以显示中文,如果中文的两个字节在相邻的两个地址上,将不会显示,或是显示乱码)。

        上代码:

        int putchar2Lcd(int ch)
        {
            char addr,dat;
            
            if (ch == '\n')           // '\n'(回车),换行 {
                ChangeNextRow();
            }
            else {
                addr = LcdReadAddr();
                if(ch < 0x80)
                {
                    LcdWriteData(ch);
                }
                else {
                    LcdWriteData(0x20);     //写入一个空字符,根据地址判断是否为前半字 if(addr == LcdReadAddr())   //前半字 从新写入ch字符 {
                        LcdWriteComm(addr);
                        LcdWriteData(ch);
                    }
                    else {
                        LcdWriteComm(addr);
                        dat = LcdReadData();
                        if(dat < 0x80)           //前一个字符是英文字符 {
                         LcdWriteData(0x20);                 //空格               }
                        LcdWriteData(ch);
                    }
                }
            }
            if((addr != LcdReadAddr()) &&               //写入的是行最后位的后半字则换行 (addr==0x87 || addr==0x97 || addr==0x8F || addr==0x9F))
            {
                ChangeNextRow();
            }
            return (ch);
        }

        这个函数首先判断换行;然后处理其他一般字符,如果是英文字符,不用考虑前后半字,只需正常写入液晶即可;如果是中文字符,在判断是否是前半字,前半字则直接写入,后半字则判断之前写入的前半字是否是中文,是则直接写入,不是则把英文字符移入后半字,然后写入;最后判断是否到行尾,是则换行。

        程序更新为:更新日期:20110821 18:51
        目的是修复原来,行尾前半字为英文,再输入中文会显示乱码。
        int putchar2Lcd(int ch)
        {
            char addr,dat;
            char changeRowFlag = 0;
            
            if (ch == '\n')         // '\n'(回车),换行 {
                ChangeNextRow();
                changeRowFlag = 1;
            }
            else if (ch == '\b')    // '\b' (退格) {
                BackSpace();
            }
            else {
                addr = LcdReadAddr();
                if(ch < 0x80)
                {
                    LcdWriteData(ch);
                }
                else {
                    LcdWriteData(0x20);     //写入一个空字符,根据地址判断是否为前半字 if(addr == LcdReadAddr())   //前半字 从新写入ch字符 {
                        LcdWriteComm(addr);
                        LcdWriteData(ch);
                    }
                    else {
                        LcdWriteComm(addr);
                        dat = LcdReadData();
                        if(dat < 0x80)           //前一个字符是英文字符 {
                            LcdWriteData(0x20);                 //空格 }
                        if((addr != LcdReadAddr()) &&               //写入的是行最后位的后半字则换行 (addr==0x87 || addr==0x97 || addr==0x8F || addr==0x9F))
                        {
                            ChangeNextRow();
                            changeRowFlag = 1;
                        }
                        LcdWriteData(ch);
                    }
                }
            }
            if((addr != LcdReadAddr()) &&   //写入的是行最后位的后半字则换行,且未换过行 (changeRowFlag == 0) &&   
               (addr==0x87 || addr==0x97 || addr==0x8F || addr==0x9F))
            {
                ChangeNextRow();
            }
            return (ch);
        }

        前后半字判断方法如下:读液晶地址,向液晶写入一个空格,再读地址,两地址相同则是前半字,不同则是后半字。读地址函数在Lcd12864.c中,新加入函数,代码如下:

        char LcdReadAddr()
        {
            char ch;
            
            WaitForEnable();
            
            CLR_RS;
            SET_RW;
            
            DATA_DIR_IN;
            
            SET_EN;
            _NOP();
            
            ch = DATA_IN;    //读数据 CLR_EN;
            DATA_DIR_OUT;
            
            return (ch|0x80);
        }

        这个是读地址,ch|0x80是因为写入液晶地址首位应为1.。

        液晶中新加入两个函数,一个是上边的读地址,另外一个是读数据;作用是读取液晶当前地址处的数据,从而判断之前半字是否是中文。代码如下:

        char LcdReadData()
        {
            char ch;
            
            WaitForEnable();
            
            SET_RS;
            SET_RW;
            
            DATA_DIR_IN;
            
            SET_EN;
            _NOP();
            
            ch = DATA_IN;    //读数据 CLR_EN;
            DATA_DIR_OUT;
            
            return ch;
        }

        另外 putchar还调用了换行——ChangeNextRow函数,完成液晶输出换至下一行。

        代码如下:

        void ChangeNextRow()
        {
            char addr;
            
            addr = LcdReadAddr();       //当前地址 if(addr <= 0x88)
            {
                LcdWriteComm(0x90);
            }
            else if(addr <= 0x90)
            {
                LcdWriteComm(0x98);
            }
            else if(addr <= 0x98)
            {
                LcdWriteComm(0x88);
            }
            else {
                AddNewline();           //添加行,同时向上滚动 LcdWriteComm(0x98);
            }
        }

        读取当前地址,判断在哪一行,然后写入下一行首地址;如果是最后一行,则所有安徽那个向上移,写入最后一行首地址。

        AddNewLine函数完成所有行向上滚动一行,然后地址定位至最后一行。

        代码如下:

        void AddNewline()
        {
            char str[17];
            str[16] = 0;
            
            //第二行 移至第一行 LcdWriteComm(0x90);
            LcdReadData();              //空读取 for(int i = 0;i<16;i++)
            {
                str[i] = LcdReadData();
            }
            LcdWriteString(0x80,str);
            
            //第三行 移至第二行 LcdWriteComm(0x88);
            LcdReadData();
            for(int i = 0;i<16;i++)
            {
                str[i] = LcdReadData();
            }
            LcdWriteString(0x90,str);
            
            //第四行 移至第三行 LcdWriteComm(0x98);
            LcdReadData();
            for(int i = 0;i<16;i++)
            {
                str[i] = LcdReadData();
            }
            LcdWriteString(0x88,str);
            
            //第四行 空白 LcdWriteString(0x98," ");    //十六个空格 }

        读出下一行数据,写入上一行,最后一行写入空格即可。

        到此putchar函数全部完成,printf移植的程序部分完成,使用方法详见使用示例。

      • scanf

        scanf和printf类似,其只负责格式化输入的字符,字符来源是从getchar函数获取;同样,在使用scanf函数之前,要针对字符输入源自行编写getchar函数

        最简getchar:

        int getchar()
        {
            return (putchar(UartReadChar()));
        }

        这是最简单的getchar函数,直接调用读取字符函数,输出并返回。

        但是人的输入过程会偶尔犯错误的,为了支持退格键等,需要开辟一个缓存区。

        详细代码如下:

        #define LINE_LENGTH 80          //行缓冲区大小,决定每行最多输入的字符数 /*标准终端设备中,特殊ASCII码定义,请勿修改*/ #define InBACKSP 0x08           //ASCII <-- (退格键) #define InDELETE 0x7F           //ASCII <DEL> (DEL 键) #define InEOL '\r' //ASCII <CR> (回车键) #define InSKIP '\3' //ASCII control-C #define InEOF '\x1A' //ASCII control-Z #define OutDELETE "\x8 \x8" //VT100 backspace and clear #define OutSKIP "^C\n" //^C and new line #define OutEOF "^Z" //^Z and return EOF 
        int getchar()
        {
            static char inBuffer[LINE_LENGTH + 2];      //Where to put chars static char ptr;                            //Pointer in buffer char c;
            
            while(1)
            {
                if(inBuffer[ptr])                       //如果缓冲区有字符 return (inBuffer[ptr++]);           //则逐个返回字符 ptr = 0;                                //直到发送完毕,缓冲区指针归零 while(1)                                //缓冲区没有字符,则等待字符输入 {
                    c = UartReadChar();                 //等待接收一个字符 if(c == InEOF && !ptr)              //==EOF== Ctrl+Z {                                   //只有在未入其他字符时才有效 printf(OutEOF);                 //终端显示EOF符 return EOF;                     //返回 EOF(-1) }
                    if(c==InDELETE || c==InBACKSP)      //==退格或删除键== {
                        if(ptr)                         //缓冲区有值 {
                            ptr--;                      //从缓冲区移除一个字符 printf(OutDELETE);          //同时显示也删掉一个字符 }
                    }
                    else if(c == InSKIP)                //==取消键 Ctrl+C == {
                        printf(OutSKIP);                //终端显示跳至下一行 ptr = LINE_LENGTH + 1;          //==0 结束符== break;
                    }
                    else if(c == InEOL)                 //== '\r' 回车== {
                        putchar(inBuffer[ptr++] = '\n');//终端换行 inBuffer[ptr] = 0;              //末尾添加结束符(NULL) ptr = 0;                        //指针清空 break;
                    }
                    else if(ptr < LINE_LENGTH)          //== 正常字符 == {
                        if(c >= ' ')                    //删除 0x20以下字符 {
                            //存入缓冲区 putchar(inBuffer[ptr++] = c);
                        }
                    }
                    else //缓冲区已满 {
                        putchar('\7');                  //== 0x07 蜂鸣符,PC回响一声 }
                }
            }
        }

        注释已经很详细了,这里不再详细解释。

        scanf的移植程序部分已经完成,如果需要从键盘读入字符,可以仿照上述函数写getchar函数。具体使用和设置见使用示例。

        另外,iar的安装文件夹下,430文件夹下有一个src文件夹,lib/clib文件夹下(我的具体文件夹是:D:\Program Files\IAR Systems\Embedded Workbench 6.0 Evaluation\430\src\lib\clib\getchar.c),有一个getchar.c文件,这是getchar的函数,内容如下:

        #include "stdio.h" extern char _low_level_get(void);       /* Read one char from I/O */ /* Should be supplied by user */ static void put_message(char *s)
        {
          while (*s)
            putchar(*s++);
        }
        
        
        #define LINE_LENGTH 80          /* Change if you need */ #define In_DELETE 0x7F          /* ASCII <DEL> */ #define In_EOL '\r' /* ASCII <CR> */ #define In_SKIP '\3' /* ASCII control-C */ #define In_EOF '\x1A' /* ASCII control-Z */ #define Out_DELETE "\x8 \x8" /* VT100 backspace and clear */ #define Out_SKIP "^C\n" /* ^C and new line */ #define Out_EOF "^Z" /* ^Z and return EOF */ int getchar(void)
        {
          static char io_buffer[LINE_LENGTH + 2];     /* Where to put chars */ static int ptr;                             /* Pointer in buffer */ char c;
        
          for (;;)
          {
            if (io_buffer[ptr])
              return (io_buffer[ptr++]);
            ptr = 0;
            for (;;)
            {
              if ((c = _low_level_get()) == In_EOF && !ptr)
              {
                put_message(Out_EOF);
                return EOF;
              }
              if (c == In_DELETE)
              {
                if (ptr)
                {
                  ptr--;
                  put_message(Out_DELETE);
                }
              }
              else if (c == In_SKIP)
              {
                put_message(Out_SKIP);
                ptr = LINE_LENGTH + 1;  /* Where there always is a zero... */ break;
              }
              else if (c == In_EOL)
              {
                putchar(io_buffer[ptr++] = '\n');
                io_buffer[ptr] = 0;
                ptr = 0;
                break;
              }
              else if (ptr < LINE_LENGTH)
              {
                if (c >= ' ')
                {
                  putchar(io_buffer[ptr++] = c);
                }
              }
              else {
                putchar('\7');
              }
            }
          }
        }

        _low_level_get(void); 这个函数需用户定义,不过这个getchar函数不支持退格键,可以更改以支持;_low_level_get(void);这个函数可以直接调用UartReadChar();这个函数,使用时,把getchar.c加入项目,同时在项目中添加_low_level_get(void);函数,函数体只有一句:return UartReadChar();即可。

    3. 程序调用示例:

      程序使用方式,项目中添加printf.c文件和scanf.c文件(用printf函数则加printf.c文件,用scanf函数就添加scanf.c文件),在要使用函数的地方包含stdio.h(编译器自带库——标准输入输出库)

      image_thumb1

      还要设置使用库和printf的大小:

      image_thumb4

      如果不进行这项设置,使用scanf时将报错:

      Error[e27]: Entry "getchar" in module Scanf ( G:\work\程序库\Printf\Debug\Obj\Scanf.r43 ) redefined in module ?getchar ( D:\Program Files\IAR Systems\Embedded;用的是C语言,这里选择CLIB。

      然后设置库选项:

      image_thumb7

      这里选择大尺寸,目的是支持所有的格式,因为所用单片机有64kb的程序存储空间,足够使用,如果程序存储空间不够大,推荐选择中尺寸或小尺寸。大尺寸printf占用空间 4.8kb、scanf :2.3kb,中尺寸 printf:2.5kb、scanf:1.6kb,小尺寸 printf:1.6kb。实际使用时根据需要进行选择。

      同时要加入Lcd12864的使用(c文件,h文件(要调用lcd12864的初始化函数))Uart和液晶一样要调用初始化函数。

      #include <msp430x16x.h> #include <stdio.h> #include "Uart.h" #include "Lcd12864.h" 

      头文件包含。

      void main( void )
      {
          // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD;
          ClkInit();
          LcdInit();
          UartInit(38400,'n',8,1);//串口初始化,设置成38400bps,无校验,8位数据,1位停止 //int a; _EINT();
          //scanf("%d",&a); //printf("刘中原%d\n",a); printf("刘中原%f\n",23.6);
          printf("刘中原%1.2f\n",23.6);
      }

      使用时,先调用液晶和串口的初始化函数,然后开中断;就可以正常的调用scanf和printf函数了。

    至此,printf和scanf的移植全部完成,使用这两个函数将给单片机的输入输出带来极大方便。另外,Lcd12864的液晶使用是4行显示,空间较小,可能需要定位至具体位置,以使界面看起来更合理,为此,在Printf中再添加一个定位函数(GotoXY):

    void GotoXY(char x,char y)
    {
        char addr;
        
        if(y==0)
        {
            addr = 0x80 + x / 2;
        }
        else if(y==1)
        {
            addr = 0x90 + x / 2;
        }
        else if(y==2)
        {
            addr = 0x88 + x / 2;
        }
        else {
            addr = 0x98 + x / 2;
        }
        LcdWriteComm(addr);
        if(x % 2)                   //是奇数,后移一位(写入空格) {
            LcdWriteData(0x20);
        }
    }

    这样就方便了液晶程序的编写。

    又加入一个函数,在printf.c里,目的是支持退格键,内容如下:

    void BackSpace()
    {
        char addr,dat;
        
        addr = LcdReadAddr();       //当前地址 LcdWriteData(0x20);         //写入一个空字符,根据地址判断是否为前半字 if(addr == LcdReadAddr())   //前半字 {
            if(addr == 0x80)
                return;
            else if(addr == 0x90)
                addr = 0x87;
            else if(addr == 0x88)
                addr = 0x97;
            else if(addr == 0x98)
                addr = 0x8F;
            else addr = addr - 1;
           
            LcdWriteComm(addr);
            LcdReadData();          //空读取 dat = LcdReadData();
            LcdWriteComm(addr);
            if(dat < 0x80)
                LcdWriteData(dat);
        }
        else {
            LcdWriteComm(addr);
        }
    }
  • 给你个参考,

    ******************************************************

    #include <msp430g2553.h>
    #include <stdarg.h>
    #include <string.h>
    #include "uart.h"
    / ********************************************************************
     *静态函数声明
     * ********************************************************************/
    static void Vs_Printf(char *s,char *format,va_list arg);
    static void IntToString(int temp,char *pchar);
    / ********************************************************************
     * 函数名   :   UartInit
     * 函数功能  :  初始化msp430g2553的USCI寄存器,使其工作在UART模式
     * 形参     :  无
     * 返回值   :  无
     * ********************************************************************/
    void UartInit()
    {
        / ****************************************************************************
         * P1.1设为输入作为uart的数据输入口
         * P1.2设为输出作为UART的数据输出口
         ****************************************************************************/
        P1DIR &=~BIT1;
        P1DIR |=(BIT2 );
        / ****************************************************************************
         * 将P1.1和P1.2口配置为第三功能口,UART功能
         ****************************************************************************/
        P1SEL |=  BIT1 + BIT2 ;
        P1SEL2 |= BIT1 + BIT2;
        / ****************************************************************************
         * 配置U0CTL1寄存器,在UCSWRST置位的情况下(即保持USCI软件复位的情况下配置各
         * 个寄存器的各标志位)置位UCSSEL_2配置时钟源为SMCLK。其他位为0
         ****************************************************************************/
        U0CTL1 |= UCSWRST;                      // Set SW Reset
        U0CTL1 = UCSSEL_2+ UCSWRST;               // Use SMCLK, keep SW reset
        / ****************************************************************************
         * 配置波特率大小,公式:(U0BR1<<8+U0BR0)=(int)(source_clk/baud rate)
         * U0MCTL为(source_clk/baud rate)的余数乘以8之后的值对应表中的值,实现控
         * 制调制系数
         * 大小如表所示:
         * _______________________________________________________________
         * |余数*8  |1     |2     |3     |4     |5     |6     |7     |
         * |U0MCTL |0x08  |0x88  |0x2A  |0x55  |0x6B  |0xdd  |0xef |   
         ****************************************************************************/
        U0BR0 = 0x04;                           
        U0BR1 = 0x01;
        U0MCTL = 0x2A;
        / ****************************************************************
        * 解除软件复位,使USCI开始工作
        ****************************************************************/
        U0CTL1 &= ~UCSWRST;
        / ****************************************************************
         * 允许接收中断
         ****************************************************************/
        UC0IE |= UCA0RXIE;                              // Enable RX int
    }
    / ********************************************************************
     * 函数名   :   UartPutchar
     * 函数功能  :  向串口终端发送一个字符
     * 形参     :  Txdata为待发送的字符
     * 返回值   :  无
    *******************************************************************/
    void UartPutchar(char Txdata)
    {
        if(Txdata=='\n'){
           while(UCA0STAT & UCBUSY);
           UCA0TXBUF='\r';
        }
        while(UCA0STAT & UCBUSY);
        UCA0TXBUF=Txdata;
    }
    / ********************************************************************
     * 函数名   :   UartSendString
     * 函数功能  :  向串口终端发送一个字符串
     * 形参     :  pt为字符串指针。
     * 返回值   :  无
     *******************************************************************/
    void UartSendString(char *pt)
    {
        while(*pt)
            UartPutchar(*pt++);
    }
    / *******************************************************************
     * 函数名    :   IntToString
     * 函数功能  :  将一个整形的书转化成为一个表现形式一样的字符串
     * 说明      :  举例说明功能,若有一个整数为65535,该函数作用就是将
     *              “65535”其转化为字符串
     * 形参      :  temp为待装换的整数,pchar为转化成的字符串所存储的地址
     * 返回值    :  无
    ********************************************************************/
    void IntToString(int temp,char *pchar)
    {
        char ch,*p=pchar;
        while(temp!=0){
           *pchar++=(char)(temp+0x30);
           temp/=10;
        }
        *pchar--='\0';
        while(pchar>p){
           ch=*p;
           *p++=*pchar;
           *pchar--=ch;
        }
    }
    / ********************************************************************
     * 函数名   :   Vs_Printf
     * 函数功能  :  将参数指针arg所指的不定参数按照格式字符串format中的一一对应的格
    *            式转化后生成一个新的字符串存于地址s中。
     * 形参     :  s为最终形成的字符串存储地址,format为格式字符串,arg为不定参数指
    *            针。
     * 返回值   :  无
    ********************************************************************/
    void Vs_Printf(char *s,char *format,va_list arg)
    {
        char *pchar;
        char *temp;
        for(pchar=format;*pchar;pchar++){
           if(*pchar !='%'){
               *s++=*pchar;
               continue;
           }
           switch(*++pchar){
               case 'd'   :{
                  IntToString(va_arg(arg,int),s);
                  while(*s++);
                  *--s='0';
                  break;
               }
               case 's'   :{
                  temp=va_arg(arg,char *);
                  while(*s++=*temp++);
                  *--s='0';
                  break;
               }
               case 'c'   :{
                  *s++=va_arg(arg,char);
                  break;
               }
               default       :break;
           }
        }
        *s='\0';
    }
    / ********************************************************************
     * 函数名   :   Printf
     * 函数功能  :  格式化输出
     * 形参     :  fmt为格式字符串,…为不定(类型不定、个数不定)形参
     * 返回值   :  无
    *******************************************************************/
    void Printf(char *fmt,...)
    {
        / ********************************************************
         * va_list类型声明一个参数指针ap,该变量将依次引用各个参数
         * ******************************************************/
        va_list ap;
        char string[256];
        / ********************************************************
         * va_start(ap,fmt),该函数将ap指针指向参数列表中的最后一个
         * 有名参数fmt
         * ******************************************************/
        va_start(ap,fmt);
        / ********************************************************
         * Vs_Printf,该函数将ap指向的无名参数按照fmt固定的格式转化
         * 成为字符串存于string中
         * ******************************************************/
        Vs_Printf(string,fmt,ap);
        UartSendString(string);
        / ********************************************************
         * 最后调用va_end(ap)释放指针
         * ******************************************************/
        va_end(ap);
    }
    / ************************ end of file ******************************/
    将文件uart.c添加到工程中去,并建立主函数进行验证。笔者的写的测试主函数如下所示:
    #include <msp430g2553.h>
    #include "clock.h"
    #include "uart.h" 
    void main()
    {  
        int year=2012;
        WDTCTL = WDTPW + WDTHOLD;
        Init_Clk();
        UartInit();
        char *str="Hello World!";
        Printf("year=%d\n str=%s\n",year,str);
    }
  • qunmei,

      CCS里面是支持printf来调试的,关于设置方面,你可以参考下面的链接:

    http://processors.wiki.ti.com/index.php/Printf_support_for_MSP430_CCSTUDIO_compiler

    谢谢