EPTmachine

  • 2025-03-25
  • 回复了主题帖: >>征集 | 晒电机控制痛点与难题,一起寻求最优解!

    芯片选型:高度集成的TMC9660集成驱动器和控制IC,简化电机控制中的弱电控制强电的电路设计,节省PCB面积的同时,降低布线的难度; 效率优化和控制精度:集成除功率管外的控制部分的算法,方便开发的同时,降低系统的响应时间,是控制回路更为紧凑,降低硬件上的时延,提高系统控制的效率,为更为精细的控制算法提供硬件支持; 抗干扰性、电磁干扰和成本控制:单芯片的设计在减少元器件使用的同时,也减少器件本身的寄生电容、电感对电路的扰动,降低系统防干扰设计的难度,减少元器件的数量和生产成本,提高产品供应链的稳定性; 算法、安全和工具使用:采用硬件伺服控制器、硬件轨迹曲线控制器,在保证电机控制实时性的同时,也避免由于系统故障导致的冲击的发生概率,提高电机产品的安全性;丰富的在线文档为用户使用工具提供便利,ADI自身在模拟领域的丰富经验,助力工程师开发电机,提高产品的质量; 热管理:70V智能栅极驱动硬件和单电源Buck转换器,使电机控制系统的能源使用便于管理,减少因为供电电路复杂导致的额外电能消耗,降低系统的热量产生。  

  • 2025-01-10
  • 回复了主题帖: 【回顾2024,展望2025】新年抢楼活动来啦!

    最想关注嵌入式音频和AI计数

  • 2024-12-24
  • 回复了主题帖: 2025年测评中心,DigiKey得捷赞助继续,欢迎跟帖推你期待的上线的测品啦~

    BeagleBone® Black 是一款面向开发人员和业余爱好者的低成本、高扩展、并有社区支持的开发平台。处理器选用了TI AM3358芯片,基于ARM Cortex-A8架构处理器。还配备了丰富的扩展资源,包括HDMI接口、以太网、SD 卡槽、并预留了足够多的管脚用于AD转换、LCD显示屏、PWM输出、I2C、串口等等。板卡可运行完整的 Linux 系统,且支持多种编程语言。

  • 2024-12-15
  • 发表了主题帖: 【Follow me第二季第3期】EK-RA6M5简易信号发生器设计汇总

    本帖最后由 EPTmachine 于 2025-1-6 22:14 编辑 本次Follow Me活动使用的开发板为Renesas的EK_RA6M5开发板。主要实现以下几个任务。 入门任务:搭建环境,下载调试示例程序,Blink,按键; 基础任务:quad-spi flash和octo-spi flash配置及读写速度测试;DAC配置生成波形及性能测试; 进阶任务:示例程序中新增命令打印信息; 扩展任务:设计一个类似信号发生器功能的例程。可在示例程序上修改。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息。 [localvideo]da54068e218459c5756737773eb2c7b5[/localvideo] # 入门任务: 任务相关的内容[【Follow me第二季第3期】1入门任务:搭建环境,下载调试示例程序,Blink,按键](https://bbs.eeworld.com.cn/thread-1298133-1-1.html) 入门任务通过调用bsp中的延时函数,实现周期控制,在延时完成后,改变连接LED的IO的输出状态,从事而实现LED灯闪烁的功能。连接按键的IO配置为中断输入,接收外部的中断信号,设置相应的标志变量,在主程序中检测对应的标志变量,改变延时的时间长短,影响LED灯的闪烁频率。程序的流程图如下: 中断程序检测部分代码(位于“button.c中”): ```c void button1_callback(external_irq_callback_args_t *p_args) { /* Make sure it's the right interrupt*/ if(USER_SW1_IRQ_NUMBER == p_args->channel) { g_sw1_press = true; } } void button2_callback(external_irq_callback_args_t *p_args) { /* Make sure it's the right interrupt*/ if(USER_SW2_IRQ_NUMBER == p_args->channel) { g_sw2_press = true; } } ``` 主程序中检测按键状态变量和控制LED输出引脚的代码如下(位于“hal_entry.c中”) ```c while (1) { /* Toggle user LED1 when user button1 is pressed*/ if(true == g_sw1_press) { /* Clear user button1 flag */ g_sw1_press = false; /* Read user LED pin */ err = R_IOPORT_PinRead(&g_ioport_ctrl, (bsp_io_port_pin_t)leds.p_leds[0], &led1_level); /* Handle error */ if (FSP_SUCCESS != err) { /* Close External IRQ module.*/ button_deinit(); } /* Reverse LED pin state*/ led1_level ^= BSP_IO_LEVEL_HIGH; /* Toggle user LED */ err = R_IOPORT_PinWrite(&g_ioport_ctrl, (bsp_io_port_pin_t)leds.p_leds[0], led1_level); /* Handle error */ if (FSP_SUCCESS != err) { /* Close External IRQ module.*/ button_deinit(); } } /* Change user LED2 blink feq when user button2 is pressed*/ if(true == g_sw2_press) { /* Clear user button2 flag */ g_sw2_press = false; switch(feq_level) { case slow_speed: feq_level=normal_speed; freq_in_hz=1; break; case normal_speed: feq_level=high_speed; freq_in_hz=2; break; case high_speed: feq_level=slow_speed; freq_in_hz=5; break; } delay = bsp_delay_units / freq_in_hz; } err = R_IOPORT_PinWrite(&g_ioport_ctrl, (bsp_io_port_pin_t)leds.p_leds[1], led2_level); /* Toggle level for next write */ if (BSP_IO_LEVEL_LOW == led2_level) { led2_level = BSP_IO_LEVEL_HIGH; } else { led2_level = BSP_IO_LEVEL_LOW; } /* Delay */ R_BSP_SoftwareDelay(delay, bsp_delay_units); } ``` 工程的效果如图 e2studio的开发环境功能多样,在熟悉各部分功能的使用后,可以借助FSP工具、Deverlop Asssitant代码提示加快开发进度。 # 基础任务: 任务相关的内容[【Follow me第二季第三期】基础任务:quad spi、octo spi、dac和定时器使用]( https://bbs.eeworld.com.cn/thread-1301167-1-1.html) 板载的外设很多,quad spi flash和octo spi flash扩展了开发板的存储空间,可以存储更多的程序和数据,实现复杂的应用,同时FSP配置工具中可以快捷地设定相关外设的驱动代码,方便外设的使用减少开发人员的工作量。 测量quad spi flash和octo spi flash 的基本思路为: 相关的代码如下(位于gpt_timer.c中): ```c fsp_err_t start_gpt_timer (timer_ctrl_t * const p_timer_ctl) { fsp_err_t err = FSP_SUCCESS; /* Starts GPT timer */ err = R_GPT_Start(p_timer_ctl); if (FSP_SUCCESS != err) { /* In case of GPT_open is successful and start fails, requires a immediate cleanup. * Since, cleanup for GPT open is done in start_gpt_timer,Hence cleanup is not required */ APP_ERR_PRINT ("\r\n ** R_GPT_Start API failed ** \r\n"); } return err; } void report_timer_count(void) { fsp_err_t err = FSP_SUCCESS; timer_status_t timer_info; uint32_t time_counter=0; err=stop_gpt_timer (&g_timer_ctrl); err=get_gpt_timer_status(&g_timer_ctrl,&timer_info); err=reset_gpt_timer (&g_timer_ctrl); time_counter=timer_info.counter; APP_PRINT("\nOperation on Flash Completed Successfully,Time Cost: %d ticks under %d HZ \r\n",time_counter,timer_freq); } ``` 实际运行时,可以得到OSPI在SPI模式、SOPI、DOPI模式下的读写操作耗时。通过Segger RTT工具输出的定时器计数频率在100MHz时,读写4096字节数据的测试信息如下。 SPI模式下写时间耗时3.26ms,读时间耗时5.1ms SOPI模式下写时间耗时2.6ms,读时间耗时1.6ms DOPI模式下写时间耗时2.5ms,读时间耗时1.5ms 使用DAC输出方波,配置DAC和定时器,在定时器中断中改变DAC输出寄存器的值,从而输出周期为定时器频率一半的方波,大致的流程如下: 主函数中对定时器和DAC进行初始化(位于“hal_entry.c中”) ```c /* Open the DAC channel */ err = R_DAC_Open (&g_dac1_ctrl, &g_dac1_cfg); /* Write value to DAC module */ err = R_DAC_Write (&g_dac1_ctrl, DAC_MIN_VAL); /* Start DAC conversion */ err = R_DAC_Start (&g_dac1_ctrl); /*Initialize Periodic Timer */ err = init_gpt_timer(&g_timer0_ctrl, &g_timer0_cfg); /* Start Periodic Timer*/ err = start_gpt_timer(&g_timer0_ctrl); ``` 回调函数每次调用会修改DAC的数据寄存器中的值,改变DAC输出的电压值,从而生成方波。(位于“gpt_timer.c中”) ```c void timer0_callback(timer_callback_args_t *p_args) { /* TODO: add your own code here */ if(TIMER_EVENT_CYCLE_END==p_args->event) { if(dac_output==DAC_MIN_VAL) { dac_output=DAC_MAX_VAL; } else if(dac_output==DAC_MAX_VAL) { dac_output=DAC_MIN_VAL; } R_DAC_Write (&g_dac1_ctrl,dac_output); } } ``` 使用示波器采集输出端的信号,得到的是500Hz,幅值为3.3V的方波。 # 进阶任务: 任务相关的内容[【Follow me第二季第三期】进阶任务:通过USB发送指令修改QSPI中的数据 ](https://bbs.eeworld.com.cn/thread-1301875-1-1.html) USB设备可以设定端点类型为CDC设备,从而实现与电脑的通讯,建立通讯后后,通过控制台向开发板发送数据,从而实现数据交互和指令控制。 根据接受到的数据的不同,提示用户输入相关的输入,从而实现对qspi flash中存储的数据的修改。 示例程序的流程图如下 添加指令的核心在与添加可以被识别的菜单选项(menu option),指令的识别和执行的流程图如下: 实现上述功能的代码在工程的menu_dds_record.c和menu_dds_record.h中,其中的dds_record_menu()为处理Flash中数据的具体流程 ```c test_fn dds_record_menu(void) { int8_t c = -1; bool_t valid_dds_index = false; bool_t valid_dds_type = false; bool_t valid_dds_freq = false; int32_t block_sz_ndx = 0; int32_t block_sz_limit = (INPUT_BUFFER - 2); uint8_t dds_index; uint8_t dds_type; uint32_t dds_freq; uint32_t value=0; 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, MODULE_NAME, g_selected_menu); print_to_console((void*)s_print_buffer); for(uint8_t index=0;index= 10000 && freq < 100000) { // FMCLK = 2MHz, 100M / 100 * 2 = 2MHz R_GPT_PeriodSet(&g_timer_dds_ctrl, 50-1); dds.lutLen = (uint32_t)(2000000 / freq); getNewWaveLUT(dds.lutLen, dds.waveType, dds.amp, dds.offset); } // Restart DAC DMA Transfer g_dma_dds_cfg.p_info->length=dds.lutLen; g_dma_dds_cfg.p_info->p_src=dds_lut; g_dma_dds_cfg.p_info->p_dest=&g_dac0_ctrl.p_reg->DADR[g_dac0_ctrl.channel_index]; R_DMAC_Reconfigure(&g_dma_dds_ctrl, g_dma_dds_cfg.p_info); R_DMAC_Enable(&g_dma_dds_ctrl); //HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)dds_lut, dds.lutLen/2, DAC_ALIGN_12B_R); R_GPT_Start(&g_timer_dds_ctrl); if (dds.enable) { } } void getNewWaveLUT(uint32_t length, uint8_t type, uint8_t amp, int8_t offset) { uint16_t a_offset_value = DAC_AMP - (int32_t)DAC_AMP * offset / DDS_MAX_AMP; if (type == SINE_WAVE) { float sin_step = 2.0f * 3.14159f / (float)(length-1); for (uint16_t i = 0; i < length; i++) { dds_lut = (uint16_t)(a_offset_value - (DAC_AMP * sinf(sin_step*(float)i) * amp / DDS_MAX_AMP)); } } else if (type == SQUARE_WAVE) { for(uint16_t i = 0; i < length / 2; i++) { dds_lut = a_offset_value - DAC_AMP * amp / DDS_MAX_AMP; dds_lut[i + (length / 2)] = a_offset_value + DAC_AMP * amp / DDS_MAX_AMP; } } else if (type == TRIANGLE_WAVE) { uint16_t tri_step = DAC_AMP * 2 * amp / DDS_MAX_AMP / (length/2); for(uint16_t i = 0; i < length / 2; i++) { dds_lut = a_offset_value - DAC_AMP * amp / DDS_MAX_AMP + tri_step*i; dds_lut[length - i - 1] = dds_lut; } } } ``` 实验效果: 产生正弦波 产生方波 产生三角波 # 总结 开发板的硬件资源和示例代码很多,方便开发者理解如何使用芯片的功能。同时e2studio的开发工具辅助开发者快速搭建应用程序,加快开发进度。 任务代码:

  • 上传了资料: FollowMeEK-RA6M5

  • 发表了主题帖: 【Follow me第二季第三期】扩展任务:设计一个类似信号发生器功能的例程

    本帖最后由 EPTmachine 于 2024-12-15 12:12 编辑 设计程序能发出不同的波形,频率范围1——1kHz,支持正弦波、方波和三角波。 ## 程序设计 在MCU上实现信号发生器的功能,参考以下两篇博客 [STM32片上DAC实现DDS](https://www.emoe.xyz/stm32-dac-direct-digital-synthesis/) [STM32口袋仪器设计](https://www.eetree.cn/project/546) 采用其中的DDS模块实现信号的输出。结合之前任务中使用到的USB、QSPI Flash外设即可实现类似信号发生器的功能。 ## 程序实现 在FSP中添加以下的模块 涉及到DDS功能的模块有dac、gpt和dma模块。其中dac模块的参数设置如下 gpt模块设置如下 dma模块设置如下 DMA的数据搬运由定时器的溢出事件驱动。瑞萨DMA模块的使用和STM32的类似,在dds.c的DDS_setWaveParams函数中,通过修改DMA的数据源,加载不同的DDS查找表,从而实现不同配置波形的产生。 类似于任务3的Flash存储数据示例,在任务3的基础上添加以下文件,其中的代码实现DDS相关外设的初始化、DDS信号数据计算以及用户选择DDS信号配置的菜单。 添加上述代码,编译完成即可实现DDS信号发生器的功能,同时用户可以编辑信号的类型和频率。 # 程序演示 产生正弦波 产生方波 ![alt text](figures/04/dds_squ.jpg) 产生三角波 相关示例代码

  • 发表了主题帖: 【Follow me第二季第三期】进阶任务:通过USB发送指令修改QSPI中的数据

    本帖最后由 EPTmachine 于 2024-12-15 12:07 编辑 查看开发资料中演示例程的流程图了解控制台指令是如何实现的。开发板通过USB接口连接到电脑后,通过对电脑端发送的字符串进行解析,从而执行不同的功能函数。 # USB传输字符串并解析 USB通讯中,客户端(这里为开发板)可以设定端点(endpoint)的类型,实现不同的功能,本任务中使用的CDC类型的端点,通过usb连接至电脑后,可以实现串口通讯功能,传输数据,实现人机交互。 实现上述功能需要用的到外设有qspi、usb。在FSP的配置界面中添加需要用到的组件、定义的RTOS线程以及信号量等。 USB模块使用USB_PCDC,FSP工具可以生成USB CDC类型端点的代码,简化开发流程。 属性界面中设置CallBack的函数名。 QSPI的配置参考基础任务中的qspi配置。 # 添加新指令 任务目标是添加一条新指令,指令的功能设定为查看和修改存储在QSPI Flash上的DDS数据。存储在QSPI Flash上的数据结构为dds_record,dds_record的定义如下。 ```c typedef struct dds_param{ uint8_t waveType; uint8_t amp; int8_t offset; uint32_t freq; }dds_param_t; enum dds_wavetype{ SIN_WAVE=0, SQU_WAVE=1, TRI_WAVE=2 }; #define DDS_RECORD_TYPE 0xF5 typedef struct dds_record{ uint8_t type; dds_param_t dds_items[10]; }dds_record_t; ``` # 程序设计 程序设计参考示例程序的框架,包含的文件中新的文件如图所示。dds_record.c、dds_record.h和dds_record_ctrl_entry.c实现在QSPI Flash中管理数据的功能。menu_dds_record.c、menu_dds_record.h实现指令解析部分。 新文件中的代码为实现新指令的代码。 Flash存储相关的代码会初始化qspi flash,并对需要存储的数据进行管理。 ```c #include "common_init.h" #include "common_utils.h" #include "qspi_drv.h" #define DDS_RECORD_SIZE 1024 static char_t s_print_buffer[BUFFER_LINE_LENGTH] = {}; extern dds_record_t dds_record_ins; /* DDS_record entry function */ /* pvParameters contains TaskHandle_t */ void dds_record_ctrl_entry(void *pvParameters) { FSP_PARAMETER_NOT_USED (pvParameters); fsp_err_t err; uint8_t* p_src=(uint8_t *)QSPI_DEVICE_START_ADDRESS;; uint8_t* p_dest=(uint8_t*)&dds_record_ins; qpi_init(); memcpy (p_dest, p_src, sizeof(dds_record_t)); if(dds_record_ins.type!=DDS_RECORD_TYPE) { /* Erase Flash for one sector */ err = R_QSPI_Erase(&g_qspi_ctrl, p_src, SECTOR_SIZE); if (FSP_SUCCESS != err) { sprintf(s_print_buffer, "R_QSPI_Erase Failed\r\n"); print_to_console((void*)s_print_buffer); } } /* TODO: add your own code here */ while (1) { while (pdPASS != xSemaphoreTake(g_store_dds_semaphore, pdMS_TO_TICKS(500u))) { vTaskDelay(10); } dds_record_ins.type=DDS_RECORD_TYPE; /* Erase Flash for one sector */ err = R_QSPI_Erase(&g_qspi_ctrl, p_src, SECTOR_SIZE); if (FSP_SUCCESS != err) { sprintf(s_print_buffer, "R_QSPI_Erase Failed\r\n"); print_to_console((void*)s_print_buffer); } err = get_flash_status(); err = R_QSPI_Write(&g_qspi_ctrl, (uint8_t*)&dds_record_ins, p_src, sizeof(dds_record_t)); if (FSP_SUCCESS != err) { sprintf(s_print_buffer, "R_QSPI_Write Failed\r\n"); print_to_console((void*)s_print_buffer); } err = get_flash_status(); sprintf (s_print_buffer, "g_store_dds_semaphore recevied" ); print_to_console((void*)s_print_buffer); memcpy (p_dest, p_src, sizeof(dds_record_t)); vTaskDelay (10); } } ``` 上述代码在初始化QSPI Flash后,读取其中的数据,并等待g_store_dds_semaphore信号量,用于更新Flash中存储的内容。 USB CDC模块中,用户需要自定义相关的端点描述符用于设备的枚举。相关的代码参考示例程序在r_usb_pcdc_descriptor.c中。 usb的Callback中转发接受到的事件,用于后续的字符解析。 ```c void usb_console_callback(usb_event_info_t* p_event_info, usb_hdl_t hdl, usb_onoff_t state) { /* Void unused args */ FSP_PARAMETER_NOT_USED(hdl); FSP_PARAMETER_NOT_USED(state); BaseType_t xHigherPriorityTaskWoken; memcpy(&s_usb_event_list[s_usb_event_pindex], p_event_info, sizeof(usb_event_info_t)); if (xQueueIsQueueFullFromISR(g_usb_transaction_queue) == pdFALSE) { xQueueSendToBackFromISR(g_usb_transaction_queue, &s_usb_event_pindex, &xHigherPriorityTaskWoken); /* set next available index, cast to maintain sign integrity */ s_usb_event_pindex = (uint8_t)((s_usb_event_pindex + 1) % USB_QUEUE_SIZE); } else { /* Fatal error - usb message queue is full, this should not occur unless there has been a fatal USB error */ //SYSTEM_ERROR } /* Switch context if necessary. */ if (xHigherPriorityTaskWoken) { taskYIELD (); } } ``` 后续对字符串的处理参考示例代码中usb_console_main.c的实现。 USB交互相关的部分则对用户的输入进行解析,修改DDS_record中数据,数据修改完成后,向Flash存储任务发出信号量g_store_dds_semaphore,进行存储数据的更新。主要的代码menu_dds_record.c的dds_record_menu函数中。相关的代码在工程的dds_record_menu函数中。 # 实际测试 工程编译并下载后,效果运行的效果如下所示。能够对Flash中存储的数据进行读写管理。 相关工程代码

  • 2024-12-07
  • 发表了主题帖: 【Follow me第二季第三期】基础任务:quad spi、octo spi、dac和定时器使用

    本帖最后由 EPTmachine 于 2024-12-7 11:09 编辑 基础任务:quad-spi flash和octo-spi flash配置及读写速度测试;DAC配置生成波形及性能测试; 评估板上提供了很多外设可供测试。借助瑞萨提供FSP(Flexiable Software Package)工具,可以配置外设和引脚的参数,生成相应的驱动代码,用户在此基础上能快速开放相应的应用代码开发和调试。本帖对板上的FLASH芯片读写性能和芯片的DAC性能进行测试。 任务涉及的外设有: - RA6M5的quad spi - RA6M5的octo spi - 板载的Quand-SPI flash-MX25L25645G - 板载的Octo-SPI Flash-MX25LM51245GM - RA6M5的DAC - RA6M5的定时器 ## quad-spi flash配置及读写速度测试 在官方提供的ek-ra6m5-exampleprojects.zip中有很多例程可供参考,详情见附件。这里参考例程中的gpt和qspi来完成flahs的配置和读写速度测试。 在gpt的例程中,对通用定时器进行设置,配置为周期工作模式,同时配合Segger RTT组件实现上位机与开发板之间的交互。参考例程的设计, ### 添加Segger RTT模块实现上位机和开发板的交互 将gpt例程中的Segger RTT文件夹和common_utils.h头文件 添加到新建工程的src文件夹下, 在其他文件中包含common_utils.h头文件后,就可以使用Segger RTT的功能。 ### 使用定时器进行时间测量 使用定时器的周期性中断功能,在中断发生时,进行时间技术,从而实现时间测量功能,用于计算某段代码的执行时间,从而计算出flash的读写速度。 在FSP的Stacks界面中添加gpt组件 设置定时器的参数,包括定时器工作模式、中断函数名、中断使能和优先级(设定优先级后默认使能该中断) 点击生成代码后,在工程中添加gpt_timer.c和gpt_timer.h,其中的代码如下,实现定时器的初始化、启动、Segger_RTT交互功能、定时器回调函数处理。 gpt_timer.h代码如下 ```c #ifndef GPT_TIMER_H_ #define GPT_TIMER_H_ /* Macros definitions */ #define GPT_MAX_PERCENT (100U) /* Max Duty Cycle percentage */ #define BUF_SIZE (16U) /* Size of buffer for RTT input data */ #define PERIODIC_MODE_TIMER (1U) /* To perform GPT Timer in Periodic mode */ #define INITIAL_VALUE ('\0') #define TIMER_UNITS_MILLISECONDS (1000U) /* timer unit in millisecond */ #define CLOCK_TYPE_SPECIFIER (1ULL) /* type specifier */ /* GPT Timer Pin for boards */ #define TIMER_PIN (GPT_IO_PIN_GTIOCB) #if defined (BOARD_RA2A1_EK) || defined (BOARD_RA4W1_EK) #define GPT_MAX_PERIOD_COUNT (0XFFFF) /* Max Period Count for 16-bit Timer*/ #else #define GPT_MAX_PERIOD_COUNT (0XFFFFFFFF) /* Max Period Count for 32-bit Timer*/ #endif #define START_GPT (1U) /* To Set the period of GPT */ #define CLOSE_GPT (2U) /* To stop of GPT Timer */ #define QSPIWRITE_MODE (3U) /* To test the qspi flash write function*/ #define QSPIREAD_MODE (4U) /* To test the qspi flash read function*/ /* Function declaration */ fsp_err_t init_gpt_timer(timer_ctrl_t * const p_timer_ctl, timer_cfg_t const * const p_timer_cfg, uint8_t timer_mode); fsp_err_t start_gpt_timer (timer_ctrl_t * const p_timer_ctl); uint32_t process_input_data(void); void deinit_gpt_timer(timer_ctrl_t * const p_timer_ctl); void print_timer_menu(void); uint32_t timer_GetRunTime(void); #endif /* GPT_TIMER_H_ */ ``` gpt_timer.c代码如下 ```c __IO uint32_t g_iRunTime = 0; /* Store Timer open state*/ uint8_t g_timer_open_state = RESET_VALUE; extern bsp_leds_t g_bsp_leds; /* Holds level to set for pins */ bsp_io_level_t pin_level = BSP_IO_LEVEL_LOW; /*******************************************************************************************************************//** * @addtogroup r_gpt_ep * @{ **********************************************************************************************************************/ /***************************************************************************************************************** * @brief Initialize GPT timer. * @param[in] p_timer_ctl Timer instance control structure * @param[in] p_timer_cfg Timer instance Configuration structure * @param[in] timer_mode Mode of GPT Timer * @retval FSP_SUCCESS Upon successful open of timer. * @retval Any Other Error code apart from FSP_SUCCES on Unsuccessful open . ****************************************************************************************************************/ fsp_err_t init_gpt_timer(timer_ctrl_t * const p_timer_ctl, timer_cfg_t const * const p_timer_cfg, uint8_t timer_mode) { fsp_err_t err = FSP_SUCCESS; /* Initialize GPT Timer */ err = R_GPT_Open(p_timer_ctl, p_timer_cfg); if (FSP_SUCCESS != err) { APP_ERR_PRINT ("\r\n ** R_GPT_TimerOpen FAILED ** \r\n"); return err; } if(PERIODIC_MODE_TIMER == timer_mode) { g_timer_open_state = START_GPT; } return err; } /***************************************************************************************************************** * @brief Start GPT timers in periodic, one shot, PWM mode. * @param[in] p_timer_ctl Timer instance control structure * @retval FSP_SUCCESS Upon successful start of timer. * @retval Any Other Error code apart from FSP_SUCCES on Unsuccessful start . ****************************************************************************************************************/ fsp_err_t start_gpt_timer (timer_ctrl_t * const p_timer_ctl) { fsp_err_t err = FSP_SUCCESS; /* Starts GPT timer */ err = R_GPT_Start(p_timer_ctl); if (FSP_SUCCESS != err) { /* In case of GPT_open is successful and start fails, requires a immediate cleanup. * Since, cleanup for GPT open is done in start_gpt_timer,Hence cleanup is not required */ APP_ERR_PRINT ("\r\n ** R_GPT_Start API failed ** \r\n"); } return err; } /***************************************************************************************************************** * @brief Process input string to integer value * @param[in] None * @retval integer value of input string. ****************************************************************************************************************/ uint32_t process_input_data(void) { unsigned char buf[BUF_SIZE] = {INITIAL_VALUE}; uint32_t num_bytes = RESET_VALUE; uint32_t value = RESET_VALUE; while (RESET_VALUE == num_bytes) { if (APP_CHECK_DATA) { num_bytes = APP_READ(buf); if (RESET_VALUE == num_bytes) { APP_PRINT("\r\nInvalid Input\r\n"); } } } /* Conversion from input string to integer value */ value = (uint32_t) (atoi((char *)buf)); return value; } /***************************************************************************************************************** * @brief Close the GPT HAL driver. * @param[in] p_timer_ctl Timer instance control structure * @retval None ****************************************************************************************************************/ void deinit_gpt_timer(timer_ctrl_t * const p_timer_ctl) { fsp_err_t err = FSP_SUCCESS; /* Timer Close API call*/ err = R_GPT_Close(p_timer_ctl); if (FSP_SUCCESS != err) { /* GPT Close failure message */ APP_ERR_PRINT ("\r\n ** R_GPT_Close FAILED ** \r\n"); } } /***************************************************************************************************************** * @brief Print GPT Timer menu option. * @param[in] None * @retval None ****************************************************************************************************************/ void print_timer_menu(void) { APP_PRINT ("\r\nMenu Options"); APP_PRINT ("\r\nEnter 1 for Start and Set the GPT timer"); APP_PRINT ("\r\nEnter 2 for Stop the GPT timer"); APP_PRINT ("\r\nEnter 3 for Writing Data to QSPI Flash test"); APP_PRINT ("\r\nEnter 4 for Reading Data from QSPI Flash test"); APP_PRINT ("\r\nUser Input: "); } uint32_t timer_GetRunTime(void) { uint32_t runtime; DISABLE_INT(); /* */ runtime = g_iRunTime; /* */ ENABLE_INT(); /* */ return runtime; } void timer_tick(timer_callback_args_t *p_args) { /* TODO: add your own code here */ if(NULL != p_args) { if (TIMER_EVENT_CYCLE_END == p_args->event) { R_IOPORT_PinWrite(&g_ioport_ctrl, (bsp_io_port_pin_t)g_bsp_leds.p_leds[1], pin_level); if (BSP_IO_LEVEL_LOW == pin_level) { pin_level = BSP_IO_LEVEL_HIGH; } else { pin_level = BSP_IO_LEVEL_LOW; } g_iRunTime++; if (g_iRunTime == 0x7FFFFFFF) /* the variable g_iRunTime expire 0x7FFFFFFF ,set it to 0*/ { g_iRunTime = 0; } } } } ``` 编译并烧写后完成后,在上位机打开J-Link RTT Viewer。在File->Connect界面设定参数如下所示: 其中RTT Control Block中地址需要在工程的Debug目录中的xxxx.map文件中寻找`_SEGGER_RTT`字段。 点击连接后可以在J-Link RTT Viewer的界面中看到提示用户输入的信息。 在菜单栏中设定输入的发送方式为按下Enter后发送 根据提示输入,即可调用不同的程序 ### Quad Flash设置 在开发板上通过qspi接口连接了QSPI Flash。 在FSP的Stacks中添加qspi模块。 qspi模块的参数设置如下所示 通过查看芯片的用户手册可知,读模式设置为"Fast Read Quad I/O"后,QSPI控制器会自动生成相应的控制指令。这样节省了用户编程工作量,可以直接使用内存操作函数,memcpy、memcmp等,提高读写性能。 ! 参考例程中的qspi flash初始化和数据操作,添加qspi flash的驱动代码如下。实现对Flash的初始化、存储块数据擦除、数据写入和读出操作。 qspi_drv.h代码如下: ```c #ifndef QSPI_DRV_H_ #define QSPI_DRV_H_ #include "common_utils.h" #include "hal_data.h" /* QSPI flash page number to be written */ #define PAGE_FIRST (0U) /* QSPI flash page Size */ #define PAGE_WRITE_SIZE (256U) #define TEST_WRITE_SIZE (256U) /* QSPI flash address through page*/ #define QSPI_FLASH_ADDRESS(page_no) ((uint8_t *) (QSPI_DEVICE_START_ADDRESS + ((page_no) * PAGE_WRITE_SIZE))) /* Status register pay-load */ #define STATUS_REG_PAYLOAD {0x01,0x40,0x00} /* data written to status register */ #define SET_SREG_VALUE (0x40) /* sector size of QSPI flash device */ #define SECTOR_SIZE (4096U) /* one byte data transfer */ #define ONE_BYTE (0x01) /* SREG pay-load size */ #define SREG_SIZE (0x03) /* default memory value */ #define DEFAULT_MEM_VAL (0xFF) /* QPI mode exit command */ #define QSPI_MX25L_CMD_EXIT_QPI_MODE (0xF5) /* QPI mode entry command */ #define QSPI_MX25L_CMD_ENTER_QPI_MODE (0x35) // #define RDID (0x9F) #define MX_MANUFACTURER_ID (0xC2) #define DEVICE_ID (0x18) #define MEMORY_TYPE (0x20) #define MEMORY_DENSITY (0x19) //function declaration void QSPI_FlashInit(void); void QSPI_EraseSector(uint8_t * address); fsp_err_t QSPI_WritePage(uint8_t *_pBuf, uint32_t _uiWriteAddr, uint16_t _usWriteSize); void QSPI_ReadBuffer(uint8_t * _pBuf, uint32_t _uiReadAddr, uint32_t _uiSize); uint32_t QSPI_ReadID(void); #endif /* QSPI_DRV_H_ */ ``` qspi_drv.c的代码如下 ```c #include "qspi_drv.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_qspi_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 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_qspi_ctrl, &(g_qspi_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_qspi_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_qspi_ctrl, SPI_FLASH_PROTOCOL_QPI); if (FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_SpiProtocolSet Failed\r\n"); } 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_qspi_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_qspi_ctrl); 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"); } void QSPI_FlashInit(void) { fsp_err_t err= FSP_SUCCESS; uint8_t data_sreg[SREG_SIZE] = STATUS_REG_PAYLOAD; if (SPI_FLASH_PROTOCOL_QPI == g_qspi_cfg.spi_protocol) { /* * this needs to be done since QPI is set by user in configuration * and it sets QPI only in MCU but not in flash device * so as a system (MCU + QSPI flash device) QPI mode does not get set by * simply calling only R_QSPI_Open in QPI mode. * Rather QPI mode enabling has to be done in Flash device as well * So opening the driver in extended SPI mode only * and QPI mode is enabled when qpi_mode_set sub-function is called */ spi_flash_cfg_t l_qspi_cfg; memcpy((spi_flash_cfg_t *)&l_qspi_cfg, (spi_flash_cfg_t *)&g_qspi_cfg, sizeof (spi_flash_cfg_t)); l_qspi_cfg.spi_protocol = SPI_FLASH_PROTOCOL_EXTENDED_SPI; APP_PRINT ("\r\n ** user selected QPI Mode in RA configuration tool ** \r\n"); /* open QSPI with local configuration */ err = R_QSPI_Open(&g_qspi_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_qspi_ctrl, &g_qspi_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_qspi_ctrl, &(g_qspi_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_qspi_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_qspi_ctrl, &(g_qspi_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 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_qspi_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_qspi_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_EraseSector(uint8_t * address) { fsp_err_t err= FSP_SUCCESS; err = R_QSPI_Erase(&g_qspi_ctrl, address, SECTOR_SIZE); if (FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_Erase Failed\r\n"); deinit_qspi(g_qspi_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_qspi_cfg.spi_protocol); APP_ERR_TRAP(err); } } } fsp_err_t QSPI_WritePage(uint8_t *_pBuf, uint32_t _uiWriteAddr, uint16_t _usWriteSize) { fsp_err_t err= FSP_SUCCESS; /* Write data to QSPI Flash */ err = R_QSPI_Write(&g_qspi_ctrl, _pBuf, (uint8_t *)QSPI_FLASH_ADDRESS(_uiWriteAddr), _usWriteSize); if (FSP_SUCCESS != err) { APP_ERR_PRINT("R_QSPI_Write Failed\r\n"); deinit_qspi(g_qspi_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_qspi_cfg.spi_protocol); APP_ERR_TRAP(err); } } return err; } //Due to the qspi Read Mode is set to Fast Read Quad I/O , the flash is mapped to the memory region at 0x6000000 void QSPI_ReadBuffer(uint8_t * _pBuf, uint32_t _uiReadAddr, uint32_t _uiSize) { /* Read data from QSPI memory region */ memcpy(_pBuf, (uint8_t *)QSPI_FLASH_ADDRESS(_uiReadAddr), _uiSize); } uint32_t QSPI_ReadID(void) { fsp_err_t err = FSP_SUCCESS; uint8_t write_data; uint8_t read_data[8]; uint32_t uiID; write_data = RDID; /* Read ID */ memset(read_data, 0, sizeof(read_data)); err = R_QSPI_DirectWrite(&g_qspi_ctrl, &write_data, 1, true); if (FSP_SUCCESS != err) { return err; } err = R_QSPI_DirectRead(&g_qspi_ctrl, read_data, 3); if (FSP_SUCCESS != err) { return err; } if ((MX_MANUFACTURER_ID != read_data[0]) || (MEMORY_TYPE != read_data[1]) || (MEMORY_DENSITY != read_data[2])) { return FSP_ERR_ASSERTION; } uiID=(read_data[0] = (uint32_t)(g_timer_cfg.source_div); /* Convert period to PCLK counts so it can be set in hardware. */ period_counts = (uint64_t)((gpt_desired_period_ms * (pclkd_freq_hz * CLOCK_TYPE_SPECIFIER)) / TIMER_UNITS_MILLISECONDS); /* Validate Period Count based on user input (time period in ms) */ if(GPT_MAX_PERIOD_COUNT < period_counts) { APP_ERR_PRINT ("\r\n ** INVALID INPUT, DESIRED PERIOD IS OUT OF RANGE. ** \r\n"); } else { /* Check the status of GPT timer in Periodic mode */ if(START_GPT != g_timer_open_state) { /*Initialize Periodic Timer */ err = init_gpt_timer(&g_timer_ctrl, &g_timer_cfg, PERIODIC_MODE_TIMER); if(FSP_SUCCESS != err) { APP_ERR_PRINT("** GPT TIMER INIT FAILED ** \r\n"); APP_ERR_TRAP(err); } APP_PRINT("Opened Timer in Periodic Mode\r\n"); /* Start Periodic Timer*/ err = start_gpt_timer(&g_timer_ctrl); if(FSP_SUCCESS != err) { APP_ERR_PRINT("** GPT TIMER START FAILED ** \r\n"); /*Close Periodic Timer instance */ deinit_gpt_timer(&g_timer_ctrl); APP_ERR_TRAP(err); } APP_PRINT("Started Timer in Periodic Mode\r\n"); } else { APP_PRINT("Periodic Timer Already Started, Update Timer Period to : %d \r\n",gpt_desired_period_ms); } /* Period Set API set the desired period counts on the on-board LED */ err = R_GPT_PeriodSet(&g_timer_ctrl, (uint32_t)period_counts); if (FSP_SUCCESS != err) { /* GPT Timer PeriodSet Failure message */ APP_ERR_PRINT ("\r\n ** R_GPT_PeriodSet API failed ** \r\n"); /*Close Periodic Timer instance */ deinit_gpt_timer(&g_timer_ctrl); APP_ERR_TRAP(err); } } break; } case CLOSE_GPT: { deinit_gpt_timer(&g_timer_ctrl); APP_PRINT("\r\n GPT timer closed,g_iRunTime is %d\r\n",g_iRunTime); g_iRunTime=0; break; } case QSPIWRITE_MODE: { uint32_t iTime1, iTime2; QSPI_EraseSector(p_mem_addr); // Fill the data write buffer further to be written in QSPI flash device for (uint16_t write_index = RESET_VALUE; write_index < TEST_WRITE_SIZE ; write_index++) { data_write[write_index] = (uint8_t)write_index; } APP_PRINT ("\r\nMeasure the time cost of qspi write\r\n"); iTime1=timer_GetRunTime(); for(uint16_t page_index = RESET_VALUE;page_index

  • 2024-11-24
  • 回复了主题帖: 【Follow me第二季第3期】1入门任务:搭建环境,下载调试示例程序,Blink,按键

    bigbat 发表于 2024-11-24 15:19 UP的原理图能传一份吗?"ek-ra6m5-v1-designpackage.zip",   我的原理图是怎样滴,我也没 ... 好的

  • 2024-11-23
  • 发表了主题帖: 【Follow me第二季第3期】1入门任务:搭建环境,下载调试示例程序,Blink,按键

    本帖最后由 EPTmachine 于 2024-11-24 21:33 编辑 # 入门任务:搭建环境,下载调试示例程序,Blink,按键 本次Follow Me活动的开发板是瑞萨的EK-RA6M5,在官网可以下载到如下的相关的资料。 官方的《EK-RA6M5 Quick Start Guide.pdf》可以帮助开发者快速了解套件的内容和使用方法。 套件包含了以下的内容 ## 搭建调试环境 e2studio是瑞萨提供的集成开发环境,包含编译器、代码编辑器、工程管理工具、芯片支持包等。 首先在e2studio的[下载页面](https://www.renesas.cn/zh/software-tool/e-studio)选择和电脑系统匹配的安装包。 下载后解压得到安装包,点击应用程序开始安装。 在安装选项中选择RA系列支持和fsp版本即可。安装过程各个界面的选项如下。 选择安装RA系列支持 点击install开始安装。 安装完成后,就可以编辑和调试代码。 ## 示例程序 针对EK-RA6M5,官方提供了丰富的示例代码和帮助文档。EK-RA6M5的产品页面提供了相应的资料和代码下载。 将下载的代码压缩包解压后,其中的示例代码如下所示: 通过菜单栏中的File->Import将工程导入到工作目录中 选择导入存在的工程到工作空间中。 选择工程所在的目录,在"Option"中勾选“Copy projects into workspace”将工程复制到工作空间中。 导入后项目栏中可以看到相应的工程。 在工程的右键选项中选择“Build Project”,完成后即可下载程序。 使用USB线连接电脑和开发板,点击调试按钮即可下载程序进行调试。 ## Blink程序 查看“EK-RA6M5 User's Manual.pdf”,板载三个LED灯的相关信息如下图。 在e2studio中创建EK-RA6M5的工程控制LED闪烁。 在菜单栏中选择"File->New->C/C++ Project" 输入工程名 选择对应的开发套件或者根据芯片型号进行工程创建 剩下的选择默认项即可 在开发瑞萨的RA系列芯片时,需要使用FSP配置工具对外设进行参数设置,在工程栏中点击“configuration.xml”即可打开FSP配置界面。 在“FSP Configuration”界面中对硬件外设和软件组件包进行管理。 查看下载资料"ek-ra6m5-v1-designpackage.zip"中的原理图可知,板上的LED的接线如图所示,控制引脚为P006、P007、P008。 在FSP界面的Pins选项卡页面可以查看相关引脚的设置。 在FSP界面的Stacks选项卡页面可以查看应用中涉及到的功能栈。Blink程序只涉及到引脚状态控制,使用r_ioport模块即可实现功能。 点击右上角的"Generate Project Content"生成相关设置的配置代码。 生成的代码中,与配置相关的部分在文件夹ra_cfg中 接下来编写相关的应用的代码。由于FSP配置生成的代码中包含main函数,每次点击"Generate Project Content"生成代码时都会对main进行改写,所以用户无法直接编写main函数的代码,用户代码的 入口就变为,在不使用RTOS实时操作系统的前提下,在src文件夹下的hal_entry.c中的hal_entry函数为用户代码入口。 hal_entry.c添加实现Blink功能的代码如下: ``` c #include "hal_data.h" FSP_CPP_HEADER void R_BSP_WarmStart(bsp_warm_start_event_t event); FSP_CPP_FOOTER extern bsp_leds_t g_bsp_leds; /*******************************************************************************************************************//** * 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 */ #if BSP_TZ_SECURE_BUILD /* Enter non-secure code */ R_BSP_NonSecureEnter(); #endif /* Define the units to be used with the software delay function */ const bsp_delay_units_t bsp_delay_units = BSP_DELAY_UNITS_MILLISECONDS; /* Set the blink frequency (must be channel) { g_sw2_press = true; } } ``` 在hal_entry函数中,通过对全局变量`g_sw1_press`、`g_sw2_press`的状态进行判断,执行相应的处理逻辑,实现按键1控制LED1蓝灯,按键2控制LED2绿灯的闪烁频率。具体代码如下: ```c #include "button.h" /* Board's user LED */ extern bsp_leds_t g_bsp_leds; /* Boolean flag to determine switch is pressed or not.*/ extern volatile bool g_sw1_press; extern volatile bool g_sw2_press; /*******************************************************************************************************************//** * 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 */ #if BSP_TZ_SECURE_BUILD /* Enter non-secure code */ R_BSP_NonSecureEnter(); #endif fsp_err_t err = FSP_SUCCESS; blink_speed_t feq_level= slow_speed; /* Define the units to be used with the software delay function */ const bsp_delay_units_t bsp_delay_units = BSP_DELAY_UNITS_MILLISECONDS; /* the blink frequency,high 5h=Hz,normal 2Hz,slow 1Hz , (must be

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

  • 2024-11-03
  • 加入了学习《【2024 DigiKey创意大赛】- 基于毫米波雷达的生命体征检测及健康监护系统》,观看 【2024 DigiKey创意大赛】- 基于毫米波雷达的生命体征检测及健康监护系统-作品提交

统计信息

已有86人来访过

  • 芯积分:480
  • 好友:--
  • 主题:47
  • 回复:126

留言

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


现在还没有留言