EFM32串口功能——添加Printf打印函数

前言

打印函数对一个程序员是十分重要的,当代码出问题的时候,我们可以通过打印函数实时的跟踪到代码运行到的地方和对应的数值是否符合自己的预期,最近在学习EFM32,发现没有Printf函数,我需要打印的格式数据没办法看到,琢磨了和百度了好久都没有结果,最后在一位大神手上拿到了。

串口初始化

void uartInit (void)
{
    CLKINIT();                                                          /* 时钟初始化                   */
    PININIT();                                                          /* 引脚初始化                   */
    MISCINIT();                                                         /* 其它项初始化                 */
    
    USART_InitAsync_TypeDef tUsartInit = {
        .enable       = usartEnable,                                    /* 使能USART发送与接收          */
        .refFreq      = 0,                                              /* 使用当前时钟配置来配置波特率 */
        .baudrate     = BAUDSET,                                        /* 波特率配置                   */
        .oversampling = usartOVS16,                                     /* 16x过采样率                  */
        .databits     = DATABIT,                                        /* 8位数据位                    */
        .parity       = PARITY,                                         /* 无校验位                     */
        .stopbits     = STOPBIT,                                        /* 1位停止位                    */
        .mvdis        = false,                                          /* 使能Majority                 */
        .prsRxEnable  = false,                                          /* 禁能PRS作为RX输入            */
        .prsRxCh      = usartPrsRxCh0                                   /* 选择PRS通道                  */
    };
    USART_InitAsync(UARTPERIPH, &tUsartInit);                           /* 调用初始化函数               */
    
    /* 
     * 使能USART1的TX和RX
     */
    UARTPERIPH->ROUTE =  USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | LOCATION;
    
    USART_IntEnable(UARTPERIPH, USART_IF_RXDATAV);
    NVIC_EnableIRQ(USART1_RX_IRQn);                                      /* 使能USART1接收中断          */
}

修改对应的参数

/*********************************************************************************************************
** 宏定义
*********************************************************************************************************/  
#define UARTPERIPH      USART1
#define LOCATION       (2UL << 8)
    
/*
 *  开启与UART驱动相关时钟
 */
#define CLKINIT()    do {                                                           \
                            CMU_ClockEnable(cmuClock_HF, true);                  \
                            CMU_ClockEnable(cmuClock_GPIO, true);                   \
                            CMU_ClockEnable(cmuClock_USART1, true);                 \
                        } while(0)
/*
 *  UART驱动引脚配置
 */                 
#define PININIT()    do {                                                           \
                            GPIO_PinModeSet(gpioPortD, 7, gpioModePushPull, 1);     \
                            GPIO_PinModeSet(gpioPortD, 6, gpioModeInput, 0);        \
                        } while(0)
/*
 *  完成其它杂项配置
 */                 
#define MISCINIT()   do {                                                           \
                        } while(0)
    
#define   BAUDSET       115200                                          /* 波特率配置为115200           */
#define   DATABIT       usartDatabits8                                  /* 8位数据位                    */
#define   STOPBIT       usartStopbits1                                  /* 1位停止位                    */
#define   PARITY        usartNoParity                                   /* 无校验位                     */

修改对应参数需要注意的地方:
1、#define LOCATION (2UL << 8)
需要查芯片规格书,LOCATION所对应的寄存器修改。
2、你使用的GPIO口管脚需要对应
3、波特率需要一一对应

串口发送函数

void uartTxByte (INT8U ucData)
{
    while (!(UARTPERIPH->STATUS & USART_STATUS_TXBL));                  /* 检查发送缓冲区是否为空       */

    UARTPERIPH->TXDATA = (unsigned int)ucData;
}

串口接收函数函数

INT8U uartRxByte (void)
{
    while (!(UARTPERIPH->STATUS & USART_STATUS_RXDATAV));               /* 查询是否接收到数据           */

    return (INT8U)(UARTPERIPH->RXDATA);
}

串口发送字符函数

void uartPrintString (char *pcString)
{
    while (*pcString != 0) {                                            /* 查询是否是到字符串的末尾     */
        uartTxByte(*pcString++);
    }
}

注意:此函数仅仅支持发送字符,不支持格式字符发送。

发送函数改造

1、我们日常使用的STM32芯片中printf函数是需要重写的,EFM32芯片中同样也是需要重写,重写的方式也是不一样,我在网上百度了好久基本没有找到半点可参考的内容,后来在一位牛人手中得到了重写的方式,今天把它发出来,和大家分享,也是一种学习记录,希望对大家也有帮助。

#ifdef _RAISONANCE_
#define PUTCHAR_PROTOTYPE int putchar (char c)
#define GETCHAR_PROTOTYPE int getchar (void)
#elif defined (_COSMIC_)
#define PUTCHAR_PROTOTYPE char putchar (char c)
#define GETCHAR_PROTOTYPE char getchar (void)
#else /* _IAR_ */
#define PUTCHAR_PROTOTYPE int putchar (int c)
#define GETCHAR_PROTOTYPE int getchar (void)
#endif /* _RAISONANCE_ */
PUTCHAR_PROTOTYPE
{
    uartTxByte(c);
    return c;
}


//将Printf添加到你需要打印的地方即可。
printf("Time_3s = %d\r\n",Time_3s);

将我们发送函数uartTxByte填上去就可以了。然后我们就可以在我们的主程序之中愉快的使用Printf函数了,这样我们就可以实时观测到我们需要查看的数据。

