linyu0395 发表于 2025-1-12 17:11

【Follow me第二季第3期】任务总汇

本帖最后由 linyu0395 于 2025-1-20 22:28 编辑

<p>开发板到手已经有一段时间了,瑞萨的这款EK-RA6M5虽然是首次尝试,但是入门和开发流程个人感觉比ST还快捷。开发环境我综合考虑了一下,相对于e2studio,还是通过RASC开发更方便,毕竟MDK也用的熟练。大家可以通过<a data-darkreader-inline-color="" href="https://github.com/renesas" style="color: rgb(70, 120, 134); text-decoration: underline; --darkreader-inline-color: #90d1e3;">https://github.com/renesas</a>进行下载。除了IDE安装文件,还有很多历程可以参考,特别是上手前期,通过丰富的例子可以加快对这块开发板的调试和使用。以下链接大家也可以参考。</p>

<p>&nbsp;</p>

<p> &nbsp;</p>

<ol>
        <li>FSP Webpage:&nbsp;<a data-darkreader-inline-color="" href="http://www.renesas.com/ra/fsp" style="color: rgb(70, 120, 134); text-decoration: underline; --darkreader-inline-color: #90d1e3;">www.renesas.com/ra/fsp</a></li>
        <li>FSP GitHub:&nbsp;<a data-darkreader-inline-color="" href="https://github.com/renesas/fsp" style="color: rgb(70, 120, 134); text-decoration: underline; --darkreader-inline-color: #90d1e3;">https://github.com/renesas/fsp</a></li>
        <li>FSP Releases:&nbsp;<a data-darkreader-inline-color="" href="https://github.com/renesas/fsp/releases" style="color: rgb(70, 120, 134); text-decoration: underline; --darkreader-inline-color: #90d1e3;">https://github.com/renesas/fsp/releases</a></li>
        <li>FSP Documentation:&nbsp;<a data-darkreader-inline-color="" href="https://renesas.github.io/fsp" style="color: rgb(70, 120, 134); text-decoration: underline; --darkreader-inline-color: #90d1e3;">https://renesas.github.io/fsp</a></li>
        <li>RA Product Information:&nbsp;<a data-darkreader-inline-color="" href="http://www.renesas.com/ra" style="color: rgb(70, 120, 134); text-decoration: underline; --darkreader-inline-color: #90d1e3;">www.renesas.com/ra</a></li>
        <li>RA/FSP Knowledge Base:&nbsp;<a data-darkreader-inline-color="" href="https://en-support.renesas.com/knowledgeBase/category/31087" style="color: rgb(70, 120, 134); text-decoration: underline; --darkreader-inline-color: #90d1e3;">https://en-support.renesas.com/knowledgeBase/category/31087</a></li>
        <li>Support:&nbsp;<a data-darkreader-inline-color="" href="http://www.renesas.com/support" style="color: rgb(70, 120, 134); text-decoration: underline; --darkreader-inline-color: #90d1e3;">www.renesas.com/support</a></li>
</ol>

<p>&nbsp;&nbsp;&nbsp;</p>

<p>4cfa391f3856d0f81b244b97bb666c51<br />
&nbsp;</p>

<p><br />
<br />
&nbsp;</p>

<p>任务软件流程图如下:</p>

<p> &nbsp;</p>

<p><span style="font-size:16px;">任务成果展示</span></p>

<ol>
        <li><b>入门任务:搭建环境,下载调试示例程序,Blink,按键</b></li>
</ol>

<p>&nbsp; &nbsp; &nbsp;安装Renesas RA Smart Configurator 5.7.0后,打开界面如下:</p>

<p><b>&nbsp;&nbsp;&nbsp; 选择了EK-RA6M5,里面包含了和开发板资源相关外设的IO、功能模块的初始化,接下来只要实例化就可以了。</b></p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p><b>本次任务需要实例化的外设,QSPI、OSPI、DAC等,通过下载的example里的实例就可以快速配置。</b></p>

<p>&nbsp;</p>

<p> &nbsp;</p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p><b>然后点击右上角的&ldquo;Generate Project Content&rdquo;生成MDK的项目工程</b></p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p><b>根据任务需求,我加入了qspi、ospi、dac_wave、rtt、按键、led的代码。</b></p>

<p>&nbsp;</p>

<p><b>2、基础任务:</b>quad-spi flash和octo-spi flash配置及读写速度测试;DAC配置生成波形及性能测试</p>

