瑞萨单片机论坛
直播中

刘鑫源的水煮鱼

8年用户 15经验值
擅长:可编程逻辑 电源/新能源 MEMS/传感技术 测量仪表 嵌入式技术 控制/MCU
私信 关注
[经验]

【RA-Eco-RA2E1-48PIN-V1.0开发板试用】在M23内核上使用qfplib浮点运算库进行浮点运算

串口打印qfplib浮点库测试效果

     瑞萨的RA2E1系列MCU是基于M23内核的,这款芯片是不带FPU浮点运算单元的,使用串口prinf函数打印时是无法打印出浮点数的,只有Cortex-M4/M7这些内核才具备FPU单元,才能进行浮点运算。难道由于硬件不支持FPU, 常用的M0/M0+/M23/M3内核就无缘浮点运算了呢?答案是显然不是的。
   我们可以移植使用开源的qfplib库来实现浮点运算,这样在一些不具备FPU的低性能MCU上也能实现接近硬件浮点运算的性能。特别是在一些电机控制领域,随便跑跑FOC算法都需要浮点运算,特别是在一些低成本的园林工具和电动牙刷工具领域,都会使用类似于51单片机/STM8/STM32F103等M0/M0+/M3内核的MCU上有提供了一种新的方法来实现浮点运算。
   言归正传,下面来介绍一下开源的qfplib浮点库的移植和使用步骤。
   首先创建一个串口打印工程。双击图标,

点击next

点击next

点击finish

弹出如下图片

我们先关闭它,然后打开KEIL


配置好后,连接到jlink

再打开下面

配置串口9,我的配置如下

然后点击生成generate,然后关闭当前IDE打开KEIL
修改代码如下:

#include "hal_data.h"
#include


/*********   ²ÎÊýºê¶¨Òå     *********/
#define USART_REC_LEN                          50                          //¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý 50
#define First_String                          "Receive:"            //·µ»Ø¸øPC¶ËµÄÆðʼ×Ö·û´®
#define First_String_num    strlen(First_String)  //Æðʼ×Ö·û´®³¤¶È
#define g_uartx_ctrl        g_uart9_ctrl          //Èç¹ûÊÇ´®¿Ú9ÐèÒªprintfÖØÓ³É䣬¾Íдg_uart9_ctrl


/*×÷Ó㺴®¿Ú9³õʼ»¯£¬P109--TXD,P110--RXD
*´«Èë²ÎÊý£ºÎÞ
*·µ»Ø²ÎÊý£ºÎÞ
*/
void UART9_Init(void)
{       
        fsp_err_t err = FSP_SUCCESS;
       
        err = R_SCI_UART_Open(&g_uart9_ctrl,&g_uart9_cfg);
       
        assert(err == FSP_SUCCESS);
       
}

volatile bool uart_send_complete_flag = false;          // ·¢ËÍÍê³É±êÖ¾
uint8_t USART_RX_BUF[USART_REC_LEN] = First_String;     //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.Æðʼ×Ö·û´®ÎªFirst_StringµÄºê¶¨Òå

/*

        =============================================================================================================
                                              USART_RX_STA  
  =============================================================================================================
         bit15                     |             bit14                        |         bit13--bit0
  =============================================================================================================
    ½ÓÊÕÍê³É±ê־루0x0A,»»Ðмü£©  |         ½ÓÊÕµ½0x0d£¨»Ø³µ¼ü£©             |     ½ÓÊÕµ½µÄÓÐЧÊý¾Ý¸öÊý                                 
  =============================================================================================================

*/
uint16_t USART_RX_STA = First_String_num;       //½ÓÊÕ״̬±ê¼Ç£¬¸ù¾ÝÆðʼ×Ö·û´®À´³õʼ»¯Æðʼ×Ö·ûλÖÃ

void UART_Agreement(uart_callback_args_t * p_args); //´®¿ÚͨѶЭÒé

/*ÓÃÓÚ´®¿Ú9µÄ½ÓÊպͷ¢ËÍÖжÏ
*´«Èë²ÎÊý£º
                *p_args£ºÕâ¸ö²»ÐèÒªÎÒÃǹܣ¬ÏµÍ³×Ô¶¯»á½«Êý¾Ý´«Èë
*·µ»Ø²ÎÊý£ºÎÞ
*/
void uart9_callback(uart_callback_args_t * p_args)
{
        switch (p_args->event)
        {
                //Èç¹ûÊÇ´®¿Ú½ÓÊÕÖжÏ
                case UART_EVENT_RX_CHAR:
                {
                        UART_Agreement(p_args);//´®¿ÚͨѶЭÒéÅжÏ
                        if(USART_RX_STA&0x8000)//Èç¹û½ÓÊÕÍê³É
                        {
                                USART_RX_BUF[USART_RX_STA&0x3FFF] = 0x0d;//½«×Ö·û´®×Ô¶¯»»ÐÐ
                                USART_RX_STA++;                          //ÒòΪÔö¼ÓÁË0x0d£¬ËùÒÔ×Ö·û´®ÊýÁ¿+1
                                R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t*)USART_RX_BUF, USART_RX_STA&0x3fff);//½«×Ö·û´®Êý¾ÝÊä³ö
                                USART_RX_STA=First_String_num;                          //½«USART_RX_STA³õʼ»¯
                        }
                        break;
                }
                //Èç¹ûÊÇ´®¿Ú·¢ËÍÖжÏ
                case UART_EVENT_TX_COMPLETE:
                {
                        uart_send_complete_flag = true;
                        break;
                }
                default:
                break;
        }
}

