瑞萨e2studio----串口获取数据通过SPI存储于W25Q128外部flash

发布时间:2024-02-22  

1.概述

本篇文章主要介绍如何使用e2studio对瑞萨进行spi配置,同时移植stm32上的W25Q128到瑞萨上,同时通过对该FLASH进行读写操作,验证是否正确。


2.硬件准备

首先需要准备一个开发板,这里我准备的是芯片型号 R7FA2L1AB2DFL 的开发板。

pYYBAGGLLTuAKokoAAL5D_IbQXA990.png


3.新建工程

1b66d376-51d1-11ec-a27f-dac502259ad0.png



4.工程模板


1bdd20ee-51d1-11ec-a27f-dac502259ad0.png



5.保存工程路径


1c5da570-51d1-11ec-a27f-dac502259ad0.png



6.芯片配置


本文中使用R7FA2L1AB2DFL来进行演示。

1cde6494-51d1-11ec-a27f-dac502259ad0.png


7

7.工程模板选择


1d8e86bc-51d1-11ec-a27f-dac502259ad0.png



8.SPI配置


点击Stacks->New Stack->Driver->Connectivity->SPI Driver on r_spi。

1e004450-51d1-11ec-a27f-dac502259ad0.png



9.SPI属性配置


1e8fc8fa-51d1-11ec-a27f-dac502259ad0.png



10.片选CS管脚设置


设置P103管脚为输出管脚,作为CS片选。

1f47176c-51d1-11ec-a27f-dac502259ad0.png



11.设置E2STUDIO堆栈


1fd12614-51d1-11ec-a27f-dac502259ad0.png



12.e2studio的重定向printf设置


2048c692-51d1-11ec-a27f-dac502259ad0.png

C++ 构建->设置->GNU ARM Cross C Linker->Miscellaneous去掉Other linker flags中的 “--specs=rdimon.specs”

20f8c4f2-51d1-11ec-a27f-dac502259ad0.png

13.printf输出重定向到串口

打印最常用的方法是printf,所以要解决的问题是将printf的输出重定向到串口,然后通过串口将数据发送出去。

注意一定要加上头文件#include

 

#ifdef __GNUC__                                 //串口重定向

    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif


PUTCHAR_PROTOTYPE

{

        err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&ch, 1);

        if(FSP_SUCCESS != err) __BKPT();

        while(uart_send_complete_flag == false){}

        uart_send_complete_flag = false;

        return ch;

}


int _write(int fd,char *pBuffer,int size)

{

    for(int i=0;i;i++)>



14.stm32移植瑞萨说明

在STM32的W25Qx.h中,有个片选定义,代码如下。


#define W25Qx_Enable()  HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET)

#define W25Qx_Disable()     HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET)

修改后如下所示。

#define W25Qx_Enable()          R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_03, BSP_IO_LEVEL_LOW);

#define W25Qx_Disable()         R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_03, BSP_IO_LEVEL_HIGH);

在STM32的W25Qx.c中,有对数据进行发送和接受,代码如下。

    /* Send the read status command */

    HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);  

    /* Reception of the data */

    HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE);

修改后如下所示。

    /* Send the read status command */

    g_transfer_complete = false;

    err = R_SPI_Write(&g_spi0_ctrl, cmd, 1, SPI_BIT_WIDTH_8_BITS);

    assert(FSP_SUCCESS == err);

    /* Wait for SPI_EVENT_TRANSFER_COMPLETE callback event. */

    while (  g_transfer_complete==false)

    {

        ;

    }

    /* Reception of the data */

    g_transfer_complete = false;

    err = R_SPI_Read(&g_spi0_ctrl, &status, 1, SPI_BIT_WIDTH_8_BITS);

    assert(FSP_SUCCESS == err);

    /* Wait for SPI_EVENT_TRANSFER_COMPLETE callback event. */

    while (  g_transfer_complete==false)

    {

        ;

    }



15.W25Q128说明

W25Q128将16M的容量分为256个块(Block),每个块大小为64K字节,每个块又分为16个扇区(Sector),每个扇区4K个字节。W25Q128的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。芯片ID如下所示。

0XEF13,表示芯片型号为W25Q80

0XEF14,表示芯片型号为W25Q16

0XEF15,表示芯片型号为W25Q32

0XEF16,表示芯片型号为W25Q64

0XEF17,表示芯片型号为W25Q128



16.演示效果


开机会打印W25Q128的ID,ID为0XEF17,实际如下所示。

并且之前保存的数据也正确读取出来了。

93339caf6a14a76898a1d940907500f2_wKgZomTn1F-AWyYUAAJTzZtf99U143.png

定义数组DataBuff,其中DataBuff[0]表示写入扇区, DataBuff[1]表示写入位置,剩下的为写入数据,同时以0xff结尾。

分别输入数据 01 02 01 02 03 04 ff与02 20 aa bb cc dd ff

ddf831ed08cacff7eb6ff450ffd11856_wKgZomTn1F-ABsCHAASktmRS7-A450.png

2356134e-51d1-11ec-a27f-dac502259ad0.png

17.主程序代码

#include "hal_data.h"

#include 

