本帖最后由 superw 于 2025-1-13 12:37 编辑
一、视频介绍
二、任务实现详情
入门任务:搭建环境,下载调试示例程序,Blink,按键
物料清单:EK-RA6M5
设计思路:
根据出厂示例程序,通过按键外部中断控制LED灯的亮度(占空比)和闪烁快慢(频率),将按键的GPIO配置为外部中断模式,每当按下时跳转到中断服务函数中,进行占空比和频率的切换。按键默认状态下被外部电阻上拉,当按下按键时,IO为低电平,因此要配置为下降沿触发中断。
对于占空比和频率的输出,通过配置内部定时器实现输出。
软件流程图:
代码片段:
/**********************************************************************************************************************
* Function Name: button_irq10_callback
* Description : SW1 Interrupt handler.
* Argument : p_args
* Return Value : None
*********************************************************************************************************************/
void button_irq10_callback(external_irq_callback_args_t *p_args)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
BaseType_t xResult = pdFAIL;
EventBits_t uxBits;
/* Void the unused args */
FSP_PARAMETER_NOT_USED(p_args);
uxBits = xEventGroupGetBitsFromISR (g_update_console_event);
if ((uxBits & (STATUS_UPDATE_INTENSE_INFO)) != (STATUS_UPDATE_INTENSE_INFO))
{
/* Cast, as compiler will assume calc is int */
g_board_status.led_intensity = (uint16_t) ((g_board_status.led_intensity + 1) % 5);
xResult = xEventGroupSetBitsFromISR(g_update_console_event, STATUS_UPDATE_INTENSE_INFO,
&xHigherPriorityTaskWoken);
/* Was the message posted successfully? */
if (pdFAIL != xResult)
{
/* If xHigherPriorityTaskWoken is now set to pdTRUE then a context
switch should be requested. The macro used is port specific and will
be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
the documentation page for the port being used. */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
}
/**********************************************************************************************************************
End of function button_irq10_callback
*********************************************************************************************************************/
/* SW 2 */
/**********************************************************************************************************************
* Function Name: button_irq9_callback
* Description : SW2 interrupt handler.
* Argument : p_args
* Return Value : None
*********************************************************************************************************************/
void button_irq9_callback(external_irq_callback_args_t *p_args)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
BaseType_t xResult = pdFAIL;
EventBits_t uxBits;
/* Void the unused args */
FSP_PARAMETER_NOT_USED(p_args);
uxBits = xEventGroupGetBitsFromISR (g_update_console_event);
if ((uxBits & (STATUS_UPDATE_FREQ_INFO)) != (STATUS_UPDATE_FREQ_INFO))
{
/* Cast, as compiler will assume calc is int */
g_board_status.led_frequency = (uint16_t) ((g_board_status.led_frequency + 1) % 5);
xResult = xEventGroupSetBitsFromISR(g_update_console_event, STATUS_UPDATE_FREQ_INFO, &xHigherPriorityTaskWoken);
/* Was the message posted successfully? */
if (pdFAIL != xResult)
{
/* If xHigherPriorityTaskWoken is now set to pdTRUE then a context
switch should be requested. The macro used is port specific and will
be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
the documentation page for the port being used. */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
}
/**********************************************************************************************************************
End of function button_irq9_callback
*********************************************************************************************************************/
uint32_t g_pwm_dcs[5] =
{ LED_INTENSITY_10, LED_INTENSITY_30, LED_INTENSITY_50, LED_INTENSITY_70, LED_INTENSITY_90 };
uint32_t g_pwm_rates[5] =
{ BLINK_FREQ_1HZ, BLINK_FREQ_3HZ, BLINK_FREQ_5HZ, BLINK_FREQ_7HZ, BLINK_FREQ_10HZ };
st_board_status_t g_board_status =
{ };
uint8_t g_pwm_dcs_data[] =
{ 10, 30, 50, 70, 90 };
uint8_t g_pwm_rates_data[] =
{ 1, 3, 5, 7, 10 };
功能展示:
基础任务:quad-spi flash和octo-spi flash配置及读写速度测试;DAC配置生成波形及性能测试
物料清单:EK-RA6M5
设计思路:
EK-RA6M5板载有QSPI和OSPI存储器,QSPI Flash对应型号为MX25L25645G,采用四线SPI模式操作;OSPI Flash对应型号为MX25LM51245GM,采用八线SPI模式操作。开发板上内部已连接好线路,无需额外硬件连接。
关于QSPI的引脚和外设配置如下
关于OSPI的引脚和外设配置如下
同时,官方针对EK-RA6M5提供的fsp开发包里面也有关于QSPI和OSPI的相关例程,可以进行学习。
RA6M5芯片具有一个DAC外设,两个通道,可以分别输出不同的电压值或者波形。关于DAC的引脚和外设配置如下
软件流程图:
代码片段:
block_size_actual = value;
if ((MENU_ENTER_RESPONSE_CRTL == c) && (0 != block_size_actual))
{
fsp_err_t fsp_err;
uint32_t ospi_read_result = 0;
uint32_t ospi_write_result = 0;
uint32_t qspi_read_result = 0;
uint32_t qspi_write_result = 0;
fsp_err = R_GPT_Open(g_memory_performance.p_ctrl, g_memory_performance.p_cfg);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
sprintf(s_print_buffer, "\r\n\r\nGenerated a text block of %2lu KB in SRAM\r\n", block_size_actual);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
/* ignoring -Wpointer-sign is OK for a constant string */
print_to_console((uint8_t *)
"\r\nWriting the text block to external Quad-SPI and Octo-SPI flash memories...\r\n");
uint32_t ospi_performance_write_result = 0;
uint32_t ospi_performance_read_result = 0;
uint32_t timer_frequency;
R_GPT_InfoGet(g_memory_performance.p_ctrl, &timer_info);
timer_frequency = timer_info.clock_frequency;
ospi_performance_test (block_size_actual, &ospi_performance_write_result, &ospi_performance_read_result);
/* Multiply uSec calcs by 100, to avoid losses due to small results in integer maths
* Scaled to fit within uint32_t */
ospi_write_result = ((100000000 / timer_frequency) * ospi_performance_write_result) / 100;
qspi_write_result = ((100000000 / timer_frequency) * qspi_write_test(block_size_actual)) / 100;
/* ignoring -Wpointer-sign is OK for a constant string */
print_to_console((uint8_t *)"Writing to flash completed\r\n");
/* ignoring -Wpointer-sign is OK for a constant string */
print_to_console((uint8_t *)"\r\nReading the text block from external Quad-SPI and Octo-SPI flash memories...\r\n");
ospi_read_result = ((100000000 / timer_frequency) * ospi_performance_read_result) / 100;
qspi_read_result = ((100000000 / timer_frequency) * qspi_read_test(block_size_actual)) / 100;
/* ignoring -Wpointer-sign is OK for a constant string */
print_to_console((uint8_t *)"Reading from flash completed\r\n");
R_GPT_Close(g_memory_performance.p_ctrl);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
SYSTEM_ERROR
}
/* ignoring -Wpointer-sign is OK for a constant string */
print_to_console((uint8_t *)"\r\n-------------------------------------------------");
/* ignoring -Wpointer-sign is OK for a constant string */
print_to_console((uint8_t *)"\r\nOperation/Flash Quad-SPI Octa-SPI");
/* ignoring -Wpointer-sign is OK for a constant string */
print_to_console((uint8_t *)"\r\n-------------------------------------------------");
sprintf(s_print_buffer, "\r\nWrite %6ld %6ld", qspi_write_result , ospi_write_result);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
sprintf(s_print_buffer, "\r\nRead %6ld %6ld", qspi_read_result , ospi_read_result);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
/* ignoring -Wpointer-sign is OK for a constant string */
print_to_console((uint8_t *)"\r\n-------------------------------------------------");
/* ignoring -Wpointer-sign is OK for a constant string */
print_to_console((uint8_t *)"\r\nNote: Times are in microseconds");
sprintf(s_print_buffer, MENU_RETURN_INFO);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
}
while ((CONNECTION_ABORT_CRTL != c))
{
if ((MENU_EXIT_CRTL == c) || (0x00 == c))
{
break;
}
c = input_from_console();
}
功能展示:
分别对QSPI和OSPI写入32KB数据并读出,测试结果如下
进阶任务:示例程序中新增命令打印信息
物料清单:EK-RA6M5
设计思路:
官方提供的出厂demo中已经预置了7条测试命令,包括USB、以太网等等,对于新增命令打印信息,找到官方实现的函数,依葫芦画瓢即可。
软件流程图:
代码片段:
/* Table of menu functions */
static st_menu_fn_tbl_t s_menu_items[] =
{
{"Kit Information" , kis_display_menu},
{"Web Server" , eth_emb_display_menu},
{"Network Name Lookup" , eth_www_display_menu},
{"Quad-SPI and Octo-SPI Speed Comparison" , ext_display_menu},
{"Cryptography and USB High speed (MSC)" , enc_display_menu},
{"DAC & DDS Test" , dds_display_menu},
{"Next Steps", ns_display_menu },
{"", NULL }
};
功能展示:
扩展任务:设计一个类似信号发生器功能的例程。可在示例程序上修改。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息
物料清单:EK-RA6M5
设计思路:
扩展任务将和进阶任务中新增的命令、基础任务中使用DAC生成波形结合,共同实现通过串口命令行发送相应指令,开发板输出对应的波形。具体配置前面任务已经介绍过,不再介绍。
软件流程图:
代码片段:
#include <math.h>
#define M_PI 3.14159265358979323846
uint16_t dac_val = 0;
uint8_t change_flag = 0;
/**********************************************************************************************************************
* Function Name: gpt_blue_callback
* Description : Callback function for driver g_gpt_blue.
* Argument : p_args
* Return Value : .
*********************************************************************************************************************/
void gpt_blue_callback(timer_callback_args_t * p_args)
{
/* Void the unused params */
FSP_PARAMETER_NOT_USED(p_args);
static double w = 0.0;
w += M_PI / 30;
if(w >= M_PI*2)
{
w = 0.0;
}
dac_val = (sin(w)+1) /2 * 4095;
change_flag = 1;
//R_DAC_Write(&g_dac0_ctrl, dac_val);
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];
}
}
}
test_fn dds_display_menu(void)
{
int8_t c = -1;
sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
sprintf (s_print_buffer, DDS_MODULE_NAME, g_selected_menu);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
sprintf (s_print_buffer, DDS_SUB_OPTIONS);
print_to_console((void*)s_print_buffer);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
// print_to_console((void*)s_print_buffer);
sprintf (s_print_buffer, MENU_RETURN_INFO);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
/* provide small delay so board_status should be up to date */
vTaskDelay (s_ticks_to_wait);
xEventGroupSetBits (g_update_console_event, STATUS_DISPLAY_MENU_KIS);
while (CONNECTION_ABORT_CRTL != c)
{
c = input_from_console ();
if ((MENU_EXIT_CRTL == c) || (CONNECTION_ABORT_CRTL == c))
{
break;
}
if(MENU_SIN_CRTL == c)
{
while(1)
{
R_DAC_Write(&g_dac0_ctrl, dac_val);
}
}
else if(MENU_SQUARE_CRTL == c)
{
}
else if(MENU_TRIANGULAR_CRTL == c)
{
}
}
xEventGroupClearBits (g_update_console_event, STATUS_DISPLAY_MENU_KIS);
return (0);
}
功能展示:
进入DAC&DDS Test测试界面后,输入键盘上的小写字母a、b、c将分别通过DAC输出正弦波、方波、三角波。
示波器观察到的波形
心得体会
非常感谢活动主办方提供这么棒的开发板供大家学习,个人感觉这次的难度是今年四期中最难的了,但是啃硬骨头啃完的感觉真爽,未来争取不让这块开发板吃灰,板载这么多外设,争取让它继续发光发热。
三、可编译下载的代码
|