<p>QSPI的配置如下:</p>

<p> &nbsp;</p>

<pre>
<code class="language-cpp">#include &quot;qspi.h&quot;
#include &quot;hal_data.h&quot;
#include &quot;common_utils.h&quot;
#include &quot;qspi_ep.h&quot;

/*******************************************************************************************************************//**
*<a href="home.php?mod=space&amp;uid=159083" target="_blank">@brief </a>       wait for QSPI flash device status register to get idle till operation is in progress
*@param   None
*@retval      FSP_SUCCESS or any other possible error codes
**********************************************************************************************************************/
static fsp_err_t get_flash_status(void)
{
    spi_flash_status_t status = { .write_in_progress = true };
    int32_t time_out = (INT32_MAX);
    fsp_err_t err = FSP_SUCCESS;

    do
    {
      /* Get status from QSPI flash device */
      err = R_QSPI_StatusGet(&amp;g_qspi0_ctrl, &amp;status);
      if(FSP_SUCCESS != err)
      {
            APP_ERR_PRINT(&quot;R_QSPI_StatusGet Failed\r\n&quot;);
            return err;
      }

      /* Decrement time out to avoid infinite loop in case of consistent failure */
      --time_out;

      if(RESET_VALUE &gt;= time_out)
      {
            APP_PRINT(&quot;\r\n ** Timeout : No result from QSPI flash status register ** \r\n&quot;);
            return FSP_ERR_TIMEOUT;
      }

    }
    while(false != status.write_in_progress);

    return err;
}


