本帖最后由 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的定义如下。
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,并对需要存储的数据进行管理。
#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;
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)
{
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);
}
}
while (1)
{
while (pdPASS != xSemaphoreTake(g_store_dds_semaphore, pdMS_TO_TICKS(500u)))
{
vTaskDelay(10);
}
dds_record_ins.type=DDS_RECORD_TYPE;
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中转发接受到的事件,用于后续的字符解析。
void usb_console_callback(usb_event_info_t* p_event_info, usb_hdl_t hdl, usb_onoff_t state)
{
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);
s_usb_event_pindex = (uint8_t)((s_usb_event_pindex + 1) % USB_QUEUE_SIZE);
}
else
{
}
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中存储的数据进行读写管理。
相关工程代码