/*ÓÃÓÚ´®¿ÚͨѶЭÒéÅжÏ
*´«Èë²ÎÊý£º
                *p_args£ºÕâ¸ö²»ÐèÒªÎÒÃǹܣ¬ÏµÍ³×Ô¶¯»á½«Êý¾Ý´«Èë
*·µ»Ø²ÎÊý£ºÎÞ
*/
void UART_Agreement(uart_callback_args_t * p_args)
{
        if((USART_RX_STA&0x8000)==0)                                    //bit15ûÓб»ÖÃΪ1£¬½ÓÊÕδÍê³É
        {
                if(USART_RX_STA&0x4000)                                       //bit14±»ÖÃΪ1£¬±íʾ½ÓÊÕµ½ÁË'n'£¨0x0d£©
                {
                        if((p_args->data)!=0x0a)USART_RX_STA=0;                     //Èç¹ûbit14±»ÖÃ1ÁË£¬µ«ÊÇbit15²¢²»ÊÇ»»ÐвÙ×÷£¬±íʾ½ÓÊÕ´íÎó,ÖØпªÊ¼
                        else USART_RX_STA|=0x8000;                                        //½ÓÊÕÍê³ÉÁË
                }
                else //»¹Ã»ÊÕµ½'n'£¨0x0d£©
                {       
                        if((p_args->data)==0x0d)USART_RX_STA|=0x4000;               //Èç¹û½ÓÊÕµ½ÁË'n'£¨0x0d£©£¬bit14±»ÖÃΪ1
                        else
                        {
                                USART_RX_BUF[USART_RX_STA&0x3FFF]=(uint8_t)(p_args->data);//Èç¹ûûÓнÓÊÕµ½½áÊø±êÖ¾£¬¼ÌÐø½«Êý¾ÝдÈëUSART_RX_BUF[]
                                USART_RX_STA++;
                                if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;         //Èç¹û½ÓÊÕµ½µÄÊý¾Ý´óÓÚ¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý£¬±íʾ½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ          
                        }                 
                }
        }
}

/* Öض¨Ïò printf Êä³ö */
#if defined __GNUC__ && !defined __clang__
int _write(int fd, char *pBuffer, int size); //·ÀÖ¹±àÒ뾯¸æ
int _write(int fd, char *pBuffer, int size)
{
        (void)fd;
        R_SCI_UART_Write(&g_uartx_ctrl, (uint8_t *)pBuffer, (uint32_t)size);
        while(uart_send_complete_flag == false);
        uart_send_complete_flag = false;
        return size;
}
#else
int fputc(int ch, FILE *f)
{
        (void)f;
        R_SCI_UART_Write(&g_uartx_ctrl, (uint8_t *)&ch, 1);
        while(uart_send_complete_flag == false);
        uart_send_complete_flag = false;
        return ch;
}
#endif



FSP_CPP_HEADER
void R_BSP_WARMStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER

/*******************************************************************************************************************//**
* main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
* is called by main() when no RTOS is used.
**********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */
        UART9_Init();
       

       
        printf("»¶Ó­À´µ½ÈðÈøµç×ÓRA2E1ÊÔÓÃÖÐÐÄrn");
        printf("ÎÒŪºÃÁË´®¿Ú´òÓ¡rn");
        printf("ÏÖÔÚÀ´½øÐи¡µãÔËË㣬ÒÆÖ²qfplib¿ârn");
       
       
       
       
       
//        float fnum = 83.12345;
//        printf("fnum = %frn",fnum);

#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}


串口接收用了原子的接收处理



重定向printf

编译后烧录结果见串口打印如下:

接下来,移植qfplib库,复制下面文件夹到keil工程


就是上面的文件夹,里面一个头文件和一个汇编文件,假如keil工程



添加这两个头文件

下面代码是浮点库测试函数

然后编译keil工程烧录,打开串口查看结果

查看视频效果,使用该软件浮点库,能实现接近硬件FPU的性能,非常强悍
附上github连接

https://github.com/mysterywolf/Qfplib-M3
下面是我的工程代码


附件: 您需要登录才可以下载或查看附件。没有帐号?注册

更多回帖

发帖
×
20
完善资料,
赚取积分