quansirx

  • 2024-12-09
  • 回复了主题帖: 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器

    御坂10032号 发表于 2024-12-7 21:57 我想看一下这个保存历史波形到Flash里的相关代码,但是似乎你这个工程文件中并没有这一部分, 而你这个帖子 ... 你参考这篇帖子https://bbs.eeworld.com.cn/thread-1299584-1-1.html 可以进行SPI Flash外设初始化和数据写入与读取。完成SPI Flash驱动后就可以将波形数据存入Flash保存下来

  • 2024-12-04
  • 加入了学习《【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器》,观看 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器

  • 2024-12-02
  • 回复了主题帖: 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器

    quansirx 发表于 2024-11-30 21:29 可以,源程序后面会上传 后续更新下文件链接 工程链接:https://download.eeworld.com.cn/detail/quansirx/635164

  • 2024-11-30
  • 回复了主题帖: 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器

    beyond_笑谈 发表于 2024-11-30 17:37 请问有没有这个任务完整的工程代码?或者细一点的分享,这个任务的功能试了几次搞不定,谢谢   文件资源正在审核

  • 上传了资料: 【Follow me第二季第3期】扩展任务 源代码工程

  • 回复了主题帖: 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器

    beyond_笑谈 发表于 2024-11-30 17:37 请问有没有这个任务完整的工程代码?或者细一点的分享,这个任务的功能试了几次搞不定,谢谢 可以,源程序后面会上传 后续更新下文件链接

  • 回复了主题帖: 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器

    wangerxian 发表于 2024-11-30 16:22 8KHz频率这么高吗?输出个方波看看频率 可以的 但是DAC转换点数需要适当减少

  • 2024-11-29
  • 回复了主题帖: 【Follow me第二季第3期】任务汇总

    beyond_笑谈 发表于 2024-11-29 16:16 第五个任务能打开,而且楼主速度挺快的,这就已经做好了。 勉强做好

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

    Jacktang 发表于 2024-11-29 07:31 第五个任务链接打不开吧   我看下,可能是帖子还没通过审核

  • 回复了主题帖: 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器

    qwqwqw2088 发表于 2024-11-29 11:17 做的这个函数发生器的频率能做到大概在多少范围 没有使用DMA,目前是8KHz左右

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

    一、EK-RA6M5开箱帖 【Follow me第二季第3期】EK-RA6M5开箱帖 - DigiKey得捷技术专区 - 电子工程世界-论坛 二、入门任务---调试程序、Blink及按键测试 【Follow me第二季第3期】入门任务---调试程序、Blink及按键测试 - DigiKey得捷技术专区 - 电子工程世界-论坛 三、基础任务---QSPI、OSPI Flash及DAC测试 【Follow me第二季第3期】基础任务---QSPI、OSPI Flash及DAC测试 - DigiKey得捷技术专区 - 电子工程世界-论坛 四、进阶任务---示例程序新增命令打印信息 【Follow me第二季第3期】进阶任务---示例程序新增命令打印信息 - DigiKey得捷技术专区 - 电子工程世界-论坛 五、扩展任务---EK_RA6M5函数信号发生器 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器 - DigiKey得捷技术专区 - 电子工程世界-论坛  

  • 发表了主题帖: 【Follow me第二季第3期】扩展任务---EK_RA6M5函数信号发生器

    本帖最后由 quansirx 于 2024-11-28 21:17 编辑 一、任务介绍 该项目使用EK_RA6M5评估板完成一简易函数信号发生器的制作,涉及EK_RA6M5主控芯片的片内资源有定时器GPT,数模转换器DAC;片外QSPI Flash用于存储历史DAC波形数据 DAC最大模拟输出电压为3.3V,最小输出电压为0V,如果使用外部电压偏置电路可以实现更大电压或负压输出。 二、原理说明 函数信号发生器最基本的功能是生成一定幅度、频率(周期)、波形类型的信号,那么如何通过MCU主控来控制波形的类型、幅度以及频率?这个思路是比较简单的,只需使用到定时器与DAC这两个外设就能够实现以上功能。对于一个12位的DAC,能转换的离散电压范围为2^12=4096档,这4096个电压档位将DAC的输出电压范围3.3V均分为4096份。 2.1、幅度调节 因此波形的幅度大小通过控制DAC的输出档位来实现,将DAC_Array波形查找表内数据归一化,设幅度调节因子为A,A∈[0,1]。因此DAC最终输出的电压等于 DAC_Arrat*4095*A 2.2、频率调节 使用定时器实现,设定时器溢出频率为F,设DAC在一个信号周期的采样点数为N,于是DAC输出信号频率 f=F/N; 2.3、波形类型 将不同信号的波形数据存储到片内Flash,通过设置标记变量的方式来输出不同类型的波形   2.4 软件流程图   三、程序设计 3.1 定时器外设设置 在FSP工具内新增定时器外设,用于定时触发DAC进行转换   3.2 DAC外设设置 FSP内新增DAC外设   3.3 波形设置代码 //add*** #include "bsp_adc.h" #include "math.h" #define M_PI 3.14159265358979323846 #define ND 128 float frac=0.8; volatile float dac_array[ND]; volatile uint16_t dac_value; volatile uint8_t wave_type=0; static uint32_t n1=0; static uint32_t n2=0; static uint32_t n3=0; //add*** //add2*** #define ND2 12800 volatile float history_dac_array[ND2]; volatile uint8_t show_history_wave=0; //add2*** void init_dac_array(uint8_t cmd); void init_dac_array(uint8_t cmd){ switch(cmd){ case 1://锯齿波 for(uint16_t i=0;i<ND;i++){ dac_array[i]=(float)1.0*i/(ND-1); } break; case 2://正弦波 double w=0.0; for(uint16_t i=0;i<ND;i++){ dac_array[i]=(float)(sin(w)+1)/2; w+=(2*M_PI/(ND-1)); } break; case 3://方波 for(uint16_t i=0;i<ND;i++){ if(i<ND/2){ dac_array[i]=1.0; } else{ dac_array[i]=0; } } break; case 4://历史波形删除方波 n3=0; n2=0; // for(uint32_t i=0;i<ND2;i++){ // history_dac_array[i]=0; // } break; } } DAC定时输出设置、信号幅度测试 //add*** void g_timer0_callback(timer_callback_args_t * p_args) { FSP_PARAMETER_NOT_USED(p_args); if(show_history_wave==0){ dac_value=(uint16_t)(frac*4095*dac_array[n1++]); R_DAC_Write(&g_dac0_ctrl,dac_value); //add2** history_dac_array[n2++]=dac_array[n1-1]; QSPI_Flash_BufferWrite(history_dac_array, FLASH_WriteAddress, ND2);//存储历史DAC波形 //add2** if(n1==ND) n1=0; if(n2==ND2) n2=0; } else{ QSPI_Flash_BufferRead(history_dac_array2, FLASH_WriteAddress, ND2);//读取历史DAC波形 dac_value=(uint16_t)(frac*4095*history_dac_array2[n3++]); R_DAC_Write(&g_dac0_ctrl,dac_value); if(n3==n2) n3=0; } } 四、实验结果 我这里通过在调试状态更改标记变量的方式,更改DAC输出波形类型,信号幅度、频率,默认DAC历史波形存储深度为12800,超过存储深度后历史波形数据将被新的波形数据覆盖 另外提供了清除历史存储波形的选项。使用e2 studio内置real-time chart来观察DAC信号波形 4.1 GIF演示   4.2 视频演示  

  • 2024-11-24
  • 加入了学习《Follow me第二季第4期 任务完成视频》,观看 【Follow me第二季第4期】最终视频

  • 2024-11-19
  • 发表了主题帖: 【Follow me第二季第3期】进阶任务---示例程序新增命令打印信息

    本帖最后由 quansirx 于 2024-11-19 23:01 编辑 一、任务说明 使用EK_RA6M5的示例程序,新增一个菜单命令行,新增命令用于打印开发板信息或其他程序处理。 E2 studio打开quickstart_ek_ra6m5_ep工程 在main.c处找到关于menu的线程创建       打开menu线程的声明,是在menu_thread.c文件内       进行往下查找       menu_main.c文件       命令菜单列表定义在变量s_menu_items内         在s_menu_items数组新增命令“Show kit Information” 并打开kis_display_menu函数定义处     kis_display_menu函数定义       show_display_menu函数内容与kis_display_menu一致       新添加的菜单命令函数未做声明,找到kis_display_menu函数声明所在文件,添加 show_display_menu的外部声明 extern test_fn show_display_menu(void); 编译无误后开始调试目标板   二、实验结果   打开串口终端工具       菜单列表出现了新增的命令序列   按下数字键2,新增命令执行正常       

  • 发表了主题帖: 【Follow me第二季第3期】基础任务---QSPI、OSPI Flash及DAC测试

    本帖最后由 quansirx 于 2024-11-19 23:00 编辑 一、QSPI Flash配置 1.1 使用e2 studio新建MCU自定义工程,MCU型号为R7FA6M5BH3CFC       打开开发板原理图文件,找到QSPI Flash的原理图   在FSP配置界面找到Pins栏,引脚配置与原理图一致,注意引脚组选项为_B only 操作模式为Quad     在stacks栏新增qspi flash     Qspi flash stack属性设置保持默认 FSP设置完成后点击右上角的Generate Project Content 1.2       在工程目录src下新建bsp文件夹,并新建qspi的两个c/h驱动文件 bsp_qspi_flash.h头文件内容如下 #ifndef QSPI_FLASH_BSP_QSPI_FLASH_H_ #define QSPI_FLASH_BSP_QSPI_FLASH_H_ #include "hal_data.h" #include "r_qspi.h" #define  FLASH_ID_W25Q32JV      0xEF4016    // W25Q32JV #define  FLASH_ID_AT25SF321B    0x1F8701    // AT25SF321B #define SPI_FLASH_PageSize              256 #define SPI_FLASH_PerWritePageSize      256 #define RESET_VALUE                    (0x00) /*命令定义-开头*******************************/ #define WriteEnable                 0x06 #define WriteDisable                0x04 #define ReadStatusReg               0x05 #define WriteStatusReg              0x01 #define ReadData                    0x03 #define FastReadData                0x0B #define FastReadDual                0x3B #define PageProgram                 0x02 #define BlockErase                  0xD8 #define SectorErase                 0x20 #define ChipErase                   0xC7 #define PowerDown                   0xB9 #define ReleasePowerDown            0xAB #define DeviceID                    0xAB #define ManufactDeviceID            0x90 #define JedecDeviceID               0x9F /* WIP(busy)标志,FLASH内部正在写入 */ #define WIP_Flag                    0x01 #define Dummy_Byte                  0xFF /*命令定义-结尾*******************************/ void QSPI_Flash_Init(void); uint32_t QSPI_Flash_ReadID(void); uint32_t QSPI_Flash_ReadDeviceID(void); void QSPI_Flash_PowerDown(void); void QSPI_Flash_WakeUp(void); void QSPI_Flash_WriteEnable(void); fsp_err_t QSPI_Flash_WaitForWriteEnd(void); void QSPI_Flash_SectorErase(uint32_t adress); void QSPI_Flash_PageWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); //页写入 void QSPI_Flash_BufferWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); void QSPI_Flash_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead); //static void qspi_d0_byte_write_standard (uint8_t byte); fsp_err_t R_QSPI_Read(spi_flash_ctrl_t *p_ctrl, uint8_t *p_src, uint8_t *const p_dest, uint32_t byte_count); #endif /* QSPI_FLASH_BSP_QSPI_FLASH_H_ */   bsp_qspi_flash.c文件内容如下 #include "bsp_qspi_flash.h" void QSPI_Flash_Init(void) {     R_QSPI_Open(&g_qspi0_flash_ctrl, &g_qspi0_flash_cfg);     R_BSP_SoftwareDelay(10u, BSP_DELAY_UNITS_MILLISECONDS); } /** * @brief  读取FLASH ID * @param  无 * @retval FLASH ID */ uint32_t QSPI_Flash_ReadID(void) {    unsigned char data[6] = {};    uint32_t back;    data[0] = JedecDeviceID;    R_QSPI_DirectWrite(&g_qspi0_flash_ctrl, &data[0], 1, true);     //false: close the spi  true: go go go    R_QSPI_DirectRead(&g_qspi0_flash_ctrl, &data[0], 3);    /*把数据组合起来,作为函数的返回值*/    back = (data[0] << 16) | (data[1] << 8) | (data[2]);    return back; } /** * @brief  读取FLASH 设备ID * @param  无 * @retval FLASH ID */ uint32_t QSPI_Flash_ReadDeviceID(void) {     unsigned char data[6] = {};     uint32_t back;     data[0] = DeviceID;     data[1] = 0xff;     data[2] = 0xff;     data[3] = 0xff;     R_QSPI_DirectWrite(&g_qspi0_flash_ctrl, &data[0], 4, true);     //false: close the spi  true: go go go     R_QSPI_DirectRead(&g_qspi0_flash_ctrl, &data[0], 3);     /*把数据组合起来,作为函数的返回值*/     back = (data[0] << 16) | (data[1] << 8) | (data[2]);     return back; } /** * @brief  等待WIP(BUSY)标志被置0,即等待FLASH内部数据写入完毕 * @param  无 */ fsp_err_t QSPI_Flash_WaitForWriteEnd(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_flash_ctrl, &status);         if (FSP_SUCCESS != err)         {             //printf("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)         {             //printf("\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  擦除FLASH扇区 * @param  SectorAddr:要擦除的扇区地址 * @retval 无 */ void QSPI_Flash_SectorErase(uint32_t adress) {     unsigned char data[6] = {};     data[0] = 0x06;     //write_enable_command     data[1] = 0x20;     //erase_command     data[2] = (uint8_t)(adress >> 16);     data[3] = (uint8_t)(adress >> 8);     data[4] = (uint8_t)(adress);     R_QSPI->SFMCMD = 1U;     R_QSPI->SFMCOM = data[0];     R_QSPI_DirectWrite(&g_qspi0_flash_ctrl, &data[1], 4, false);     QSPI_Flash_WaitForWriteEnd(); } /**  * @brief  对FLASH写入数据,调用本函数写入数据前需要先擦除扇区  * @param  pBuffer,要写入数据的指针  * @param  WriteAddr,写入地址  * @param  NumByteToWrite,写入数据长度  * @retval 无  */ void QSPI_Flash_BufferWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) {     uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;     /*mod运算求余,若writeAddr是SPI_FLASH_PageSize整数倍,运算结果Addr值为0*/     Addr = WriteAddr % SPI_FLASH_PageSize;     /*差count个数据值,刚好可以对齐到页地址*/     count = SPI_FLASH_PageSize - Addr;     /*计算出要写多少整数页*/     NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;     /*mod运算求余,计算出剩余不满一页的字节数*/     NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;     /* Addr=0,则WriteAddr 刚好按页对齐 aligned  */     if (Addr == 0)     {         /* NumByteToWrite < SPI_FLASH_PageSize */         if (NumOfPage == 0)         {             R_QSPI_Write(&g_qspi0_flash_ctrl, pBuffer, WriteAddr, NumByteToWrite);             QSPI_Flash_WaitForWriteEnd();         }         else /* NumByteToWrite > SPI_FLASH_PageSize */         {             /*先把整数页都写了*/             while (NumOfPage--)             {                 R_QSPI_Write(&g_qspi0_flash_ctrl, pBuffer, WriteAddr, SPI_FLASH_PageSize);                 QSPI_Flash_WaitForWriteEnd();                 WriteAddr +=  SPI_FLASH_PageSize;                 pBuffer += SPI_FLASH_PageSize;             }             /*若有多余的不满一页的数据,把它写完*/             R_QSPI_Write(&g_qspi0_flash_ctrl, pBuffer, WriteAddr, NumOfSingle);             QSPI_Flash_WaitForWriteEnd();         }     }     /* 若地址与 SPI_FLASH_PageSize 不对齐  */     else     {         /* NumByteToWrite < SPI_FLASH_PageSize */         if (NumOfPage == 0)         {             /*当前页剩余的count个位置比NumOfSingle小,一页写不完*/             if (NumOfSingle > count)             {                 temp = NumOfSingle - count;                 /*先写满当前页*/                 R_QSPI_Write(&g_qspi0_flash_ctrl, pBuffer, WriteAddr, count);                 QSPI_Flash_WaitForWriteEnd();                 WriteAddr +=  count;                 pBuffer += count;                 /*再写剩余的数据*/                 R_QSPI_Write(&g_qspi0_flash_ctrl, pBuffer, WriteAddr, temp);                 QSPI_Flash_WaitForWriteEnd();             }             else /*当前页剩余的count个位置能写完NumOfSingle个数据*/             {                 R_QSPI_Write(&g_qspi0_flash_ctrl, pBuffer, WriteAddr, NumByteToWrite);                 QSPI_Flash_WaitForWriteEnd();             }         }         else /* NumByteToWrite > SPI_FLASH_PageSize */         {             /*地址不对齐多出的count分开处理,不加入这个运算*/             NumByteToWrite -= count;             NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;             NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;             /* 先写完count个数据,为的是让下一次要写的地址对齐 */             R_QSPI_Write(&g_qspi0_flash_ctrl, pBuffer, WriteAddr, count);             QSPI_Flash_WaitForWriteEnd();             /* 接下来就重复地址对齐的情况 */             WriteAddr +=  count;             pBuffer += count;             /*把整数页都写了*/             while (NumOfPage--)             {                 R_QSPI_Write(&g_qspi0_flash_ctrl, pBuffer, WriteAddr, SPI_FLASH_PageSize);                 QSPI_Flash_WaitForWriteEnd();                 WriteAddr +=  SPI_FLASH_PageSize;                 pBuffer += SPI_FLASH_PageSize;             }             /*若有多余的不满一页的数据,把它写完*/             if (NumOfSingle != 0)             {                 R_QSPI_Write(&g_qspi0_flash_ctrl, pBuffer, WriteAddr, NumOfSingle);                 QSPI_Flash_WaitForWriteEnd();             }         }     } } /** * @brief  读取FLASH数据,减少ctrl这个标志 * @param  pBuffer,存储读出数据的指针 * @param  ReadAddr,读取地址 * @param  NumByteToRead,读取数据长度 * @retval 无 */ void QSPI_Flash_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) {     R_QSPI_Read(&g_qspi0_flash_ctrl, pBuffer, ReadAddr, NumByteToRead); } /** * @brief  读取flash数据 * @param  p_ctrl * @param  p_src     需要传回的数据 * @param  p_dest    数据地址 * @param  byte_count    数据长度 */ void qspi_d0_byte_write_standard(uint8_t byte) {     R_QSPI->SFMCOM = byte; } fsp_err_t R_QSPI_Read(spi_flash_ctrl_t     *p_ctrl,                       uint8_t              *p_src,                       uint8_t *const       p_dest,                       uint32_t              byte_count) {     qspi_instance_ctrl_t *p_instance_ctrl = (qspi_instance_ctrl_t *) p_ctrl;     uint32_t chip_address = (uint32_t) p_dest - (uint32_t) QSPI_DEVICE_START_ADDRESS + R_QSPI->SFMCNT1;     bool restore_spi_mode = false;     void (* write_command)(uint8_t byte) = qspi_d0_byte_write_standard;     void (* write_address)(uint8_t byte) = qspi_d0_byte_write_standard; #if QSPI_CFG_SUPPORT_EXTENDED_SPI_MULTI_LINE_PROGRAM     /* If the peripheral is in extended SPI mode, and the configuration provided in the BSP allows for programming on      * multiple data lines, and a unique command is provided for the required mode, update the SPI protocol to send      * data on multiple lines. */     if ((SPI_FLASH_DATA_LINES_1 != p_instance_ctrl->data_lines) &&             (SPI_FLASH_PROTOCOL_EXTENDED_SPI == R_QSPI->SFMSPC_b.SFMSPI))     {         R_QSPI->SFMSPC_b.SFMSPI = p_instance_ctrl->data_lines;         restore_spi_mode = true;         /* Write command in extended SPI mode on one line. */         write_command = gp_qspi_prv_byte_write[p_instance_ctrl->data_lines];         if (SPI_FLASH_DATA_LINES_1 == p_instance_ctrl->p_cfg->page_program_address_lines)         {             /* Write address in extended SPI mode on one line. */             write_address = gp_qspi_prv_byte_write[p_instance_ctrl->data_lines];         }     } #endif     /* Enter Direct Communication mode */     R_QSPI->SFMCMD = 1;     /* Send command to enable writing */     write_command(0x03);     /* Write the address. */     if ((p_instance_ctrl->p_cfg->address_bytes & R_QSPI_SFMSAC_SFMAS_Msk) == SPI_FLASH_ADDRESS_BYTES_4)     {         /* Send the most significant byte of the address */         write_address((uint8_t)(chip_address >> 24));     }     /* Send the remaining bytes of the address */     write_address((uint8_t)(chip_address >> 16));     write_address((uint8_t)(chip_address >> 8));     write_address((uint8_t)(chip_address));     /* Write the data. */     uint32_t index = 0;     while (index < byte_count)     {         /* Read the device memory into the passed in buffer */         *(p_src + index) = (uint8_t) R_QSPI->SFMCOM;         index++;     }     /* Close the SPI bus cycle. Reference section 39.10.3 "Generating the SPI Bus Cycle during Direct Communication"      * in the RA6M3 manual R01UH0886EJ0100. */     R_QSPI->SFMCMD = 1;     /* Return to ROM access mode */     R_QSPI->SFMCMD = 0;     return FSP_SUCCESS; } 1.3 hal_entry.c代码编写   hal_entry.c添加内容 //add*** uint32_t flag=0; uint32_t id; uint32_t id1; #define  FLASH_WriteAddress     0x00000 #define  FLASH_ReadAddress      FLASH_WriteAddress #define  FLASH_SectorToErase    FLASH_WriteAddress /* 发送缓冲区初始化 */ uint8_t Tx_Buffer[] = "Hello Digikey&EEWorld!\n"; uint8_t Rx_Buffer[sizeof(Tx_Buffer)]; int Buffercmp(uint8_t *pBuffer1, uint8_t *pBuffer2, uint16_t BufferLength) {     while (BufferLength--)     {         if (*pBuffer1 != *pBuffer2)         {             return 1;         }         pBuffer1++;         pBuffer2++;     }     return 0; } //add***   hal_entry函数添加如下内容 //add*** /*******************************************************************************************************************//**  * 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 */     //add*** //    uint32_t FlashID = 0; //    uint32_t FlashDeviceID = 0;     QSPI_Flash_Init();  // 串行FLASH初始化 //    FlashID = QSPI_Flash_ReadID(); //    FlashDeviceID = QSPI_Flash_ReadDeviceID();     QSPI_Flash_SectorErase(FLASH_SectorToErase);     /* 将发送缓冲区的数据写到flash中 */            // 这里写一页,一页的大小为256个字节            QSPI_Flash_BufferWrite(Tx_Buffer, FLASH_WriteAddress, sizeof(Tx_Buffer));            //printf("写入的数据为:%s \r\n", Tx_Buffer);            /* 将刚刚写入的数据读出来放到接收缓冲区中 */            QSPI_Flash_BufferRead(Rx_Buffer, FLASH_ReadAddress, sizeof(Tx_Buffer));            //printf("读出的数据为:%s \r\n", Rx_Buffer);            if (Buffercmp(Tx_Buffer, Rx_Buffer, sizeof(Tx_Buffer)) == 0)            {                flag=1;                //printf("\r\n32Mbit串行Flash测试成功!\r\n");                //LED3_ON;            }            else            {                flag=0;                //printf("\r\n32Mbit串行Flash测试失败!\r\n");                //LED1_ON;            }     //add*** 编译工程后进入调试模式 打开Jlink RTT查看日志输出     这里往QSPI Flash的起始地址写入一行字符串,并读出该地址的字符数据,如果写入的数据与读出的数据一致,说明QSPI Flash读写测试成功 二、OSPI配置 2.1 使用e2 studio新建MCU自定义工程     打开开发板原理图文件,找到OSPI Flash的原理图       在FSP配置界面找到Pins栏,引脚配置与原理图一致,注意引脚组选项为Mixed 操作模式为Custom   在stacks栏新增ospi flash   ospi flash stack属性设置保持默认,由于OPSI外设使用独立的OCTASPICLK时钟信号,需要在Clocks配置OSPI的时钟信号,时钟树配置如下   2.2 在工程目录src下新建bsp文件夹,并新建ospi的两个c/h驱动文件 bsp_ospi_flash.h头文件内容如下     bsp_ospi_flash.h头文件内容如下 /*  * bsp_ospi_flash.h  *  *  Created on: 2024年11月17日  *      Author: quansirx  */ #ifndef OSPI_FLASH_BSP_OSPI_FLASH_H_ #define OSPI_FLASH_BSP_OSPI_FLASH_H_ #include "hal_data.h" #include "r_ospi.h" #define RESET_VALUE             (0x00) void QSPI_Flash_Init(void); fsp_err_t ospi_init(void); #endif /* OSPI_FLASH_BSP_OSPI_FLASH_H_ */ bsp_ospi_flash.c文件内容如下 /*  * bsp_ospi_flash.c  *  *  Created on: 2024年11月17日  *      Author: quansirx  */ #include "bsp_ospi_flash.h" void QSPI_Flash_Init(void){ //    bsp_octaclk_settings_t octaclk        = {RESET_VALUE}; //    octaclk.source_clock = BSP_CFG_OCTA_SOURCE;  /* 200MHz */ //    octaclk.divider      = BSP_CLOCKS_OCTA_CLOCK_DIV_2; //    R_BSP_OctaclkUpdate(&octaclk);//更新OSI 时钟频率 // //    fsp_err_t          err                =  FSP_SUCCESS; //    err = ospi_init();     R_OSPI_Open(&g_ospi_ctrl, &g_ospi_cfg); } spi_flash_cfg_t     g_loc_ospi_cfg; ospi_extended_cfg_t g_loc_ospi_extnd_cfg; #define DEVICE_SECTOR_SIZE                              (4096U) #define DEVICE_BLOCK_SIZE                               (65536U) #define INITIAL_INDEX                                   (0U) #define OSPI_OPI_CMD_ERASE_SECTOR                       (0x21DEU) #define OSPI_OPI_CMD_ERASE_BLOCK                        (0xDC23U) #define OSPI_OPI_CMD_ERASE_CHIP                         (0xC738U) static const spi_flash_erase_command_t opi_erase_command_list[] = {  { .command = OSPI_OPI_CMD_ERASE_SECTOR, .size = DEVICE_SECTOR_SIZE },  { .command = OSPI_OPI_CMD_ERASE_BLOCK, .size = DEVICE_BLOCK_SIZE },  { .command = OSPI_OPI_CMD_ERASE_CHIP, .size = SPI_FLASH_ERASE_SIZE_CHIP_ERASE }, }; fsp_err_t ospi_init(void) {     fsp_err_t err                = FSP_SUCCESS;     /*Configuration setup of Extended SPI configuration into local config*/     ospi_extended_cfg_t* textd = NULL;     textd = (void *)g_ospi_cfg.p_extend;     g_loc_ospi_extnd_cfg = *textd;     g_loc_ospi_cfg =  g_ospi_cfg;     g_loc_ospi_cfg.p_erase_command_list = &opi_erase_command_list[INITIAL_INDEX];     g_loc_ospi_cfg.p_extend = &g_loc_ospi_extnd_cfg;     /* In the current OSPI device model, the default status of the device is set to SPI mode.      * Therefore, it is necessary to initialize the OSPI driver module in SPI mode      * to ensure compatibility with the device's default SPI protocol.      */     g_loc_ospi_cfg.spi_protocol = SPI_FLASH_PROTOCOL_EXTENDED_SPI;     /*Open Octa Flash device in Extended SPI Mode */     err = R_OSPI_Open(&g_ospi_ctrl, &g_loc_ospi_cfg);     if (FSP_SUCCESS != err)     {         //APP_ERR_PRINT ("\r\n** R_OSPI_Open API FAILED **\r\n");     }     return err; } 三、DAC波形测试 以快速向导工程为模版,驱动DAC产生正弦波波形 3.1 打开quickstart_ek_ra6m5_ep工程下FSP配置文件 在stack栏新增DAC外设   pins栏配置DAC输出引脚为P014   DAC波形产生需要使用定时器,这里使用示例工程中g_gpt_blue这一定时器   g_gpt_blue定时器已经使能定时器溢出中断,中断回调函数为gpt_blue_callback 使用全局搜索gpt_blue_callback,找到gpt_blue_callback的函数定义     gpt_blue_callback定义在common_init.c文件 在gpt_blue_callback添加以下内容 #include "math.h" #define M_PI 3.141592 /**********************************************************************************************************************  * 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 */     uint16_t dacvalue=0;     static double w=0.0;     w+=M_PI/90;     if(w>=2*M_PI){         w=0.0;     }     dacvalue=4095*(cos(w)+1)/2;     R_DAC_Write(&g_dac0_ctrl, dacvalue);     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];         }     } }   进行程序调试 我这里没有示波器观察DAC波形,使用e2 studio内置的real-time chart观察dacvalue的变化情况        因为real-time chart的刷新速率慢,所以波形会有些失真

  • 2024-11-16
  • 发表了主题帖: 【Follow me第二季第3期】入门任务---调试程序、Blink及按键测试

    本帖最后由 quansirx 于 2024-11-16 14:28 编辑 一、 瑞萨EK-RA6M5开发板支持e2 studio、IAR、Keil MDK等IDE工具进行编程开发,我使用官方基于Eclipse开源IDE制作的e2 studio,由于是官方IDE工具因此开发支持力度相对好一些。 e2 studio的安装可以参考老师的讲解视频,以下来进行调试示例程序,LED等Blink,按键操作等内容 二、e2 studio调试示例程序 下载Renesas官方FSP例程,网址链接为https://github.com/renesas/ra-fsp-examples   以上为解压的文件内容,打开e2 studio工具并导入开发板quickstart例程   鼠标右击构建项目,编译通常后开始项目调试   调试选项选第3个   打开插件终端工具,设置参数如上图所示,串口通信波特率为115200   终端菜单选项: 键盘按下数字键1,开发板基本信息一览   QSPI、OSPI Flash读写速度测试   三、Blink、按键测试 3.1 LED Blink 新建e2 studio 基本FSP工程   TrustZone设置     屏幕剪辑的捕获时间: 2024-11-16 12:38 不使用RTOS   点击创建最小基本工程   基本工程结构一览 板载LED原理图   在原理图找到板载LED的引脚连接情况,LED1连接在P006引脚 打开配置xml文件 选中Pins这一栏,输入引脚编号P006以自动定位到该引脚配置界面 板载LED1为共阴极接法,于是设P006默认输出高电平 P001引脚配置的初始化代码 烧录固件至开发板 LED1成功点亮   添加循环点亮LED代码,在hal_entry函数处 void hal_entry(void) { /* TODO: add your own code here */ while(1){ R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06, BSP_IO_LEVEL_HIGH); //LED1亮 R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS); //延时500ms R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06, BSP_IO_LEVEL_LOW); //LED1灭亮 R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS); //延时500ms } #if BSP_TZ_SECURE_BUILD /* Enter non-secure code */ R_BSP_NonSecureEnter(); #endif } 实验效果   3.2 按键测试 查看按键原理图   按键2连接至P004引脚,引脚状态默认为上拉,按键按下后引脚电平为低电平 xml配置   示例代码 void hal_entry(void) { /* TODO: add your own code here */ uint8_t t=150; while(1){ R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06, BSP_IO_LEVEL_HIGH); //LED3亮 R_BSP_SoftwareDelay(t, BSP_DELAY_UNITS_MILLISECONDS); //延时500ms R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06, BSP_IO_LEVEL_LOW); //LED1灭亮 R_BSP_SoftwareDelay(t, BSP_DELAY_UNITS_MILLISECONDS); //延时500ms KeyScan(BSP_IO_PORT_00_PIN_04); } #if BSP_TZ_SECURE_BUILD /* Enter non-secure code */ R_BSP_NonSecureEnter(); #endif } void KeyScan(bsp_io_port_pin_t key); void KeyScan(bsp_io_port_pin_t key){ bsp_io_level_t key_state; R_IOPORT_PinRead(&g_ioport_ctrl, key, &key_state); if(key_state==BSP_IO_LEVEL_LOW){ //软件消抖 R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS); //点亮LED2 R_IOPORT_PinWrite(&g_ioport_ctrl, LED2, BSP_IO_LEVEL_HIGH); //LED2亮 //等待按键松开 while(key_state==BSP_IO_LEVEL_LOW){ R_IOPORT_PinRead(&g_ioport_ctrl, key, &key_state); } //熄灭LED2 R_IOPORT_PinWrite(&g_ioport_ctrl, LED2, BSP_IO_LEVEL_LOW); //LED2灭 } } 按键实验结果  

  • 2024-11-15
  • 发表了主题帖: 【Follow me第二季第3期】EK-RA6M5开箱帖

    本帖最后由 quansirx 于 2024-11-15 23:48 编辑 一、     很幸运能够参加本次得捷&EEWorld举办的第二季3期开发板学习活动,申请通过之后马上到得捷官网购买了EK-RA6M5开发板,不得不说从得捷官网下单也是一次愉快的购物体验,主要是元器件品质的可靠性得到保证,经过两周多终于交付手上。这也是本人首次使用瑞萨的MCU产品,非常期待本次的瑞萨开发之旅 二、EK-RA6M5简介 EK-RA6M5 是瑞萨电子(Renesas Electronics)推出的一款基于 ARM Cortex-M33 核心的微控制器(MCU)。它是瑞萨 RA 系列的一部分,专为高性能、低功耗应用设计,具有广泛的外设和强大的处理能力。下面是该微控制器的一些关键特点和简介: 1. 处理器核心 核心架构:ARM Cortex-M33,支持 TrustZone技术,用于增强安全性。 主频:高达 200 MHz,适用于对性能要求较高的嵌入式应用。 2. 内存配置 闪存(Flash):最多 2 MB。 RAM:最大 512 KB。 3. 外设支持 提供丰富的外设接口,如 UART、I2C、SPI、CAN、ADC、DAC 等,支持多种通信和控制需求。 具备多通道的 PWM(脉宽调制)和 定时器,适合各种嵌入式应用。 内建硬件加速的加密引擎(AES、RSA等),使得加密和解密操作更加高效,增强了数据安全性。 4. 低功耗特性 EK-RA6M5 采用了低功耗设计,支持多种省电模式,适用于对电池寿命要求较长的设备。 5. 开发和调试支持 EK-RA6M5 提供了完整的开发套件和工具支持,用户可以通过 E2Studio IDE 或 IAR Embedded Workbench 等开发环境进行开发。 支持标准的调试接口,如 J-Link,方便开发和调试。 6. 应用领域 EK-RA6M5 适用于各种嵌入式应用,如智能家居、工业控制、物联网设备、医疗设备等。 由于其高效的性能和低功耗特点,它也适合于电池驱动设备和需要处理加密数据的应用场景 图1 EK-RA6M5板载资源一览 三、EK-RA6M5开箱     得捷包装快递箱    EK-RA6M5开发板包装盒,看着非常简约大气 内附物品有: EK-RA6M5开发板 1块 MicroUSB数据线 1根 RJ45接头网线 1根 MicroUSB OTG接头 1个 四、通电测试 开发板出厂出厂固件测试: 1.使用按键S1、S2更改LED1、LED2的显示亮度,刷新速率;       2.USB连接PC进行USB 模拟串口通信; 3.Web服务器等   五、结语 总的来说,这款EK-RA6M5开发板板载资源丰富,e2 studio是初次接触感觉操作也很不错。FSP提供的例程涵盖了大部分板载的外设驱动,有以上工具和内容丰富的例程以及社区论坛的支持,学习这款MCU的编程开发相信会非常便捷的

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

  • 2024-11-12
  • 加入了学习《TI MSPM0 MCU》,观看 视频3

  • 加入了学习《TI MSPM0 MCU》,观看 视频2

最近访客

< 1/1 >

统计信息

已有9人来访过

  • 芯积分:57
  • 好友:--
  • 主题:6
  • 回复:8

留言

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


现在还没有留言