superw 发表于 2025-1-13 04:39

【Follow me第二季第3期】+项目总结

本帖最后由 superw 于 2025-1-13 12:37 编辑

<p>一、视频介绍</p>

<p><iframe allowfullscreen="true" frameborder="0" height="450" src="https://training.eeworld.com.cn/shareOpenCourseAPI?isauto=true&amp;lessonid=42421" style="background:#eee;margin-bottom:10px;" width="700"></iframe><br />
&nbsp;</p>

<p><!--importdoc--></p>

<p>二、任务实现详情</p>

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

<div>物料清单:EK-RA6M5</div>

<div></div>

<div>设计思路:</div>

<div>根据出厂示例程序,通过按键外部中断控制LED灯的亮度(占空比)和闪烁快慢(频率),将按键的GPIO配置为外部中断模式,每当按下时跳转到中断服务函数中,进行占空比和频率的切换。按键默认状态下被外部电阻上拉,当按下按键时,IO为低电平,因此要配置为下降沿触发中断。</div>

<div></div>

<div>对于占空比和频率的输出,通过配置内部定时器实现输出。</div>

<div></div>

<div>软件流程图:</div>

<div> &nbsp;</div>

<div>代码片段:</div>

<div>
<pre>
<code class="language-cpp">/**********************************************************************************************************************
* Function Name: button_irq10_callback
* Description: SW1 Interrupt handler.
* Argument   : p_args
* Return Value : None
*********************************************************************************************************************/
void button_irq10_callback(external_irq_callback_args_t *p_args)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    BaseType_t xResult = pdFAIL;
    EventBits_t uxBits;

    /* Void the unused args */
    FSP_PARAMETER_NOT_USED(p_args);

    uxBits = xEventGroupGetBitsFromISR (g_update_console_event);

    if ((uxBits &amp; (STATUS_UPDATE_INTENSE_INFO)) != (STATUS_UPDATE_INTENSE_INFO))
    {
      /* Cast, as compiler will assume calc is int */
      g_board_status.led_intensity = (uint16_t) ((g_board_status.led_intensity + 1) % 5);
      xResult = xEventGroupSetBitsFromISR(g_update_console_event, STATUS_UPDATE_INTENSE_INFO,
                                          &amp;xHigherPriorityTaskWoken);

      /* Was the message posted successfully? */
      if (pdFAIL != xResult)
      {
            /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context
             switch should be requested.The macro used is port specific and will
             be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
             the documentation page for the port being used. */
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
      }
    }
}
/**********************************************************************************************************************
End of function button_irq10_callback
*********************************************************************************************************************/

/* SW 2 */
/**********************************************************************************************************************
* Function Name: button_irq9_callback
* Description: SW2 interrupt handler.
* Argument   : p_args
* Return Value : None
*********************************************************************************************************************/
void button_irq9_callback(external_irq_callback_args_t *p_args)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    BaseType_t xResult = pdFAIL;
    EventBits_t uxBits;

    /* Void the unused args */
    FSP_PARAMETER_NOT_USED(p_args);

    uxBits = xEventGroupGetBitsFromISR (g_update_console_event);

    if ((uxBits &amp; (STATUS_UPDATE_FREQ_INFO)) != (STATUS_UPDATE_FREQ_INFO))
    {
      /* Cast, as compiler will assume calc is int */
      g_board_status.led_frequency = (uint16_t) ((g_board_status.led_frequency + 1) % 5);
      xResult = xEventGroupSetBitsFromISR(g_update_console_event, STATUS_UPDATE_FREQ_INFO, &amp;xHigherPriorityTaskWoken);

      /* Was the message posted successfully? */
      if (pdFAIL != xResult)
      {
            /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context
             switch should be requested.The macro used is port specific and will
             be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
             the documentation page for the port being used. */
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
      }
    }
}
/**********************************************************************************************************************
End of function button_irq9_callback
*********************************************************************************************************************/
</code></pre>