第二种串口打印实现方法

自己通过对函数的改造和重写实现功能

/* 实现itoa函数的源代码 */
char *myitoa(uint32_t num,char *str,uint8_t radix)
{
    /* 索引表 */
    char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    uint32_t unum; /* 中间变量 */
    uint32_t i=0,j,k;
    /* 确定unum的值 */
    if((radix == 10)&&(num < 0))
    {
        unum=(uint32_t)-num;
        str[i++]='-';
    }
    else 
    {
        unum=(uint32_t)num; /* 其他情况 */
    }
    /* 逆序 */
    do
    {
        str[i++]=index[unum%(uint8_t)radix];
        unum/=radix;
    }while(unum);
    str[i]='\0';
    /* 转换 */
    if(str[0]=='-')
    {
        k=1; /* 十进制负数 */
    }
    else 
    {
        k=0;
    }
    /* 将原来的“/2”改为“/2.0”,保证当num在16~255之间,radix等于16时,也能得到正确结果 */
    for(j=k;j<(i-1)/2.0+k;j++) 
    {
        num=str[j];
        str[j]=str[i-j-1+k];
        str[i-j-1+k]=num;
    }
    return str;
}   
//指定的串口输出
void put_char(char ch)
{
    USART_Tx(USART1,ch);
}
#include <stdarg.h>
//打印的函数
void myprintf(const char* fmt,...)  
{  
    const char* s;  
    uint32_t d;  
    char buf[16];  
    va_list ap;  
    va_start(ap,fmt);   // 将ap指向fmt(即可变参数的第一个下一个?)  
    while (*fmt)  
    {  
        if (*fmt != '%')  
        {  
            put_char(*fmt++);   // 正常发送  
            continue;     
        }  
        switch (*++fmt) // next %  
        {  
        case 's':  
            s = va_arg(ap,const char*); // 将ap指向者转成char*型,并返回之  
            for (; *s; s++)  
                put_char(*s);  
            break;  
        case 'x':  
            d = va_arg(ap,uint16_t);     // 将ap指向者转成int型,并返回之  
            myitoa(d,buf,16);         // 将整型d以16进制转到buf中  
            for (s = buf; *s; s++)  
                put_char(*s);  
            break;  
        case 'd':  
            d = va_arg(ap,uint16_t);  
            myitoa(d,buf,10);         // 将整型d以10进制转到buf中  
            for (s = buf; *s; s++)  
                put_char(*s);  
            break; 
        case 'u':  
            d = va_arg(ap,uint32_t);  
            myitoa(d,buf,10);         // 将整型d以10进制转到buf中  
            for (s = buf; *s; s++)  
                put_char(*s);  
            break; 
        default:  
            put_char(*fmt);  
            break;  
        }  
        fmt++;  
    }  
    va_end(ap);  
} 

第二种实现的功能和Printf的功能一模一样,格式也按照Printf格式即可。

结束语

本次分享到此为止,欢迎大家一起来探讨更多的学习心得,希望本文章对你有兴趣。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: EFM32开发套件(Energy Micro Family 32-bit)是一款由索菲亚半导体(Silicon Labs)推出的集成化开发工具,旨在帮助开发者更轻松地设计和开发低功耗嵌入式系统。 其例程是一系列编写好的示例代码,旨在展示EFM32开发套件的各种功能和特性,可以帮助开发者快速入门和学习如何在EFM32芯片上开发代码。这些例程涵盖了许多常见的应用领域,如无线通信、传感器数据采集、电源管理等。 通过使用EFM32开发套件例程,开发者可以快速了解和学习EFM32芯片的特性和功能,避免从零开始编写代码。这些例程包含了完整的源代码和详细的文档,使得开发者能够快速上手并进行自己的应用开发。 除了提供例程代码,EFM32开发套件还提供了一套完整的开发环境,包括集成开发环境(IDE)、调试器等工具。开发者可以使用这些工具来编写、调试和测试他们的应用程序,并且与EFM32开发套件实现无缝的集成。 总之,EFM32开发套件例程提供了一种简便的学习和开发方式,通过使用它们,开发者可以更快地上手和掌握EFM32芯片,从而加速低功耗嵌入式系统的开发过程。 ### 回答2: EFM32开发套件例程是用来演示和说明EFM32微控制器的各种功能和特性的代码示例集合。它们被设计用作新用户学习和评估EFM32系列微控制器的工具。 EFM32开发套件例程提供了丰富的代码实现,包括了各种外设,如GPIO、USART、SPI、I2C等。这些例程覆盖了从基本的IO控制到高级的通信和数据处理功能的各个方面。 通过运行这些例程,用户可以学习如何初始化和配置各个外设,并使用它们完成各种任务。这些例程还包含了详细的代码注释和使用说明,使用户能够轻松理解和修改代码以适应自己的需求。 除了提供例程代码外,EFM32开发套件还提供了开发工具和文档,以帮助用户更好地使用例程。用户可以使用官方的开发工具和配套的IDE进行代码编译、调试和下载,同时,官方的技术文档也提供了对开发套件和例程的详细介绍和解释。 总之,EFM32开发套件例程是一套非常有价值的资源,可帮助用户快速上手和了解EFM32系列微控制器的各种功能和特性。无论是初学者还是有经验的开发人员,都可以通过使用这些例程来加快自己的开发速度并提高自己的技术水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值