linyu0395

  • 2025-01-12
  • 加入了学习《【Follow me第二季第1期】全部任务演示》,观看 全部任务演示2.0

  • 发表了主题帖: 【Follow me第二季第3期】任务总汇

    本帖最后由 linyu0395 于 2025-1-20 22:28 编辑 开发板到手已经有一段时间了,瑞萨的这款EK-RA6M5虽然是首次尝试,但是入门和开发流程个人感觉比ST还快捷。开发环境我综合考虑了一下,相对于e2studio,还是通过RASC开发更方便,毕竟MDK也用的熟练。大家可以通过https://github.com/renesas进行下载。除了IDE安装文件,还有很多历程可以参考,特别是上手前期,通过丰富的例子可以加快对这块开发板的调试和使用。以下链接大家也可以参考。     FSP Webpage: www.renesas.com/ra/fsp FSP GitHub: https://github.com/renesas/fsp FSP Releases: https://github.com/renesas/fsp/releases FSP Documentation: https://renesas.github.io/fsp RA Product Information: www.renesas.com/ra RA/FSP Knowledge Base: https://en-support.renesas.com/knowledgeBase/category/31087 Support: www.renesas.com/support     [localvideo]4cfa391f3856d0f81b244b97bb666c51[/localvideo]     任务软件流程图如下:   任务成果展示 入门任务:搭建环境,下载调试示例程序,Blink,按键      安装Renesas RA Smart Configurator 5.7.0后,打开界面如下:     选择了EK-RA6M5,里面包含了和开发板资源相关外设的IO、功能模块的初始化,接下来只要实例化就可以了。     本次任务需要实例化的外设,QSPI、OSPI、DAC等,通过下载的example里的实例就可以快速配置。         然后点击右上角的“Generate Project Content”生成MDK的项目工程     根据任务需求,我加入了qspi、ospi、dac_wave、rtt、按键、led的代码。   2、基础任务:quad-spi flash和octo-spi flash配置及读写速度测试;DAC配置生成波形及性能测试 QSPI的配置如下:   #include "qspi.h" #include "hal_data.h" #include "common_utils.h" #include "qspi_ep.h" /*******************************************************************************************************************//** * @brief wait for QSPI flash device status register to get idle till operation is in progress * @param[IN] 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(&g_qspi0_ctrl, &status); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_StatusGet Failed\r\n"); return err; } /* Decrement time out to avoid infinite loop in case of consistent failure */ --time_out; if(RESET_VALUE >= time_out) { APP_PRINT("\r\n ** Timeout : No result from QSPI flash status register ** \r\n"); return FSP_ERR_TIMEOUT; } } while(false != status.write_in_progress); return err; } /*******************************************************************************************************************//** * @brief Close QSPI module * @param[IN] 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("\r\n ** Exit QPI mode before Closing QSPI module ** \r\n"); error = R_QSPI_DirectWrite(&g_qspi0_ctrl, &data_exit_qpi, ONE_BYTE, false); if(FSP_SUCCESS != error) { APP_ERR_PRINT("R_QSPI_DirectWrite Failed\r\n"); } } APP_PRINT("\r\n ** Closing QSPI module ** \r\n"); /* close QSPI module */ error = R_QSPI_Close(&g_qspi0_cfg); if(FSP_SUCCESS != error) { APP_ERR_PRINT("R_QSPI_Close Failed\r\n"); } APP_PRINT("\r\n\r\n *****############## demo ends here ########## *******\r\n\r\n"); } /*******************************************************************************************************************//** * @brief set QPI Mode in flash device and MCU * @param[IN] 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("\r\n ** setting QPI mode: sending QPI enabling command byte to flash ** \r\n"); /* write enable once again section 9-1 states that * we should do it before sending 0x35 to flash device */ err = R_QSPI_DirectWrite(&g_qspi0_ctrl, &(g_qspi0_cfg.write_enable_command), ONE_BYTE, false); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_DirectWrite Failed\r\n"); return err; } else { err = get_flash_status(); if(FSP_SUCCESS != err) { APP_ERR_PRINT("Failed to get status for QSPI operation\r\n"); 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(&g_qspi0_ctrl, &data_qpi_en, ONE_BYTE, false); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_DirectWrite Failed\r\n"); return err; } APP_PRINT("\r\n ** setting QPI mode: setting QPI mode in MCU ** \r\n"); /* Command byte transferred to flash-> NOW set the QPI protocol in MCU run time */ err = R_QSPI_SpiProtocolSet(&g_qspi0_ctrl, SPI_FLASH_PROTOCOL_QPI); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_SpiProtocolSet Failed\r\n"); } return err; } void qspi_init(void) { fsp_err_t err; uint8_t data_sreg[SREG_SIZE] = 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 *)&l_qspi_cfg, (spi_flash_cfg_t *)&g_qspi0_cfg, sizeof(spi_flash_cfg_t)); l_qspi_cfg.spi_protocol = SPI_FLASH_PROTOCOL_EXTENDED_SPI; err = R_QSPI_Open(&g_qspi0_ctrl, &l_qspi_cfg); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_Open Failed\r\n"); APP_ERR_TRAP(err); } } else { APP_PRINT("\r\n ** user selected extended SPI Mode in RA Configuration tool ** \r\n"); /* open QSPI in extended SPI mode */ err = R_QSPI_Open(&g_qspi0_ctrl, &g_qspi0_cfg); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_Open Failed\r\n"); APP_ERR_TRAP(err); } } /* write enable for further operations */ err = R_QSPI_DirectWrite(&g_qspi0_ctrl, &(g_qspi0_cfg.write_enable_command), ONE_BYTE, false); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_DirectWrite Failed\r\n"); /* 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("Failed to get status for QSPI operation\r\n"); /* 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(&g_qspi0_ctrl, data_sreg, SREG_SIZE, false); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_DirectWrite Failed\r\n"); /* 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("Failed to get status for QSPI operation\r\n"); /* 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(&g_qspi0_ctrl, &(g_qspi0_cfg.status_command), ONE_BYTE, true); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_DirectWrite Failed\r\n"); /* 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 <SFMCD register> 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(&g_qspi0_ctrl, &sreg_data, ONE_BYTE); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_DirectRead Failed\r\n"); /* 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("Failed to get status for QSPI operation\r\n"); /* 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("Failed to get value set in the status register \r\n"); /* 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("qpi_mode_set failed\r\n"); /* 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(&g_qspi0_ctrl, p_mem_addr + sector_index * SECTOR_SIZE, sector_nums * SECTOR_SIZE); if(FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_Erase Failed\r\n"); deinit_qspi(g_qspi0_cfg.spi_protocol); APP_ERR_TRAP(err); } else { err = get_flash_status(); if(FSP_SUCCESS != err) { APP_ERR_PRINT("Failed to get status for QSPI operation\r\n"); deinit_qspi(g_qspi0_cfg.spi_protocol); APP_ERR_TRAP(err); } /* validating erase */ for(uint16_t mem_index = RESET_VALUE; mem_index < SECTOR_SIZE; mem_index++) { if(DEFAULT_MEM_VAL != p_mem_addr[mem_index]) { APP_ERR_PRINT("\r\n Verification for erase Failed \r\n"); 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 < SPI_FLASH_PageSize */ if(NumOfPage == 0) { R_QSPI_Write(&g_qspi0_ctrl, data, addr, size); get_flash_status(); } else /* NumByteToWrite > SPI_FLASH_PageSize */ { /* 先把整数页都写了 */ while(NumOfPage--) { R_QSPI_Write(&g_qspi0_ctrl, data, addr, PAGE_WRITE_SIZE); get_flash_status(); addr += PAGE_WRITE_SIZE; data += PAGE_WRITE_SIZE; } /* 若有多余的不满一页的数据,把它写完 */ R_QSPI_Write(&g_qspi0_ctrl, data, addr, NumOfSingle); get_flash_status(); } } /* 若地址与 SPI_FLASH_PageSize 不对齐 */ else { /* NumByteToWrite < SPI_FLASH_PageSize */ if(NumOfPage == 0) { /* 当前页剩余的 count 个位置比 NumOfSingle 小,一页写不完 */ if(NumOfSingle > count) { temp = NumOfSingle - count; /* 先写满当前页 */ R_QSPI_Write(&g_qspi0_ctrl, data, addr, count); get_flash_status(); addr += count; data += count; /* 再写剩余的数据 */ R_QSPI_Write(&g_qspi0_ctrl, data, addr, temp); get_flash_status(); } else /* 当前页剩余的 count 个位置能写完 NumOfSingle 个数据 */ { R_QSPI_Write(&g_qspi0_ctrl, data, addr, size); get_flash_status(); } } else /* NumByteToWrite > SPI_FLASH_PageSize */ { /* 地址不对齐多出的 count 分开处理,不加入这个运算 */ size -= count; NumOfPage = size / PAGE_WRITE_SIZE; NumOfSingle = size % PAGE_WRITE_SIZE; /* 先写完 count 个数据,为的是让下一次要写的地址对齐 */ R_QSPI_Write(&g_qspi0_ctrl, data, addr, count); get_flash_status(); /* 接下来就重复地址对齐的情况 */ addr += count; data += count; /* 把整数页都写了 */ while(NumOfPage--) { R_QSPI_Write(&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(&g_qspi0_ctrl, data, addr, NumOfSingle); get_flash_status(); } } } }   OSPI的配置如下:     #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(&g_ioport_ctrl, RESET_PIN, BSP_IO_LEVEL_LOW); R_BSP_SoftwareDelay(DELAY_TIME, BSP_DELAY_UNITS_MICROSECONDS); R_IOPORT_PinWrite(&g_ioport_ctrl, RESET_PIN, BSP_IO_LEVEL_HIGH); R_BSP_SoftwareDelay(DELAY_TIME, BSP_DELAY_UNITS_MICROSECONDS); } uint8_t write_data[4096] = { 0 }; uint8_t read_data[4096] = { 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(&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(&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(&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(&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); } } DAC的配置如下: DAC通过P014输出       按键、LED #include "key.h" uint8_t led_state; void LED_ON() //LED1 亮 { R_IOPORT_PinWrite(&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(&g_ioport_ctrl, key, &state); if(BSP_IO_LEVEL_HIGH == state) { return KEY_OFF; //按键没有被按下 } else { do //等待按键释放 { R_IOPORT_PinRead(&g_ioport_ctrl, key, &state); } while(BSP_IO_LEVEL_LOW == state); } return KEY_ON; //按键被按下了 } void Key_Poll(void) { static uint8_t key_status[2]; if(Key_Scan(KEY1_PIN) == KEY_ON) //扫描按键 1 { if(key_status[0]) { LED1_ON(); key_status[0] = 0; } else { LED1_OFF(); key_status[0] = 1; } } if(Key_Scan(KEY2_PIN) == KEY_ON) //扫描按键 2 { if(key_status[1]) { LED2_ON(); key_status[1] = 0; } else { LED2_OFF(); key_status[1] = 1; } } } #ifndef _KEY_H_ #define _KEY_H_ #include <stdint.h> #include "hal_data.h" /* 定义宏 KEY_ON 表示按键按下 定义宏 KEY_OFF 表示按键没有按下 */ #define KEY_ON 1 #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(&g_ioport_ctrl, LED1_PIN, BSP_IO_LEVEL_HIGH) #define LED1_OFF() R_IOPORT_PinWrite(&g_ioport_ctrl, LED1_PIN, BSP_IO_LEVEL_LOW) // #define LED1_TOGGLE() R_IOPORT_PinWrite(&g_ioport_ctrl, LED1_PIN, !R_IOPORT_PinRead(&g_ioport_ctrl, LED1_PIN, &led_state)) #define LED2_ON() R_IOPORT_PinWrite(&g_ioport_ctrl, LED2_PIN, BSP_IO_LEVEL_HIGH) #define LED2_OFF() R_IOPORT_PinWrite(&g_ioport_ctrl, LED2_PIN, BSP_IO_LEVEL_LOW) // #define LED2_TOGGLE() R_IOPORT_PinWrite(&g_ioport_ctrl, LED2_PIN, !R_IOPORT_PinRead(&g_ioport_ctrl, LED2_PIN, &led_state)) extern uint8_t led_state; uint32_t Key_Scan(bsp_io_port_pin_t key); void Key_Poll(void); #endif 3、进阶任务:示例程序中新增命令打印信息       4、扩展任务:设计一个类似信号发生器功能的例程。可在示例程序上修改。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息     此任务已经通过视频演示输出方波和正弦波。 #include "dac_wave.h" #include "hal_data.h" #include <math.h> #include <stdint.h> #include "r_dac.h" uint8_t dac_init_flag = 0; uint16_t buffer[BUFFER_SIZE]; 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 < length; i++) { buf[i] = (uint16_t)((i % period < 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 < length; i++) { uint32_t pos = i % period; if(pos < period / 2) { buf[i] = (uint16_t)((2 * AMPLITUDE * pos) / (period / 2)); } else { buf[i] = (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 < length; i++) { buf[i] = (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(&g_dac_ctrl, buffer[buffer_index]); /* handle error */ /* Start DAC conversion */ R_DAC_Start(&g_dac_ctrl); /* handle error */ //dac_output(buffer[buffer_index]); 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(&g_dac_ctrl, &g_dac_cfg); // generate_square_wave(buffer, BUFFER_SIZE, 1000); dac_init_flag = 1; } #ifndef _DAC_WAVE_H_ #define _DAC_WAVE_H_ #include <stdint.h> #define PI 3.14159265 #define SAMPLE_RATE 1000 #define AMPLITUDE 2048 #define BUFFER_SIZE 1000 extern uint16_t buffer[BUFFER_SIZE]; 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 总结:瑞萨的EK-RA6M5的上手非常快,开发有大量丰富的历程参考,无论对于新手还是老手,都是非常适合的。资源丰富,带网络、LCD驱动、多路FDCAN等还需要细细研究。后续有更新的话再和大家一起分享,谢谢!    代码附件:

  • 2024-12-15
  • 发表了主题帖: 【Follow me第二季第3期】+ 瑞萨开发环境

    本帖最后由 linyu0395 于 2024-12-16 00:02 编辑     首先有幸得到瑞萨的RA6M5开发板并进行测试。     开发环境的下载、安装,大家可以通过官网直接下载,安装后如图         这里不得不夸一下瑞萨的开发环境,我从入手到熟悉,基本上就花了不到一个小时。我个人觉得瑞萨的开发环境比ST的还优秀,包括各种硬件模块、功能模块的可视化配置以及丰富的代码集成,非常适合新手入门。一旦熟悉了,就能快速地搭建测试环境和代码编写,摒弃各种繁杂的底层驱动的测试,这应该是广大工程师梦寐以求的便捷式开发模式吧。 这里也推荐一下[野火]瑞萨RA系列FSP库开发实战指南——基于野火启明开发板 — [野火]瑞萨RA系列FSP库开发实战指南——基于野火启明开发板 文档这个网站,里面也提供了瑞萨RA系列的开发教程,非常适合入门的工程师们参考! renesas/ra-fsp-examples: Example projects for Renesas RA MCU family  这是github的内容,里面可以下载最新的官方example,我也是借助这些教程和参考快速进行开发板功能的验证。       好了,长话短说。测试过程中我首先测试了RA6M5的QSPI模块的功能。 以下是每个 SPI 闪存协议模式的区别: SPI_FLASH_PROTOCOL_EXTENDED_SPI (0x000): 标准的 SPI 模式,命令、地址和数据通过单条线(MOSI)传输。 SPI_FLASH_PROTOCOL_QPI (0x002): QPI(四线接口)模式使用四条线传输命令、地址和数据。相比标准 SPI 模式,QPI 模式每个时钟周期传输四位数据,从而提高数据吞吐量。 SPI_FLASH_PROTOCOL_SOPI (0x003): SOPI(串行八线接口)模式使用八条线传输命令和数据。此模式需要设备设置为 SOPI 模式,并且可以显著提高数据传输速率。 SPI_FLASH_PROTOCOL_DOPI (0x004): DOPI(双八线接口)模式也使用八条线,但它在双数据速率(DDR)模式下运行,即在时钟的上升沿和下降沿都传输数据,相比 SOPI 模式,数据速率加倍。 SPI_FLASH_PROTOCOL_1S_1S_1S (0x000): 使用一条线传输命令、地址和数据的协议,与标准 SPI 模式类似。 SPI_FLASH_PROTOCOL_4S_4D_4D (0x3B2): 使用四条线传输命令,并以双数据速率传输地址和数据。 SPI_FLASH_PROTOCOL_8D_8D_8D (0x3FF): 使用八条线以双数据速率传输命令、地址和数据。 SPI_FLASH_PROTOCOL_1S_2S_2S (0x048): 使用一条线传输命令,使用两条线传输地址和数据。 SPI_FLASH_PROTOCOL_2S_2S_2S (0x049): 使用两条线传输命令、地址和数据。 SPI_FLASH_PROTOCOL_1S_4S_4S (0x090): 使用一条线传输命令,使用四条线传输地址和数据 SPI_FLASH_PROTOCOL_4S_4S_4S (0x092): 使用四条线传输命令、地址和数据 这些协议模式的选择通常取决于设备的支持和所需的数据传输速率 QSPI和OPI的代码我参考了github上下载的   我用了SEGGER_RTT进行数据打印,过程中加入了速度测试。这里提一下,   用Auto 无法输出打印的数据,这个时候可以根据编译生成的map文件定位到 .bss._SEGGER_RTT  就可以看到RTT的内存地址     RTT选择 Adress ,然后填入就OK了。         回到瑞萨的IDE,正如开始所说,配置非常的人性化,熟悉后,基本通过菜单和功能选择就能生成一个完整的代码框架,里面包含了底层的驱动和部分应用。       熟悉代码框架后,我加入了Systick的初始化配置、OSPI、QSPI的初始化以及进行读写的测速代码,具体内容我会附上代码供大家参考 这次调试的时间比较仓促,板子寄到了老家,而且最近一直在疯狂加班,板子今天才拿回来开始测试,花了半天的时间熟悉了代码并尝试测试了一下,有点捉紧。希望后续能抽时间继续完善其他外设包括液晶、can、网络等。最后不得不说瑞萨的开发环境做的做不错,我第一次入门就花了半天时间就基本熟悉IDE和功能配置等,除了e2studio,还支持MDK,非常棒!希望瑞萨能加强国内的推荐力度!  

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

  • 2024-03-16
  • 加入了学习《BQ76952 & BQ76942, 3-16S & 3-10S 电池监控器系列讲座 (2)》,观看 2.2 bq76942/bq76952 器件概述

最近访客

< 1/2 >

统计信息

已有202人来访过

  • 芯积分:159
  • 好友:--
  • 主题:10
  • 回复:79

留言

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


现在还没有留言