<pre>
<code class="language-cpp">uint32_t g_pwm_dcs =
{ LED_INTENSITY_10, LED_INTENSITY_30, LED_INTENSITY_50, LED_INTENSITY_70, LED_INTENSITY_90 };
uint32_t g_pwm_rates =
{ BLINK_FREQ_1HZ, BLINK_FREQ_3HZ, BLINK_FREQ_5HZ, BLINK_FREQ_7HZ, BLINK_FREQ_10HZ };

st_board_status_t g_board_status =
{ };

uint8_t g_pwm_dcs_data[] =
{ 10, 30, 50, 70, 90 };
uint8_t g_pwm_rates_data[] =
{ 1, 3, 5, 7, 10 };</code></pre>

<p>功能展示:</p>
</div>

<div></div>

<div></div>

<div>&nbsp;</div>

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

<div>物料清单:EK-RA6M5</div>

<div></div>

<div>设计思路:</div>

<div>EK-RA6M5板载有QSPI和OSPI存储器,QSPI Flash对应型号为MX25L25645G,采用四线SPI模式操作;OSPI Flash对应型号为MX25LM51245GM,采用八线SPI模式操作。开发板上内部已连接好线路,无需额外硬件连接。</div>

<div></div>

<div></div>

<div>关于QSPI的引脚和外设配置如下</div>

<div></div>

<div></div>

<div>关于OSPI的引脚和外设配置如下</div>

<div></div>

<div></div>

<div>同时,官方针对EK-RA6M5提供的fsp开发包里面也有关于QSPI和OSPI的相关例程,可以进行学习。</div>

<div>RA6M5芯片具有一个DAC外设,两个通道,可以分别输出不同的电压值或者波形。关于DAC的引脚和外设配置如下</div>

<div></div>

<div></div>

<div>软件流程图:</div>

<div> &nbsp;</div>

<div>代码片段:</div>

<div>
<pre>
<code class="language-cpp">block_size_actual = value;

    if ((MENU_ENTER_RESPONSE_CRTL == c) &amp;&amp; (0 != block_size_actual))
    {
      fsp_err_t      fsp_err;
      uint32_t       ospi_read_result= 0;
      uint32_t       ospi_write_result = 0;
      uint32_t       qspi_read_result= 0;
      uint32_t       qspi_write_result = 0;

      fsp_err = R_GPT_Open(g_memory_performance.p_ctrl, g_memory_performance.p_cfg);

      /* Handle error */
      if (FSP_SUCCESS != fsp_err)
      {
            /* Fatal error */
            SYSTEM_ERROR
      }

      sprintf(s_print_buffer, "\r\n\r\nGenerated a text block of %2lu KB in SRAM\r\n", block_size_actual);

      /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
      print_to_console((void*)s_print_buffer);

      /* ignoring -Wpointer-sign is OK for a constant string */
      print_to_console((uint8_t *)
                "\r\nWriting the text block to external Quad-SPI and Octo-SPI flash memories...\r\n");

      uint32_t ospi_performance_write_result = 0;
      uint32_t ospi_performance_read_result = 0;
      uint32_t timer_frequency;


      R_GPT_InfoGet(g_memory_performance.p_ctrl, &amp;timer_info);
      timer_frequency = timer_info.clock_frequency;

      ospi_performance_test (block_size_actual, &amp;ospi_performance_write_result, &amp;ospi_performance_read_result);

      /* Multiply uSec calcs by 100, to avoid losses due to small results in integer maths
         * Scaled to fit within uint32_t */
      ospi_write_result = ((100000000 / timer_frequency) * ospi_performance_write_result) / 100;
      qspi_write_result= ((100000000 / timer_frequency) * qspi_write_test(block_size_actual)) / 100;

      /* ignoring -Wpointer-sign is OK for a constant string */
      print_to_console((uint8_t *)"Writing to flash completed\r\n");

      /* ignoring -Wpointer-sign is OK for a constant string */
      print_to_console((uint8_t *)"\r\nReading the text block from external Quad-SPI and Octo-SPI flash memories...\r\n");

      ospi_read_result= ((100000000 / timer_frequency) * ospi_performance_read_result) / 100;
      qspi_read_result= ((100000000 / timer_frequency) * qspi_read_test(block_size_actual)) / 100;

      /* ignoring -Wpointer-sign is OK for a constant string */
      print_to_console((uint8_t *)"Reading from flash completed\r\n");

      R_GPT_Close(g_memory_performance.p_ctrl);

      /* Handle error */
      if (FSP_SUCCESS != fsp_err)
      {
            /* Fatal error */
            SYSTEM_ERROR
      }

      /* ignoring -Wpointer-sign is OK for a constant string */
      print_to_console((uint8_t *)"\r\n-------------------------------------------------");

      /* ignoring -Wpointer-sign is OK for a constant string */
      print_to_console((uint8_t *)"\r\nOperation/Flash   Quad-SPI       Octa-SPI");

      /* ignoring -Wpointer-sign is OK for a constant string */
      print_to_console((uint8_t *)"\r\n-------------------------------------------------");
      sprintf(s_print_buffer, "\r\nWrite                %6ld         %6ld", qspi_write_result , ospi_write_result);

      /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
      print_to_console((void*)s_print_buffer);
      sprintf(s_print_buffer, "\r\nRead               %6ld         %6ld", qspi_read_result , ospi_read_result);

      /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
      print_to_console((void*)s_print_buffer);

      /* ignoring -Wpointer-sign is OK for a constant string */
      print_to_console((uint8_t *)"\r\n-------------------------------------------------");

      /* ignoring -Wpointer-sign is OK for a constant string */
      print_to_console((uint8_t *)"\r\nNote: Times are in microseconds");
      sprintf(s_print_buffer, MENU_RETURN_INFO);

      /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
      print_to_console((void*)s_print_buffer);
    }

    while ((CONNECTION_ABORT_CRTL != c))
    {
      if ((MENU_EXIT_CRTL == c) || (0x00 == c))
      {
            break;
      }
      c = input_from_console();
    }</code></pre>

<p>功能展示:</p>
</div>

<div>分别对QSPI和OSPI写入32KB数据并读出,测试结果如下</div>

<div></div>

<div>&nbsp;</div>

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

<div>物料清单:EK-RA6M5</div>

<div></div>

<div>设计思路:</div>

<div>官方提供的出厂demo中已经预置了7条测试命令,包括USB、以太网等等,对于新增命令打印信息,找到官方实现的函数,依葫芦画瓢即可。</div>

<div>软件流程图:</div>

<div> &nbsp;</div>

<div>代码片段:</div>

<div>
<pre>
<code class="language-cpp">/* Table of menu functions */
static st_menu_fn_tbl_t s_menu_items[] =
{
    {"Kit Information"                         , kis_display_menu},
    {"Web Server"                              , eth_emb_display_menu},
    {"Network Name Lookup"                     , eth_www_display_menu},
    {"Quad-SPI and Octo-SPI Speed Comparison", ext_display_menu},
    {"Cryptography and USB High speed (MSC)"   , enc_display_menu},
    {"DAC &amp; DDS Test"   , dds_display_menu},
    {"Next Steps", ns_display_menu },
    {"", NULL }
};</code></pre>

<p>功能展示:</p>
</div>

<div></div>

<div>&nbsp;</div>

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

<div>物料清单:EK-RA6M5</div>

<div></div>

<div>设计思路:</div>

<div>扩展任务将和进阶任务中新增的命令、基础任务中使用DAC生成波形结合,共同实现通过串口命令行发送相应指令,开发板输出对应的波形。具体配置前面任务已经介绍过,不再介绍。</div>

<div>软件流程图:</div>

<div> &nbsp;</div>

<div>代码片段:</div>