#include "W25Qx.h"

FSP_CPP_HEADER

void R_BSP_WarmStart(bsp_warm_start_event_t event);

FSP_CPP_FOOTER


void uart1_data(void);


#define BUFFERSIZE 255           //可以接收的最大字符个数

uint8_t ReceiveBuff[BUFFERSIZE]; //接收缓冲区

uint8_t recv_end_flag = 0,Rx_len=0;//接收完成中断标志,接收到字符长度


uint8_t wData1[0x200];

uint8_t wData2[0x200];

uint8_t wData3[0x200];


uint8_t rData1[0x200];

uint8_t rData2[0x200];

uint8_t rData3[0x200];

uint8_t ID[4];

uint32_t i;


uint8_t flag[1] ;

int i_flag = 0;



fsp_err_t err = FSP_SUCCESS;

volatile bool uart_send_complete_flag = false;

uint8_t RxBuff[1];      //进入中断接收数据的数组

uint8_t DataBuff[5000]; //保存接收到的数据的数组

int RxLine=0;           //接收到的数据长度

int Rx_flag=0;                  //接受到数据标志

int Rx_flag_finish=0;                  //接受完成或者时间溢出

void user_uart_callback (uart_callback_args_t * p_args)

{

    if(p_args->event == UART_EVENT_TX_COMPLETE)

    {

        uart_send_complete_flag = true;

    }


    if(p_args->event ==     UART_EVENT_RX_CHAR)

    {

        RxBuff[0] = p_args->data;

        RxLine++;                      //每接收到一个数据,进入回调数据长度加1

        DataBuff[RxLine-1]=RxBuff[0];  //把每次接收到的数据保存到缓存数组

        Rx_flag=1;

        Rx_len++;

        if(RxBuff[0]==0xff)            //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0xff

        {

            Rx_flag_finish=1;

            Rx_len--;

        }

        RxBuff[0]=0;

    }

}


#ifdef __GNUC__                                 //串口重定向

    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif


PUTCHAR_PROTOTYPE

{

        err = R_SCI_UART_Write(&g_uart1_ctrl, (uint8_t *)&ch, 1);

        if(FSP_SUCCESS != err) __BKPT();

        while(uart_send_complete_flag == false){}

        uart_send_complete_flag = false;

        return ch;

}


int _write(int fd,char *pBuffer,int size)

{

    for(int i=0;ievent)

    {

        g_transfer_complete = true;

    }

}

/*******************************************************************************************************************//**

 * 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 */


    err = R_SCI_UART_Open(&g_uart1_ctrl, &g_uart1_cfg);

    assert(FSP_SUCCESS == err);

    err = R_SPI_Open(&g_spi0_ctrl, &g_spi0_cfg);

    assert(FSP_SUCCESS == err);

    printf("rn SPI-W25Q128 openn");

    /*##-1- Read the device ID  ########################*/

    BSP_W25Qx_Init();//初始化W25Q128

    BSP_W25Qx_Read_ID(ID);//读取ID

    if((ID[0] != 0xEF) | (ID[1] != 0x17))

    {

        printf("SPI-W25Q128 error");

    }

    else//ID正确,打印ID

    {

        printf("W25Q128 ID : ");

        for(i=0;i<2;i++)

        {

            printf("0x%02X ",ID[i]);

        }

        printf("rnrn");

    }


    /**************************读取第1扇区数据**************************************************************/

     /*##-3- Read the flash     ########################*/

    /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/

    if(BSP_W25Qx_Read(rData1,0x0,0x200)== W25Qx_OK)

        printf("The first sector successn");

    else

        printf("The first sector errorn");

    /*打印数据*/

    printf("The first sector data: rn");

    for(i =0;i<0x200;i++)

    {

        if(i%20==0)

            printf("nThe first sector data[%d]--data[%d]: rn",i,i+19);

        printf("0x%02X  ",rData1[i]);

    }

        printf("n");

    /**************************读取第2扇区数据**************************************************************/

    /*##-3- Read the flash     ########################*/

    /*读取数据,rData读取数据的指针,起始地址0x1000,读取数据长度0x200*/

     if(BSP_W25Qx_Read(rData2,0x1000,0x200)== W25Qx_OK)

         printf("The second sector successn");

     else

         printf("The second sector errorn");

     /*打印数据*/

    printf("The second sector data: rn");


    for(i =0;i<0x200;i++)

    {

        if(i%20==0)

            printf("nThe second sector data[%d]--data[%d]: rn",i,i+19);

        printf("0x%02X  ",rData2[i]);

        }

    printf("n");

    /**************************读取第3扇区数据**************************************************************/

    /*##-3- Read the flash     ########################*/

    /*读取数据,rData读取数据的指针,起始地址0x2000,读取数据长度0x200*/

    if(BSP_W25Qx_Read(rData3,0x2000,0x200)== W25Qx_OK)

        printf("The third  sector successn");

    else

        printf("The third  sector errorn");

    /*打印数据*/

     printf("The third  sector data: rn");

     for(i =0;i<0x200;i++)

    {

         if(i%20==0)

             printf("nThe third  sector data[%d]--data[%d]: rn",i,i+19);

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>