/*******************************************************************************************************************//**
*@brief       Close QSPI module
*@param   spi_protocol mode
*@retval      None
**********************************************************************************************************************/
static void deinit_qspi(const spi_flash_protocol_t spi_protocol_mode)
{
    fsp_err_t error = FSP_SUCCESS;

    /* if QPI is active mode then Exit QPI mode from flash device before QSPI close */
    if(SPI_FLASH_PROTOCOL_QPI == spi_protocol_mode)
    {
      uint8_t data_exit_qpi = QSPI_MX25L_CMD_EXIT_QPI_MODE;

      APP_PRINT(&quot;\r\n ** Exit QPI mode before Closing QSPI module ** \r\n&quot;);

      error = R_QSPI_DirectWrite(&amp;g_qspi0_ctrl, &amp;data_exit_qpi, ONE_BYTE, false);
      if(FSP_SUCCESS != error)
      {
            APP_ERR_PRINT(&quot;R_QSPI_DirectWrite Failed\r\n&quot;);
      }
    }

    APP_PRINT(&quot;\r\n ** Closing QSPI module ** \r\n&quot;);

    /* close QSPI module */
    error = R_QSPI_Close(&amp;g_qspi0_cfg);
    if(FSP_SUCCESS != error)
    {
      APP_ERR_PRINT(&quot;R_QSPI_Close Failed\r\n&quot;);
    }

    APP_PRINT(&quot;\r\n\r\n *****############## demo ends here ########## *******\r\n\r\n&quot;);
}

/*******************************************************************************************************************//**
*@brief       set QPI Mode in flash device and MCU
*@param   none
*@retval      FSP_SUCCESS or any other possible error codes
**********************************************************************************************************************/
static fsp_err_t qpi_mode_set(void)
{
    fsp_err_t err = FSP_SUCCESS;
    uint8_t data_qpi_en = QSPI_MX25L_CMD_ENTER_QPI_MODE;

    APP_PRINT(&quot;\r\n ** setting QPI mode: sending QPI enabling command byte to flash ** \r\n&quot;);

    /* write enable once again section 9-1 states that
   * we should do it before sending 0x35 to flash device
   */
    err = R_QSPI_DirectWrite(&amp;g_qspi0_ctrl, &amp;(g_qspi0_cfg.write_enable_command), ONE_BYTE, false);
    if(FSP_SUCCESS != err)
    {
      APP_ERR_PRINT(&quot;R_QSPI_DirectWrite Failed\r\n&quot;);
      return err;
    }
    else
    {
      err = get_flash_status();
      if(FSP_SUCCESS != err)
      {
            APP_ERR_PRINT(&quot;Failed to get status for QSPI operation\r\n&quot;);
            return err;
      }
    }

    /* send QPI mode enable command in flash device
   * Note - no status register read after this operation
   * because flash device has gone in QPI mode
   * and MCU at this point is in extended SPI mode only.
   * vice versa same is applicable while exiting QPI mode too.
   */
    err = R_QSPI_DirectWrite(&amp;g_qspi0_ctrl, &amp;data_qpi_en, ONE_BYTE, false);
    if(FSP_SUCCESS != err)
    {
      APP_ERR_PRINT(&quot;R_QSPI_DirectWrite Failed\r\n&quot;);
      return err;
    }

    APP_PRINT(&quot;\r\n ** setting QPI mode:setting QPI mode in MCU** \r\n&quot;);

    /* Command byte transferred to flash-&gt; NOWset the QPI protocol in MCU run time */
    err = R_QSPI_SpiProtocolSet(&amp;g_qspi0_ctrl, SPI_FLASH_PROTOCOL_QPI);
    if(FSP_SUCCESS != err)
    {
      APP_ERR_PRINT(&quot;R_QSPI_SpiProtocolSet Failed\r\n&quot;);
    }

    return err;
}


void qspi_init(void)
{
    fsp_err_t err;
    uint8_t   data_sreg = STATUS_REG_PAYLOAD;

    if(SPI_FLASH_PROTOCOL_QPI == g_qspi0_cfg.spi_protocol)
    {
      spi_flash_cfg_t l_qspi_cfg;
      memcpy((spi_flash_cfg_t *)&amp;l_qspi_cfg, (spi_flash_cfg_t *)&amp;g_qspi0_cfg, sizeof(spi_flash_cfg_t));
      l_qspi_cfg.spi_protocol = SPI_FLASH_PROTOCOL_EXTENDED_SPI;
      err = R_QSPI_Open(&amp;g_qspi0_ctrl, &amp;l_qspi_cfg);
      if(FSP_SUCCESS != err)
      {
            APP_ERR_PRINT(&quot;R_QSPI_Open Failed\r\n&quot;);
            APP_ERR_TRAP(err);
      }
    }
    else
    {
      APP_PRINT(&quot;\r\n ** user selected extended SPI Mode in RA Configuration tool ** \r\n&quot;);

      /* open QSPI in extended SPI mode */
      err = R_QSPI_Open(&amp;g_qspi0_ctrl, &amp;g_qspi0_cfg);
      if(FSP_SUCCESS != err)
      {
            APP_ERR_PRINT(&quot;R_QSPI_Open Failed\r\n&quot;);
            APP_ERR_TRAP(err);
      }
    }

/* write enable for further operations */
    err = R_QSPI_DirectWrite(&amp;g_qspi0_ctrl, &amp;(g_qspi0_cfg.write_enable_command), ONE_BYTE, false);
    if(FSP_SUCCESS != err)
    {
      APP_ERR_PRINT(&quot;R_QSPI_DirectWrite Failed\r\n&quot;);
      /* close QSPI module which is currently in extended SPI mode only */
      deinit_qspi(SPI_FLASH_PROTOCOL_EXTENDED_SPI);
      APP_ERR_TRAP(err);
    }
    else
    {
      err = get_flash_status();
      if(FSP_SUCCESS != err)
      {
            APP_ERR_PRINT(&quot;Failed to get status for QSPI operation\r\n&quot;);
            /* close QSPI module which is currently in extended SPI mode only */
            deinit_qspi(SPI_FLASH_PROTOCOL_EXTENDED_SPI);
            APP_ERR_TRAP(err);
      }
    }

    /*
   * write QSPI flash status register
   * This is required to make sure the device is ready for general
   * read write operation,
   * This performs settings such as physical reset,WP hardware pin disable,
   * block protection lock bits clearing.
   * for more details please refer Mx25L data sheet.
   */
    err = R_QSPI_DirectWrite(&amp;g_qspi0_ctrl, data_sreg, SREG_SIZE, false);
    if(FSP_SUCCESS != err)
    {
      APP_ERR_PRINT(&quot;R_QSPI_DirectWrite Failed\r\n&quot;);
      /* close QSPI module which is currently in extended SPI mode only */
      deinit_qspi(SPI_FLASH_PROTOCOL_EXTENDED_SPI);
      APP_ERR_TRAP(err);
    }
    else
    {
      err = get_flash_status();
      if(FSP_SUCCESS != err)
      {
            APP_ERR_PRINT(&quot;Failed to get status for QSPI operation\r\n&quot;);
            /* close QSPI module which is currently in extended SPI mode only */
            deinit_qspi(SPI_FLASH_PROTOCOL_EXTENDED_SPI);
            APP_ERR_TRAP(err);
      }
    }

    /*
   * Verifying data written to QSPI flash status register
   * Step 1: - send command byte - 0x05
   * through R_QSPI_DirectWrite with last argument set as true
   * Step 2 - read data through R_QSPI_DirectRead
   */
    uint8_t sreg_data = RESET_VALUE;
    err = R_QSPI_DirectWrite(&amp;g_qspi0_ctrl, &amp;(g_qspi0_cfg.status_command), ONE_BYTE, true);
    if(FSP_SUCCESS != err)
    {
      APP_ERR_PRINT(&quot;R_QSPI_DirectWrite Failed\r\n&quot;);
      /* close QSPI module which is currently in extended SPI mode only */
      deinit_qspi(SPI_FLASH_PROTOCOL_EXTENDED_SPI);
      APP_ERR_TRAP(err);
    }

    /*
   *we should not call function get_flash_status here
   * because the CS line should not get interrupted between write read
   *
   * Also MCU &lt;SFMCD register&gt; is set as 0 when status register is read
   * to resume in ROM access mode hence API direct read returns error as part
   * of parameter check itself
   */
    err = R_QSPI_DirectRead(&amp;g_qspi0_ctrl, &amp;sreg_data, ONE_BYTE);
    if(FSP_SUCCESS != err)
    {
      APP_ERR_PRINT(&quot;R_QSPI_DirectRead Failed\r\n&quot;);
      /* close QSPI module which is currently in extended SPI mode only */
      deinit_qspi(SPI_FLASH_PROTOCOL_EXTENDED_SPI);
      APP_ERR_TRAP(err);
    }
    else
    {
      /* check for status check operation here */
      err = get_flash_status();
      if(FSP_SUCCESS != err)
      {
            APP_ERR_PRINT(&quot;Failed to get status for QSPI operation\r\n&quot;);
            /* close QSPI module which is currently in extended SPI mode only */
            deinit_qspi(SPI_FLASH_PROTOCOL_EXTENDED_SPI);
            APP_ERR_TRAP(err);
      }
    }

    /* verify read status register data */
    if(SET_SREG_VALUE != sreg_data)
    {
      APP_ERR_PRINT(&quot;Failed to get value set in the status register \r\n&quot;);
      /* close QSPI module which is currently in extended SPI mode only */
      deinit_qspi(SPI_FLASH_PROTOCOL_EXTENDED_SPI);
      APP_ERR_TRAP(err);
    }

    if(SPI_FLASH_PROTOCOL_QPI == g_qspi0_cfg.spi_protocol)
    {
      /* set QPI mode in flash and MCU device */
      err = qpi_mode_set();
      if(FSP_SUCCESS != err)
      {
            APP_ERR_PRINT(&quot;qpi_mode_set failed\r\n&quot;);
            /* close QSPI module which is currently in extended SPI mode only */
            deinit_qspi(SPI_FLASH_PROTOCOL_EXTENDED_SPI);
            APP_ERR_TRAP(err);
      }
    }
}


void qspi_erase_sector(uint32_t sector_index, uint32_t sector_nums)
{
    uint8_t *p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS;
    fsp_err_t err;
    /* Erase Flash for one sector */
    err = R_QSPI_Erase(&amp;g_qspi0_ctrl, p_mem_addr + sector_index * SECTOR_SIZE, sector_nums * SECTOR_SIZE);
    if(FSP_SUCCESS != err)
    {
      APP_ERR_PRINT(&quot;R_QSPI_Erase Failed\r\n&quot;);
      deinit_qspi(g_qspi0_cfg.spi_protocol);
      APP_ERR_TRAP(err);
    }
    else
    {
      err = get_flash_status();
      if(FSP_SUCCESS != err)
      {
            APP_ERR_PRINT(&quot;Failed to get status for QSPI operation\r\n&quot;);
            deinit_qspi(g_qspi0_cfg.spi_protocol);
            APP_ERR_TRAP(err);
      }

      /* validating erase */
      for(uint16_t mem_index = RESET_VALUE; mem_index &lt; SECTOR_SIZE; mem_index++)
      {
            if(DEFAULT_MEM_VAL != p_mem_addr)
            {
                APP_ERR_PRINT(&quot;\r\n Verification for erase Failed \r\n&quot;);
                deinit_qspi(g_qspi0_cfg.spi_protocol);
                APP_ERR_TRAP(err);
            }
      }
    }
}


void qspi_read(uint32_t addr, uint8_t *data, uint32_t size)
{
    memcpy(data, (uint8_t *)QSPI_DEVICE_START_ADDRESS, size);
}


void qspi_write(uint32_t addr, uint8_t *data, uint32_t size)
{
    uint32_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
    /*mod 运算求余,若 writeAddr 是 SPI_FLASH_PageSize 整数倍,运算结果 Addr 值为
    0*/
    Addr = addr % PAGE_WRITE_SIZE;
    /* 差 count 个数据值,刚好可以对齐到页地址 */
    count = PAGE_WRITE_SIZE - Addr;
    /* 计算出要写多少整数页 */
    NumOfPage = size / PAGE_WRITE_SIZE;
      /*mod 运算求余,计算出剩余不满一页的字节数 */
    NumOfSingle = size % PAGE_WRITE_SIZE;
    /* Addr=0, 则 WriteAddr 刚好按页对齐 aligned
    */
    if(Addr == 0)
    {
      /* NumByteToWrite &lt; SPI_FLASH_PageSize */
      if(NumOfPage == 0)
      {
            R_QSPI_Write(&amp;g_qspi0_ctrl, data, addr, size);
            get_flash_status();
      }
      else /* NumByteToWrite &gt; SPI_FLASH_PageSize */
      {
      /* 先把整数页都写了 */
            while(NumOfPage--)
            {
                R_QSPI_Write(&amp;g_qspi0_ctrl, data, addr, PAGE_WRITE_SIZE);
                get_flash_status();
                addr += PAGE_WRITE_SIZE;
                data += PAGE_WRITE_SIZE;
            }
            /* 若有多余的不满一页的数据,把它写完 */
            R_QSPI_Write(&amp;g_qspi0_ctrl, data, addr, NumOfSingle);
            get_flash_status();
      }
    }
    /* 若地址与 SPI_FLASH_PageSize 不对齐
    */
    else
    {
    /* NumByteToWrite &lt; SPI_FLASH_PageSize */
      if(NumOfPage == 0)
      {
/* 当前页剩余的 count 个位置比 NumOfSingle 小,一页写不完 */
            if(NumOfSingle &gt; count)
            {
                temp = NumOfSingle - count;
                /* 先写满当前页 */
                R_QSPI_Write(&amp;g_qspi0_ctrl, data, addr, count);
                get_flash_status();
                addr += count;
                data += count;
                /* 再写剩余的数据 */
                R_QSPI_Write(&amp;g_qspi0_ctrl, data, addr, temp);
                get_flash_status();
            }
            else /* 当前页剩余的 count 个位置能写完 NumOfSingle 个数据 */
            {
                R_QSPI_Write(&amp;g_qspi0_ctrl, data, addr, size);
                get_flash_status();
            }
      }
      else /* NumByteToWrite &gt; SPI_FLASH_PageSize */
      {
      /* 地址不对齐多出的 count 分开处理,不加入这个运算 */
            size -= count;
            NumOfPage = size / PAGE_WRITE_SIZE;
            NumOfSingle = size % PAGE_WRITE_SIZE;
            /* 先写完 count 个数据,为的是让下一次要写的地址对齐 */
            R_QSPI_Write(&amp;g_qspi0_ctrl, data, addr, count);
            get_flash_status();
            /* 接下来就重复地址对齐的情况 */
            addr += count;
            data += count;
            /* 把整数页都写了 */
            while(NumOfPage--)
            {
                R_QSPI_Write(&amp;g_qspi0_ctrl, data, addr, PAGE_WRITE_SIZE);
                get_flash_status();
                addr += PAGE_WRITE_SIZE;
                data += PAGE_WRITE_SIZE;
            }
            /* 若有多余的不满一页的数据,把它写完 */
            if(NumOfSingle != 0)
            {
                R_QSPI_Write(&amp;g_qspi0_ctrl, data, addr, NumOfSingle);
                get_flash_status();
            }
      }
    }
}</code></pre>

<p>&nbsp;</p>

<p>OSPI的配置如下:</p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<pre>
<code class="language-cpp">#include "ospi_test.h"
#include "ospi_commands.h"
#include "ospi_ep.h"
#include "common_utils.h"
#include "dac_wave.h"
#include "qspi.h"

void reset_device()
{
    /* OSPI Memory reset Pin */
    R_IOPORT_PinWrite(&amp;g_ioport_ctrl, RESET_PIN, BSP_IO_LEVEL_LOW);
    R_BSP_SoftwareDelay(DELAY_TIME, BSP_DELAY_UNITS_MICROSECONDS);
    R_IOPORT_PinWrite(&amp;g_ioport_ctrl, RESET_PIN, BSP_IO_LEVEL_HIGH);
    R_BSP_SoftwareDelay(DELAY_TIME, BSP_DELAY_UNITS_MICROSECONDS);
}

uint8_t write_data = { 0 };
uint8_t read_data = { 0 };
uint32_t qspi_tick;
uint32_t qspi_period_tick;

void ospi_test(void)
{
    fsp_pack_version_t version = { RESET_VALUE };
    fsp_err_t          err = FSP_SUCCESS;
    uint8_t            read_data = RESET_VALUE;
    uint32_t         dev_id = RESET_VALUE;
    bsp_octaclk_settings_t octaclk = { RESET_VALUE };

/* Reset device */
    // reset_device();
/* Upon power-on or reset, the device defaults to SPI mode.
   * To ensure proper operation, the OCTACLK clock should be configured to 100 MHz in SPI mode.
   * Because OM_SCLK (OM_SCLK = OCTACLK/2) only support 50MHz as max.
   */
    octaclk.source_clock = BSP_CFG_OCTA_SOURCE;/* 200MHz */
    octaclk.divider = BSP_CLOCKS_OCTA_CLOCK_DIV_2;
    R_BSP_OctaclkUpdate(&amp;octaclk);

    /* Initialize the OSPI driver module.*/
    err = ospi_init();
    if(FSP_SUCCESS != err)
    {
      APP_ERR_PRINT("\r\n** OSPI INIT FAILED **\r\n");
      APP_ERR_TRAP(err);
    }

    /*Enable Write */
    err = ospi_write_enable_and_verify(&amp;g_ospi_ctrl, SPI_FLASH_PROTOCOL_EXTENDED_SPI);
    if(FSP_SUCCESS != err)
    {
      /*handle error*/
      handle_error(err, "\r\n** OSPI Write Enable and Verify failed **\r\n");
    }

    /* configure ospi in extended spi mode */
    err = reconfigure_device();
    if(FSP_SUCCESS != err)
    {
      /*handle error*/
      handle_error(err, "\r\n** Reconfiguring OSPI device failed**\r\n");
    }

    /*Read the device id*/
    err = read_device_id(&amp;dev_id);
    if(FSP_SUCCESS != err)
    {
      /*handle error*/
      handle_error(err, "\r\n** Device_ID read operation failed **\r\n");
    }

    /* Reset the OCTACLK clock to 200 MHz, as specified by the default configuration.*/
    octaclk.source_clock = BSP_CFG_OCTA_SOURCE;/* 200MHz */
    octaclk.divider = BSP_CFG_OCTA_DIV;
    R_BSP_OctaclkUpdate(&amp;octaclk);

    /*Print device id and main menu*/
    APP_PRINT("\nDevice ID read successfully and Device id : 0x%X\r\n", dev_id);
    APP_PRINT(OSPI_MENU);


    while(true)
    {
      /* read user input */
      read_data = process_input_data();
      switch(read_data)
      {
            case QSPI_MODE:
                qspi_tick = get_tick();
                qspi_erase_sector(0, 1);
                APP_PRINT("\nQSPI operation erase sector successfully\r\n");
                qspi_write(0, write_data, sizeof(write_data));
                APP_PRINT("\nQSPI operation write successfully\r\n");
                qspi_read(0, read_data, sizeof(read_data));
                APP_PRINT("\nQSPI operation read successfully\r\n");
                qspi_period_tick = get_tick() - qspi_tick;
                APP_PRINT("\nQSPI operation completed in %d ms\r\n", qspi_period_tick);
                break;
            case DAC_RECT_MODE:
                generate_square_wave(buffer, BUFFER_SIZE, 500);
                // generate_triangle_wave(buffer, BUFFER_SIZE, 100);
                // generate_sine_wave(buffer, BUFFER_SIZE, 10);
                break;
            case DAC_SIN_MODE:
                generate_sine_wave(buffer, BUFFER_SIZE, 10);
                break;
                /*Perform Extended SPI Operation*/
            case SPI_MODE:
            {
                err = spi_operation();
                /*handle error*/
                handle_error(err, "\r\n** SPI Operation failed **\r\n");
                break;
            }

            /*Perform SOPI operation*/
            case SOPI_MODE:
            {
                err = opi_operation(SOPI_OPERATION_MODE);
                /*handle error*/
                handle_error(err, "\r\n** SOPI Operation failed **\r\n");
                break;
            }

            /*Perform DOPI operation*/
            case DOPI_MODE:
            {
                err = opi_operation(DOPI_OPERATION_MODE);
                /*handle error*/
                handle_error(err, "\r\n** DOPI Operation failed **\r\n");
                break;
            }

            default:
            {
                APP_PRINT("\r\n Invalid input. Provide a valid input\r\n");
                break;
            }

      }
      /*reset data */
      read_data = RESET_VALUE;
      /* Print Main Menu option of OSPI operation.*/
      APP_PRINT(OSPI_MENU);
    }

}</code></pre>

<p>DAC的配置如下:</p>

<p>DAC通过P014输出</p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>按键、LED</p>

<pre>
<code class="language-cpp">#include "key.h"

uint8_t led_state;

void LED_ON()   //LED1 亮
{
    R_IOPORT_PinWrite(&amp;g_ioport_ctrl, LED1_PIN, BSP_IO_LEVEL_HIGH);
}

uint32_t Key_Scan(bsp_io_port_pin_t key)
{
    bsp_io_level_t state;
    // 读取按键引脚电平
    R_IOPORT_PinRead(&amp;g_ioport_ctrl, key, &amp;state);
    if(BSP_IO_LEVEL_HIGH == state)
    {
      return KEY_OFF; //按键没有被按下
    }
    else
    {
      do
      //等待按键释放
      {
            R_IOPORT_PinRead(&amp;g_ioport_ctrl, key, &amp;state);
      }
      while(BSP_IO_LEVEL_LOW == state);
    }
    return KEY_ON; //按键被按下了
}

void Key_Poll(void)
{
    static uint8_t key_status;
    if(Key_Scan(KEY1_PIN) == KEY_ON)
//扫描按键 1
    {
      if(key_status)
      {
            LED1_ON();
            key_status = 0;
      }
      else
      {
            LED1_OFF();
            key_status = 1;
      }
    }
    if(Key_Scan(KEY2_PIN) == KEY_ON)
    //扫描按键 2
    {
      if(key_status)
      {
            LED2_ON();
            key_status = 0;
      }
      else
      {
            LED2_OFF();
            key_status = 1;
      }
    }
}</code></pre>

<pre>
<code class="language-cpp">#ifndef _KEY_H_
#define _KEY_H_

#include &lt;stdint.h&gt;
#include "hal_data.h"


/* 定义宏 KEY_ON 表示按键按下
定义宏 KEY_OFF 表示按键没有按下
*/
#define KEY_ON1
#define KEY_OFF 0


#define KEY1_PIN   BSP_IO_PORT_00_PIN_04
#define KEY2_PIN   BSP_IO_PORT_00_PIN_05

#define LED1_PIN   BSP_IO_PORT_00_PIN_07
#define LED2_PIN   BSP_IO_PORT_00_PIN_08

#define LED1_ON()R_IOPORT_PinWrite(&amp;g_ioport_ctrl, LED1_PIN, BSP_IO_LEVEL_HIGH)
#define LED1_OFF() R_IOPORT_PinWrite(&amp;g_ioport_ctrl, LED1_PIN, BSP_IO_LEVEL_LOW)
// #define LED1_TOGGLE() R_IOPORT_PinWrite(&amp;g_ioport_ctrl, LED1_PIN, !R_IOPORT_PinRead(&amp;g_ioport_ctrl, LED1_PIN, &amp;led_state))

#define LED2_ON()R_IOPORT_PinWrite(&amp;g_ioport_ctrl, LED2_PIN, BSP_IO_LEVEL_HIGH)
#define LED2_OFF() R_IOPORT_PinWrite(&amp;g_ioport_ctrl, LED2_PIN, BSP_IO_LEVEL_LOW)
// #define LED2_TOGGLE() R_IOPORT_PinWrite(&amp;g_ioport_ctrl, LED2_PIN, !R_IOPORT_PinRead(&amp;g_ioport_ctrl, LED2_PIN, &amp;led_state))

extern uint8_t led_state;


uint32_t Key_Scan(bsp_io_port_pin_t key);
void Key_Poll(void);


#endif</code></pre>

<p>3、进阶任务:示例程序中新增命令打印信息</p>

<p> &nbsp;</p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p>4、扩展任务:设计一个类似信号发生器功能的例程。可在示例程序上修改。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息</p>

<p>&nbsp; &nbsp; 此任务已经通过视频演示输出方波和正弦波。</p>

<pre>
<code class="language-cpp">#include "dac_wave.h"
#include "hal_data.h"
#include &lt;math.h&gt;
#include &lt;stdint.h&gt;
#include "r_dac.h"




uint8_t dac_init_flag = 0;

uint16_t buffer;
uint32_t buffer_index;

void dac_output(uint16_t value);



void generate_square_wave(uint16_t *buf, uint32_t length, uint32_t frequency)
{
    uint32_t period = (uint32_t)(SAMPLE_RATE / frequency);
    for(uint32_t i = 0; i &lt; length; i++)
    {
      buf = (uint16_t)((i % period &lt; period / 2) ? AMPLITUDE : 0);
    }
}

void generate_triangle_wave(uint16_t *buf, uint32_t length, uint32_t frequency)
{
    uint32_t period = (uint32_t)(SAMPLE_RATE / frequency);
    for(uint32_t i = 0; i &lt; length; i++)
    {
      uint32_t pos = i % period;
      if(pos &lt; period / 2)
      {
            buf = (uint16_t)((2 * AMPLITUDE * pos) / (period / 2));
      }
      else
      {
            buf = (uint16_t)(2 * AMPLITUDE - (2 * AMPLITUDE * (pos - period / 2)) / (period / 2));
      }
    }
}

void generate_sine_wave(uint16_t *buf, uint32_t length, uint32_t frequency)
{
    float increment = 2 * PI * frequency / SAMPLE_RATE;
    for(uint32_t i = 0; i &lt; length; i++)
    {
      buf = (uint16_t)(AMPLITUDE * (1 + sin(increment * i)) / 2);
    }
}

// 定时器中断服务程序
void dac_timer_isr(void)
{
    if(dac_init_flag)
    {
/* Write value to DAC module */
      R_DAC_Write(&amp;g_dac_ctrl, buffer);
      /* handle error */

      /* Start DAC conversion */
      R_DAC_Start(&amp;g_dac_ctrl);
      /* handle error */
      //dac_output(buffer);
      buffer_index = (buffer_index + 1) % BUFFER_SIZE;
    }
}

void start_waveform_output(float frequency, void (*generate_wave)(uint16_t *, uint32_t, float))
{
    generate_wave(buffer, BUFFER_SIZE, frequency);
    buffer_index = 0;
    // 启动定时器,配置定时器中断频率为 SAMPLE_RATE
    //start_timer(SAMPLE_RATE);
}

//void start_timer(uint32_t sample_rate)
//{
// 配置并启动定时器,使其以 sample_rate 频率触发中断
// 具体实现取决于你的硬件平台
//}


void dav_wave_init(void)
{
    fsp_err_t err = FSP_SUCCESS;
    err = R_DAC_Open(&amp;g_dac_ctrl, &amp;g_dac_cfg);

    // generate_square_wave(buffer, BUFFER_SIZE, 1000);
    dac_init_flag = 1;
}</code></pre>

<pre>
<code class="language-cpp">#ifndef _DAC_WAVE_H_
#define _DAC_WAVE_H_

#include &lt;stdint.h&gt;


#define PI 3.14159265
#define SAMPLE_RATE 1000
#define AMPLITUDE 2048
#define BUFFER_SIZE 1000

extern uint16_t buffer;
extern uint32_t buffer_index;

void dac_timer_isr(void);
void dav_wave_init(void);
void generate_square_wave(uint16_t *buf, uint32_t length, uint32_t frequency);
void generate_triangle_wave(uint16_t *buf, uint32_t length, uint32_t frequency);
void generate_sine_wave(uint16_t *buf, uint32_t length, uint32_t frequency);


#endif

</code></pre>

<p>总结:瑞萨的EK-RA6M5的上手非常快,开发有大量丰富的历程参考,无论对于新手还是老手,都是非常适合的。资源丰富,带网络、LCD驱动、多路FDCAN等还需要细细研究。后续有更新的话再和大家一起分享,谢谢!</p>

<p>&nbsp;</p>

<p>&nbsp;代码附件:</p>

<div></div>

Jacktang 发表于 2025-1-13 07:45

<p>瑞萨的这款EK-RA6M5的开发流程确实比ST的开发比较快捷,这确实是经验之谈</p>
页: [1]
查看完整版本: 【Follow me第二季第3期】任务总汇