fastjs

  • 2024-12-10
  • 加入了学习《Follow me第二季第3期演示视频》,观看 Follow me第二季第3期演示视频

  • 回复了主题帖: 【Follow me第二季第3期】EK-RA6M5所有任务汇总

    最后用到的是简易示波器啦

  • 2024-11-20
  • 发表了主题帖: 【Follow me第二季第3期】EK-RA6M5所有任务汇总

    本帖最后由 fastjs 于 2024-11-20 20:10 编辑 很荣幸参与【Follow me第二季第3期】,这期活动的开发板为EK-RA6M5,是一款由瑞萨官方开发的评估套件。 一、演示视频 Follow me第二季第3期演示视频-Follow me第二季第3期演示视频-EEWORLD大学堂 二、任务介绍 任务简介 入门任务:搭建环境,下载调试示例程序,Blink,按键; 基础任务:quad-spi flash和octo-spi flash配置及读写速度测试;DAC配置生成波形及性能测试; 进阶任务:示例程序中新增命令打印信息; 扩展任务:设计一个类似信号发生器功能的例程。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息。 物料清单 物料为EK-RA6M5开发板和MicroUSB线缆。   设计思路 通过USB虚拟串口传输指令,从而实现各个功能,比如调整DAC输出电压的值,以生成波形;存储波形数据,读取波形数据。通过接收命令,可以调整DAC的输出参数,例如增大或减小波形参数的值(范围为0-4095),从而动态生成所需的波形。指令 a 和 s 用于实时增减波形参数,便于快速调整输出。存储功能使用 Quad-SPI 闪存,指令 w 将当前波形数据写入闪存以便保存历史记录,指令r 则从闪存中加载存储的波形数据到内存缓冲区,实现快速回放。启动功能通过 g 指令激活波形发生器,开始输出设定的波形数据。   三、软件流程图   四、实现细节 示例程序为ek_ra6m5/_quickstart下的quickstart_ek_ra6m5_ep工程。 任务一 入门任务 开发环境搭建e2 studio 打开示例程序编译后,右键工程,选择Debug As -> Renesas GDB Hardware Debugging下载程序   编译项目时,由于示例代码所使用的FSP版本问题,可能会报错,修改BSP_CLOCKS_PLL_MUL_10_0为BSP_CLOCKS_PLL_MUL(10, 0)即可。   下载好示例程序后,会发现LED初始设置为 LED1 (蓝色):以1 Hz频率闪烁,亮度为10%。 LED2 (绿色):常亮且亮度最大。 LED3 (红色):关闭。 LED5 (调试LED):忽略其橙色闪烁或点亮状态。 此时按下用户按钮S1,会改变LED1的亮度,每次按下依次切换为10%、50%和90%循环;按下用户按钮S2:改变LED1的闪烁频率,每次按下依次切换为1 Hz、5Hz和10 Hz循环。 点灯代码,其中代码中的GPT 是指 General Purpose Timer(通用定时器) // 更改LED亮度 void gpt_blue_callback(timer_callback_args_t * p_args) { /* Void the unused params */ FSP_PARAMETER_NOT_USED(p_args); switch (s_blueled_flashing) { case ON: { if ((s_intense++ ) < s_duty) { TURN_BLUE_ON } else { TURN_BLUE_OFF } if (s_intense >= 100) { s_intense = 0; s_duty = g_pwm_dcs[g_board_status.led_intensity]; } break; } default: { TURN_BLUE_OFF s_intense = 0; s_duty = g_pwm_dcs[g_board_status.led_intensity]; } } } // 更改LED闪烁频率 { if ((s_ux_bits & (STATUS_UPDATE_FREQ_INFO)) == (STATUS_UPDATE_FREQ_INFO)) { R_GPT_PeriodSet (g_blinker.p_ctrl, g_pwm_rates[g_board_status.led_frequency]); /* Clear Event */ xEventGroupClearBits (g_update_console_event, (STATUS_UPDATE_FREQ_INFO)); } }   按键控制灯代码,按键由外部中断实现 /* SW 1 */ 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 & (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) % 3); xResult = xEventGroupSetBitsFromISR(g_update_console_event, STATUS_UPDATE_INTENSE_INFO, &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); } } } /* SW 2 */ 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 & (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) % 3); xResult = xEventGroupSetBitsFromISR(g_update_console_event, STATUS_UPDATE_FREQ_INFO, &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); } } }     任务二 基础任务 任务2的flash测试功能已经在示例代码中实现了,这里展示配置及测试的核心代码,测试效果如下 quad-spi flash配置代码为示例代码menu.ext.c中的qpi_init(void)函数 octo-spi flash配置代码为示例代码ospi_test.c中configure_dopi_ospi()函数 quad-spi flash和octo-spi flash读写速度测试代码 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, &timer_info); timer_frequency = timer_info.clock_frequency; ospi_performance_test (block_size_actual, &ospi_performance_write_result, &ospi_performance_read_result); ospi_write_result = ((100000000 / timer_frequency) * ospi_performance_write_result) / 100; qspi_write_result = ((100000000 / timer_frequency) * qspi_write_test(block_size_actual)) / 100; print_to_console((uint8_t *)"Writing to flash completed\r\n"); 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; print_to_console((uint8_t *)"Reading from flash completed\r\n"); R_GPT_Close(g_memory_performance.p_ctrl);       对于DAC波形生成,使用DAC的示例文件 DAC输出端口P014,对应Arduino_A4 ADC输入端口P000,对应MIKROBUS_AN_ARDUINO_A0 用杜邦线连接P014和P000,下载代码后运行效果如下 观察到ADC通道一读取的值随着设定的DAC的增加而增加。 DAC配置生成波形及性能测试代码 static fsp_err_t dac_adc_operations(int32_t * input) { fsp_err_t err = FSP_SUCCESS; // Error status /* Write value to DAC module */ err = R_DAC_Write (&g_dac_ctrl, (uint16_t) (* input)); /* handle error */ if (FSP_SUCCESS != err) { /* dac Write Failure message */ APP_ERR_PRINT("** DAC Write API failed ** \r\n"); return err; } /* Start DAC conversion */ err = R_DAC_Start (&g_dac_ctrl); /* handle error */ if (FSP_SUCCESS != err) { /* dac start failure message */ APP_ERR_PRINT("** DAC Start API failed ** \r\n"); return err; } /* Start the ADC scan in Single scan mode*/ err = R_ADC_ScanStart (&g_adc_ctrl); /* handle error */ if (FSP_SUCCESS != err) { /* ADC Scan Failure message */ APP_ERR_PRINT("** ADC ScanStart API failed ** \r\n"); return err; } /* Stop and start DAC conversion for consecutive user input values*/ err = R_DAC_Stop(&g_dac_ctrl); /* Handle Error */ if (FSP_SUCCESS != err) { /* DAC stop failure message */ APP_ERR_PRINT("** DAC Stop API failed ** \r\n"); } return err; }   任务三 进阶任务 新增命令打印信息 初始打印信息为   添加打印信息后,删除了暂时用不到的打印命令,显示效果如下,   按4,进入新增的第四个选项,输入字符串,按下Tab键后,将打印该字符串。 此部分核心代码如下。 block_sz_ndx = 0; memset(&s_block_sz_str, 0, INPUT_BUFFER); while (false == valid_block_size) { print_to_console("input: "); while ((CONNECTION_ABORT_CRTL != c)) { c = input_from_console (); if (block_sz_ndx < block_sz_limit) { s_block_sz_str[block_sz_ndx] = (char_t)c; block_sz_ndx++; } else { s_block_sz_str[block_sz_ndx] = MENU_ENTER_RESPONSE_CRTL; c = MENU_ENTER_RESPONSE_CRTL; } if (MENU_ENTER_RESPONSE_CRTL == c) { print_to_console("\r\noutput: "); s_block_sz_str[block_sz_ndx - 1] = '\r'; s_block_sz_str[block_sz_ndx] = '\n'; print_to_console((void*)s_block_sz_str); block_sz_ndx = 0; memset(&s_block_sz_str, 0, INPUT_BUFFER); break; } if (MENU_EXIT_CRTL == c) { valid_block_size = true; block_size_actual = 0; break; } if (CARRAGE_RETURN != c) { sprintf(s_print_buffer, "%c", (char_t)c); print_to_console((void*)s_print_buffer); } } if ((MENU_EXIT_CRTL == c) || (CONNECTION_ABORT_CRTL == c)) { break; } }   任务四 扩展任务 QSPI FLASH型号为MX25L25645G,OSPI FLASH型号为MX25LM51245GM,本次任务将波形信息存储到QSPI FLASH中。QSPI 使用6 个信号连接Flash,分别是四个数据线QIO0~QIO3,一个时钟输出SCLK,一个片选输出(低电平有效)CS#。 设置默认dac输出值为{ 2048, 2460, 2856, 3218, 3532, 3786, 3969, 4072, 4093, 4031, 3887, 3668, 3382, 3042, 2661, 2255, 1841, 1435, 1054, 714, 428, 209, 65, 3, 24, 127, 310, 564, 878, 1240, 1636, 2048 }; 这将输出一个正弦波,当输入指令时,其中的值发生增大或减小固定的值,但每个值范围在0-4095间,指令设计为 'a' - 增加波形参数 's' - 减少波形参数 'r' - 从 Quad-SPI 闪存读取波形数据到内存缓冲区 'w' - 将当前波形数据写入 Quad-SPI 闪存存储 'g' - 启动波形发生器 键入指令后,输入Tab键即可执行对应功能。 波形发生器界面 设置DAC输出波形 void DAC_Init() { R_DAC_Open(&g_dac0_ctrl, &g_dac0_cfg); R_DAC_Start(&g_dac0_ctrl); } void DAC_SinWave_Cycle(uint32_t time_interval) { for(uint32_t i = 0 ; i < (sizeof(custom_var)/sizeof(custom_var[0])); i++) { R_DAC_Write(&g_dac0_ctrl, custom_var[i]); R_BSP_SoftwareDelay(time_interval, BSP_DELAY_UNITS_MILLISECONDS); } } 在flash存储历史波形 /** * @brief 将波形数据存储到 Quad Flash * @param buffer 需要存储的波形 * @retval 无 */ void Write_Waveform_To_Flash(uint16_t *buffer) { fsp_err_t err = FSP_SUCCESS; uint32_t page_write_count = 0; uint8_t *p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS; spi_flash_protocol_t current_spi_mode; /* Cast to req type */ p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS; /* 打开 QSPI 模块 */ // err = R_QSPI_Open(&g_qspi_ctrl, &g_qspi_cfg); // if (FSP_SUCCESS != err) // { // sprintf(s_print_buffer, "Failed to open QSPI module\r\n"); // return; // } /* initialise the QSPI, and change mode to that set in FSP */ err = qpi_init(); if (FSP_SUCCESS == err) { /* The comms mode has changed. So if recovering, this new mode required */ current_spi_mode = g_qspi_cfg.spi_protocol; } /* 擦除 QSPI 的指定扇区 */ err = R_QSPI_Erase(&g_qspi_ctrl, p_mem_addr, SECTOR_SIZE); if (FSP_SUCCESS != err) { sprintf(s_print_buffer, "Failed to erase QSPI flash\r\n"); return; } /* 等待擦除完成 */ err = get_flash_status(); if (FSP_SUCCESS != err) { sprintf(s_print_buffer, "Failed to get flash status after erase\r\n"); return; } /* 逐页写入波形数据 */ while (((page_write_count * PAGE_WRITE_SIZE) < sizeof(custom_var)) && (FSP_SUCCESS == err)) { err = R_QSPI_Write(&g_qspi_ctrl, &buffer[page_write_count * PAGE_WRITE_SIZE / sizeof(uint16_t)], p_mem_addr, PAGE_WRITE_SIZE); if (FSP_SUCCESS != err) { sprintf(s_print_buffer, "Failed to write data to QSPI flash\r\n"); } else { err = get_flash_status(); if (FSP_SUCCESS != err) { sprintf(s_print_buffer, "Failed to get flash status after write\r\n"); } } p_mem_addr += PAGE_WRITE_SIZE; page_write_count++; } /* 关闭 QSPI 模块 */ // err = R_QSPI_Close(&g_qspi_ctrl); // if (FSP_SUCCESS != err) // { // sprintf(s_print_buffer, "Failed to close QSPI module\r\n"); // } /* close QSPI module */ deinit_qspi(current_spi_mode); } 读取上一次存储的波形 /** * @brief 从 Quad Flash 读取波形数据 * @param buffer 存储波形的缓冲区 * @retval 无 */ void Read_Waveform_From_Flash(uint16_t *buffer) { fsp_err_t err = FSP_SUCCESS; uint32_t page_read_count = 0; uint8_t *p_mem_addr = (uint8_t *)QSPI_DEVICE_START_ADDRESS; spi_flash_protocol_t current_spi_mode; /* The comms mode of the FLASH device is EXTENDED_SPI by default */ current_spi_mode = SPI_FLASH_PROTOCOL_EXTENDED_SPI; /* 打开 QSPI 模块 */ // err = R_QSPI_Open(&g_qspi_ctrl, &g_qspi_cfg); // if (FSP_SUCCESS != err) // { // sprintf(s_print_buffer, "Failed to open QSPI module\r\n"); // return; // } /* initialise the QSPI, and change mode to that set in FSP */ err = qpi_init(); if (FSP_SUCCESS == err) { /* The comms mode has changed. So if recovering, this new mode required */ current_spi_mode = g_qspi_cfg.spi_protocol; } /* 逐页读取波形数据 */ while ((page_read_count * PAGE_WRITE_SIZE) < sizeof(custom_var)) { memcpy(&buffer[page_read_count * PAGE_WRITE_SIZE / sizeof(uint16_t)], p_mem_addr, PAGE_WRITE_SIZE); p_mem_addr += PAGE_WRITE_SIZE; page_read_count++; } // /* 关闭 QSPI 模块 */ // err = R_QSPI_Close(&g_qspi_ctrl); // if (FSP_SUCCESS != err) // { // sprintf(s_print_buffer, "Failed to close QSPI module\r\n"); // } /* close QSPI module */ deinit_qspi(current_spi_mode); } 调整DAC参数 void Adjust_Waveform(int32_t step) { for (uint32_t i = 0; i < sizeof(custom_var) / sizeof(custom_var[0]); i++) { // 调整值,限制范围在 MIN_VALUE 和 MAX_VALUE 之间 if (custom_var[i] + step > MAX_VALUE) { custom_var[i] = MAX_VALUE; } else if (custom_var[i] + step < MIN_VALUE) { custom_var[i] = MIN_VALUE; } else { custom_var[i] += step; } } } 指令输入解析 block_sz_ndx = 0; memset(&s_block_sz_str, 0, INPUT_BUFFER); while (false == response_flag) { print_to_console("input: "); while ((CONNECTION_ABORT_CRTL != c)) { c = input_from_console(); if (block_sz_ndx < block_sz_limit) { s_block_sz_str[block_sz_ndx] = (char_t)c; block_sz_ndx++; } else { s_block_sz_str[block_sz_ndx] = MENU_ENTER_RESPONSE_CRTL; c = MENU_ENTER_RESPONSE_CRTL; } if (MENU_ENTER_RESPONSE_CRTL == c) { if (s_block_sz_str[block_sz_ndx - 2] == 'a') { sprintf(s_print_buffer, "\r\nIncrease waveform parameters\r\n"); print_to_console((void*)s_print_buffer); Adjust_Waveform(STEP_SIZE); // 增加波形值 sprintf(s_print_buffer, "custom_var contains:\r\n"); print_to_console((void *)s_print_buffer); for (uint32_t i = 0; i < 32; i++) { sprintf(s_print_buffer, "custom_var[%u] = %u\r\n", i, custom_var[i]); print_to_console((void *)s_print_buffer); } } if (s_block_sz_str[block_sz_ndx - 2] == 's') { sprintf(s_print_buffer, "\r\nDecrease waveform parameters\r\n"); print_to_console((void*)s_print_buffer); Adjust_Waveform(-STEP_SIZE); // 减少波形值 sprintf(s_print_buffer, "custom_var contains:\r\n"); print_to_console((void *)s_print_buffer); for (uint32_t i = 0; i < 32; i++) { sprintf(s_print_buffer, "custom_var[%u] = %u\r\n", i, custom_var[i]); print_to_console((void *)s_print_buffer); } } if (s_block_sz_str[block_sz_ndx - 2] == 'r') // 读取波形数据 { sprintf(s_print_buffer, "\r\nRead the waveform data from Quad-SPI flash into memory buffer\r\n"); print_to_console((void*)s_print_buffer); Read_Waveform_From_Flash(custom_var); is_custom_wave = true; sprintf(s_print_buffer, "After Reading, custom_var contains:\r\n"); print_to_console((void *)s_print_buffer); for (uint32_t i = 0; i < 32; i++) { sprintf(s_print_buffer, "custom_var[%u] = %u\r\n", i, custom_var[i]); print_to_console((void *)s_print_buffer); } } else if (s_block_sz_str[block_sz_ndx - 2] == 'w') // 写入波形数据 { sprintf(s_print_buffer, "\r\nWrite the current waveform data to Quad-SPI flash storage\r\n"); print_to_console((void*)s_print_buffer); sprintf(s_print_buffer, "Before Writing, var contains:\r\n"); print_to_console((void *)s_print_buffer); for (uint32_t i = 0; i < 32; i++) { sprintf(s_print_buffer, "var[%u] = %u\r\n", i, custom_var[i]); print_to_console((void *)s_print_buffer); } Write_Waveform_To_Flash(custom_var); } else if (s_block_sz_str[block_sz_ndx - 2] == 'g') // 写入波形数据 { sprintf(s_print_buffer, "\r\nStart Generator...\r\n"); print_to_console((void *)s_print_buffer); while(1) { DAC_SinWave_Cycle(10); } } block_sz_ndx = 0; memset(&s_block_sz_str, 0, INPUT_BUFFER); break; } if (MENU_EXIT_CRTL == c) { response_flag = true; block_size_actual = 0; break; } if (CARRAGE_RETURN != c) { sprintf(s_print_buffer, "%c", (char_t)c); print_to_console((void*)s_print_buffer); } // 输出波形 DAC_SinWave_Cycle(1); } if ((MENU_EXIT_CRTL == c) || (0x00 == c)) { break; } } 向flash写入一个周期的波形数据   从flash读取一个周期的波形数据,可以看到读取的波形数据和写入的是一致的。 默认输出波形: 修改DAC输出后波形: 五、心得体会 本次活动非常棒,通过本次活动,我对在瑞萨平台上的开发有了更加深入的了解。整个任务过程设计合理,循序渐进,从环境搭建到功能扩展,不仅让我熟悉了开发流程,还提升了实际动手能力。在扩展任务中,熟悉了spi接口操作flash和dac波形生成。此外,EEworld工作人员的全程答疑提供了很大的帮助,解决了活动中的疑问。再次感谢活动组织方和工作人员的精心安排!   六、代码下载 Follow me第二季第3期任务代码-嵌入式开发相关资料下载-EEWORLD下载中心

  • 上传了资料: Follow me第二季第3期任务代码

  • 加入了学习《FollowMe 第二季:3 - EK_RA6M5 开发板入门》,观看 EK-RA6M5 开发板入门

  • 2024-11-14
  • 加入了学习《FollowMe 第二季: 1 Adafruit Circuit Playground Express及任务讲解》,观看 Adafruit Circuit Playground Express 及任务讲解

  • 加入了学习《直播回放: FollowMe 4 W5500-EVB-Pico 使用入门》,观看 W5500-EVB-Pico 使用入门

最近访客

< 1/1 >

统计信息

已有2人来访过

  • 芯积分:55
  • 好友:--
  • 主题:1
  • 回复:1

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言