<div>
<pre>
<code class="language-cpp">#include &lt;math.h&gt;

#define M_PI      3.14159265358979323846
uint16_t dac_val = 0;
uint8_t change_flag = 0;

/**********************************************************************************************************************
* Function Name: gpt_blue_callback
* Description: Callback function for driver g_gpt_blue.
* Argument   : p_args
* Return Value : .
*********************************************************************************************************************/
void gpt_blue_callback(timer_callback_args_t * p_args)
{
    /* Void the unused params */
    FSP_PARAMETER_NOT_USED(p_args);


    static double w = 0.0;
    w += M_PI / 30;
    if(w &gt;= M_PI*2)
    {
      w = 0.0;
    }
    dac_val = (sin(w)+1) /2 * 4095;
    change_flag = 1;

    //R_DAC_Write(&amp;g_dac0_ctrl, dac_val);

    switch (s_blueled_flashing)
    {
      case ON:
      {
            if ((s_intense++ ) &lt; s_duty)
            {
                TURN_BLUE_ON
            }
            else
            {
                TURN_BLUE_OFF
            }

            if (s_intense &gt;= 100)
            {
                s_intense = 0;
                s_duty = g_pwm_dcs;
            }
            break;
      }
      default:
      {
            TURN_BLUE_OFF
            s_intense = 0;
            s_duty = g_pwm_dcs;
      }
    }
}</code></pre>

<pre>
<code class="language-cpp">test_fn dds_display_menu(void)
{
    int8_t c = -1;

    sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);

    /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
    print_to_console((void*)s_print_buffer);

    sprintf (s_print_buffer, DDS_MODULE_NAME, g_selected_menu);

    /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
    print_to_console((void*)s_print_buffer);

    sprintf (s_print_buffer, DDS_SUB_OPTIONS);
    print_to_console((void*)s_print_buffer);

    /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
//    print_to_console((void*)s_print_buffer);
    sprintf (s_print_buffer, MENU_RETURN_INFO);

    /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
    print_to_console((void*)s_print_buffer);

    /* provide small delay so board_status should be up to date */
    vTaskDelay (s_ticks_to_wait);
    xEventGroupSetBits (g_update_console_event, STATUS_DISPLAY_MENU_KIS);

    while (CONNECTION_ABORT_CRTL != c)
    {
      c = input_from_console ();
      if ((MENU_EXIT_CRTL == c) || (CONNECTION_ABORT_CRTL == c))
      {
            break;
      }
      if(MENU_SIN_CRTL == c)
      {
            while(1)
            {

                  R_DAC_Write(&amp;g_dac0_ctrl, dac_val);

            }


      }
      else if(MENU_SQUARE_CRTL == c)
      {

      }
      else if(MENU_TRIANGULAR_CRTL == c)
      {

      }
    }

    xEventGroupClearBits (g_update_console_event, STATUS_DISPLAY_MENU_KIS);
    return (0);
}</code></pre>

<p>功能展示:</p>
</div>

<div>进入DAC&amp;DDS Test测试界面后,输入键盘上的小写字母a、b、c将分别通过DAC输出正弦波、方波、三角波。</div>

<div></div>

<div>示波器观察到的波形</div>

<div></div>

<div>&nbsp;</div>

<div><strong>心得体会</strong></div>

<div>非常感谢活动主办方提供这么棒的开发板供大家学习,个人感觉这次的难度是今年四期中最难的了,但是啃硬骨头啃完的感觉真爽,未来争取不让这块开发板吃灰,板载这么多外设,争取让它继续发光发热。</div>

<div>&nbsp;</div>

<div><span style="font-size:18px;"><strong>三、可编译下载的代码</strong></span></div>

<div><a href="https://download.eeworld.com.cn/detail/superw/635647" target="_blank">源工程下载</a></div>

<p><!--importdoc--></p>
页: [1]
查看完整版本: 【Follow me第二季第3期】+项目总结