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

发布者:美丽花朵最新更新时间:2024-02-22 来源: elecfans关键字:串口  SPI  W25Q128  外部flash 手机看文章 扫描二维码
随时随地手机看文章

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);

[1] [2]
关键字:串口  SPI  W25Q128  外部flash 引用地址:瑞萨e2studio----串口获取数据通过SPI存储于W25Q128外部flash

上一篇:BC20-NBIOT模块通过MQTT协议连接华为云服务器调试
下一篇:SPL2LL转换器实现标准库代码迁移为LL库的方法与内容

推荐阅读最新更新时间:2024-11-05 11:59

单片机技术C51串口输出输入函数
*---------------------------------------- ComFun.c C51串口输出输入函数 外部声明 ComFun.h ----------------------------------------*/ #include //串口初始化 晶振为11.0592M 方式1 波特率300-57600 void InitCom(unsigned char BaudRate) { unsigned char THTL; switch (BaudRate) { case 1: THTL = 64; break; //波特率300 case 2: THTL = 160; break; //600 case
[单片机]
GPS远端定位监控系统的设计
0 引 言 GPS(全球定位系统)的主要应用之一是对车辆进行监控和管理。采用目前最完善的GSM(全球移动通信系统)技术,不仅使企业客户和个人用户对车辆的监控管理更准确、快捷,范围更宽广,而且大大降低了企业客户对GPS车辆监控的前期投入费用。只需要一台电脑,再配上监控管理软件,便可以对公司或单位内所有安装GPS的车辆进行全天候、超远程的监控。这种监控系统主要由GPS无线收发系统和监控系统两部分组成。 1 GPS无线收发系统的结构组成 GPS无线收发系统由GPS接收模块、信息处理模块、GSM发送模块3部分组成。结构见图1 。 1.1 GPS信号接收模块的组成及工作原理 常用的GPS模块主要由天线单元和接收单元两大部分组
[应用]
LabVIEW串口通讯问题解决方案
我通过串口从下位机采集了四个数据,但这四个数据通过指示控件显示出来的却出现连续的 数据 0 数据 0 的闪动,也就是说读数很不稳定。请问高手如何解决指示控件的频闪问题。谢谢 我的想法是,整个串口读数过程是在一个循环中完成的,一次循环的时间相对我100ms从串口读一次数的时间很短,就出现了指示控件显示的两次读数之间有0夹杂的频闪问题,不知这个分析对否正确,如何解决,请给与指点,谢谢 解答: 这个是因为读完数据后 又读出了0 只要 在循环结构 添加一个反馈结构就可以了 问题2 我自己做了个测试的小例子 开始第一个能写能读 到了后面的就不行了 没反映 解答:是Timeout的错误,应该是串口上没有你所要的数据,或者你要求
[测试测量]
I2C与SPI的区别是什么 速率对比
I2C 与 SPI 对比 功能 I2C SPI 线数 2(SDA,SCL) 4(MOSI,MISO,SCLK,CS) 主机数量 =1 ==1 类型 半双工 全双工 回应机制 yes no 速度 =3.4Mbps high 应用 重要数据 大量数据 流控 yes no 设备地址 yes no 常规用途 命令 数据 I2C 和 SPI 的速率如下: I2C模式 速度 标准 100KHz 快速 400KHz 快速+ 1MHz 高速 3.4MHz SPI 速率:几十 MHz 甚至上百 MHz,速度取决于 CPU 的 SPI 控制器和时钟 clock STM32F103 的 SPI
[单片机]
分析一下UART IIC SPI驱动编写步骤
1,首先都是设置引脚的功能,把引脚设置到对应的模式 2,然后设置对应串口控制器的一些参数(也就寄存器的一些参数),完成对串口的基本设置,比如UART的波特率等等的。要配置哪些参数一般在对应外设的初始化结构体里都列了。所以这个步骤就变得很简单,就往对应外设的初始化结构体里面赋值就行了。而且我发现对引脚的设置其实也是对引脚的那个结构体的里面的参数赋值!!!!!都给它弄成结构体了,很方便!!!!!!!!!!所以整个过程就变成了往两个结构体里面填值就可以了,怪不得都不不需要变成用STM32cube选几下就可以了!!!!!!确实本质就是这样子的!!!!!!! 3,然后写发送或者接收。 我觉得主体可以分为以上三个部分。
[单片机]
分析一下UART IIC <font color='red'>SPI</font>驱动编写步骤
「51单片机」RS232串口通信代码分析
想来想去不知道要怎么样把232串口通信说清楚,想想还是直接把代码分析一遍吧... 重点是“常用波特率与定时器1的参数关系”这张表格!波特率的设置很重要! 一、串口初始化 void usart_init() { SCON = 0x50; //REN=1允许串行接受状态,串口工作模式1 TMOD = 0x20; //定时器工作方式2 PCON = 0x00; TH1 = 0xFD; //波特率9600、数据位8、停止位1。效验位无 (11.0592M) TL1 = 0x
[单片机]
「51单片机」RS232<font color='red'>串口</font>通信代码分析
STM32 DMA串口发送模式配置及使用简单分享
  赠人玫瑰,手有余香;很感谢网上其他楼主的分享;我这个贴子是关于STM32 DMA USART 发送模式的调试分享,我为什么要建这个帖子呢,因为我不想看到还有其他人跟我一样,为了调通DMA串口,而花上大半天的时间,这很不利于大家高效率的开发,网上的经验都是从头教到尾的,内容极多,对于有点小经验的人,或者是想很快达到目的的人,这个很不适合他们;我的这个很简单(本帖不适合不熟悉配置STM32串口的玩家),他只是说串口的DMA怎么配置,还有我用的是DMA1_通道4,因为我的是串口1的TX长话短说:直接po代码:   DMA_InitTypeDef DMA_InitStruct; //DMA类型声明   RCC_AHBPeriphC
[单片机]
MSP430 串口通讯
MSP430 串口1 实现即时通讯 芯片:430F169 现在市面上大多数单片机都自带串口,本章介绍如何建立430串口通讯 单片机通过接收口(URXD)和发送口(UTXD)和外界进行通讯 430F169自带串口0和串口1两个通讯口 串口通讯是基于系统时钟上进行的,系统时钟的配置可以参考我之前的系统时钟进行配置。 1 串口控制各种寄存器 1 UxCTL,串口控制寄存器 2 UxTCTL,串口传输控制寄存器 3 UxRCTL,串口接收控制寄存器 4 UxBR0,波特率控制寄存器0 5 UxBR1,波特率控制寄存器1 6 UxMCTL,调制控制寄存器 7 UxRXBUF,接收缓存寄存器 8 UxTXBUF,传
[单片机]
MSP430 <font color='red'>串口</font>通讯
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved