Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
【24嵌入式设计大赛】基于HPM5300-EVK的简易嵌入式辅助调试装置
发布于 2024-09-15 17:14:28 浏览:315
订阅该版
[tocm] # 基于HPM5300-EVK的简易调试助手 ## 简介 本项目使用HPM5300-EVK作为载体,使用RT-Thread作为系统框架。实现了ADC采集,串口转发以及读取、控制GPIO电平。配合上位机,可以方便的观测到模拟/多个数字波形的连续变化。 ## 主要程序 ### 主函数 在RT-Thread框架下,得益于HPM5300-EVK的大部分所需的外设已经被初始化完成,main函数中仅执行了三部分动作。一是开启板载LED闪烁,提示系统运行状态;二是配置串口,此处主要是与串口相关的中断函数,以及开启数据解析线程;三是初始化ADC。代码如下。 ```c int main(void) { app_init_led_pins(); static uint32_t led_thread_arg = 0; rt_thread_t led_thread = rt_thread_create("led_th", thread_entry, &led_thread_arg, 1024, 1, 10); rt_thread_startup(led_thread); uart_sz_init(); adc_sz_init(); return 0; } ``` ### 串口数据处理 串口数据处理部分由三个函数联合完成,系统内数据解析函数会连续运行,其首先会调用数据接收函数。数据接收函数会持续阻塞,等待串口中断函数发送信号接收数据。串口中断函数代码如下。 ```c rt_err_t uart0_input(rt_device_t dev, rt_size_t size) { /* 串 口 接 收 到 数 据 后 产 生 中 断, 调 用 此 回 调 函 数, 然 后 发 送 接 收 信 号 量 */ rt_sem_release(&rx0_sem); return RT_EOK; } ``` 接收到信号后,数据接收函数会读取数据并返回,代码如下。 ```c char serial0_thread_entry(void ) { char ch; /* 从 串 口 读 取 一 个 字 节 的 数 据, 没 有 读 取 到 则 等 待 接 收 信 号 量 */ while (rt_device_read(rt0, -1, &ch, 1) != 1) { /* 阻 塞 等 待 接 收 信 号 量, 等 到 信 号 量 后 再 次 读 取 数 据 */ rt_sem_control(&rx0_sem, RT_IPC_CMD_RESET, RT_NULL); rt_sem_take(&rx0_sem, RT_WAITING_FOREVER); } return ch; } ``` 此时数据解析线程会将该数据存入数据数组,检查该数据是否是设定的结束符。本项目使用'\n'作为数据结束的标志。如果该数据不是结束符,则返回重新调用数据接收函数。如果是,则为相应位置添加终止符,并解析数据数组中的函数,代码如下。 ```c void data0_parsing(void) { char ch; char data0[ONE_DATA_MAXLEN]; static char i = 0; uint8_t pin_state=0; while (1) { ch = serial0_thread_entry(); data0[i++] = ch; if(ch == DATA_CMD_END) { data0[i++] = '\0'; ch='\0'; /* 中间的数据解析部分此处省略 */ i = 0; memset(data0, 0, sizeof(data0)); continue; } i = (i >= ONE_DATA_MAXLEN-1) ? ONE_DATA_MAXLEN-1 : i; } } ``` ### 数据解析 认为串口数据已经完整取出,其形式符合自定义通信协议,即标头+数据+结束符。此处最为符合switch-case函数形式,根据多种标头执行多种动作。但是由于switch-case不能匹配字符串,因此,此处使用if-else语句。代码如下。 ```c if((data0[0]=='r')&&(data0[1]=='t')&&(data0[2]=='2')) { rt_device_write(rt, 0, data0+3, i-4); } else if ((data0[0]=='a')&&(data0[1]=='d')&&(data0[2]=='c')) { if ((data0[3]=='1')&&(state_adc==0)) { thread_adc_get = rt_thread_create("adc_get", (void (*)(void *parameter))adc_get, RT_NULL,1024, 25, 10); rt_thread_startup(thread_adc_get); thread_adc = rt_thread_create("adc_print", (void (*)(void *parameter))adc_print, RT_NULL,1024, 25, 10); rt_thread_startup(thread_adc); state_adc=1; } else if ((data0[3]=='0')&&(state_adc==1)) { rt_thread_delete(thread_adc_get); rt_thread_delete(thread_adc); state_adc=0; } } else if ((data0[0]=='i')&&(data0[1]=='o')&&(data0[3]=='o')) { if (data0[2]=='a') { gpio_set_pin_output(HPM_GPIO0, GPIO_DI_GPIOA, (data0[4]-'0')*10+(data0[5]-'0')); gpio_write_pin(HPM_GPIO0, GPIO_DI_GPIOA, (data0[4]-'0')*10+(data0[5]-'0'), data0[6]-'0'); } else if (data0[2]=='b') { gpio_set_pin_output(HPM_GPIO0, GPIO_DI_GPIOB, (data0[4]-'0')*10+(data0[5]-'0')); gpio_write_pin(HPM_GPIO0, GPIO_DI_GPIOB, (data0[4]-'0')*10+(data0[5]-'0'), data0[6]-'0'); } ; } else if ((data0[0]=='i')&&(data0[1]=='o')&&(data0[3]=='i')) { if (data0[2]=='a') { gpio_set_pin_input(HPM_GPIO0, GPIO_DI_GPIOA, (data0[4]-'0')*10+(data0[5]-'0')); pin_state=gpio_read_pin(HPM_GPIO0, GPIO_DI_GPIOA, (data0[4]-'0')*10+(data0[5]-'0')); rt_kprintf("{pin:%d}\n", pin_state); } else if (data0[2]=='b') { gpio_set_pin_input(HPM_GPIO0, GPIO_DI_GPIOB, (data0[4]-'0')*10+(data0[5]-'0')); pin_state=gpio_read_pin(HPM_GPIO0, GPIO_DI_GPIOB, (data0[4]-'0')*10+(data0[5]-'0')); rt_kprintf("{pin:%d}\n", pin_state); } ; } ``` ### 串口转发 串口转发原理同调试串口的收发原理及流程一样,只不过没有数据解析,无条件转发到调试转口而已。 ### ADC采集 ADC采集部分使用RTT内置的设备驱动函数,由三个函数共同组合而成,一是ADC初始化,在main函数中执行;二是数据采集线程;三是数据发送线程。二和三由串口数据解析函数控制开始和停止。由于各种原因,ADC的采样率被控制在约900Hz左右,有效分辨率约为14bit。ADC相关代码如下。 ```c void adc_sz_init(void) { adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME); rt_adc_enable(adc_dev, ADC_DEV_CHANNEL); } void adc_get(void) { while(1) { value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL); rt_thread_mdelay(1); } } void adc_print(void) { while(1) { rt_kprintf("{o:%d}\n", value); rt_thread_mdelay(1); } } ``` 使用ADC采集20Hz,峰峰值20mv,频率20Hz的正弦波,效果如下。数据为原始数据,未计算单位为V的真实数据。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240915/05f2467d52c4333cfc84354a2cf3abe6.png.webp) ### GPIO读取及电平控制 此处为方便编程,减少RTT内置GPIO驱动程序中find device等函数,使用HPM自带的SDK函数,内置于数据解析部分,根据串口收到的数据直接控制IO。代码如下。 ```c if ((data0[0]=='i')&&(data0[1]=='o')&&(data0[3]=='o')) { if (data0[2]=='a') { gpio_set_pin_output(HPM_GPIO0, GPIO_DI_GPIOA, (data0[4]-'0')*10+(data0[5]-'0')); gpio_write_pin(HPM_GPIO0, GPIO_DI_GPIOA, (data0[4]-'0')*10+(data0[5]-'0'), data0[6]-'0'); } else if (data0[2]=='b') { gpio_set_pin_output(HPM_GPIO0, GPIO_DI_GPIOB, (data0[4]-'0')*10+(data0[5]-'0')); gpio_write_pin(HPM_GPIO0, GPIO_DI_GPIOB, (data0[4]-'0')*10+(data0[5]-'0'), data0[6]-'0'); } ; } else if ((data0[0]=='i')&&(data0[1]=='o')&&(data0[3]=='i')) { if (data0[2]=='a') { gpio_set_pin_input(HPM_GPIO0, GPIO_DI_GPIOA, (data0[4]-'0')*10+(data0[5]-'0')); pin_state=gpio_read_pin(HPM_GPIO0, GPIO_DI_GPIOA, (data0[4]-'0')*10+(data0[5]-'0')); rt_kprintf("{pin:%d}\n", pin_state); } else if (data0[2]=='b') { gpio_set_pin_input(HPM_GPIO0, GPIO_DI_GPIOB, (data0[4]-'0')*10+(data0[5]-'0')); pin_state=gpio_read_pin(HPM_GPIO0, GPIO_DI_GPIOB, (data0[4]-'0')*10+(data0[5]-'0')); rt_kprintf("{pin:%d}\n", pin_state); } ; } ```
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
obrulviser
这家伙很懒,什么也没写!
文章
1
回答
0
被采纳
0
关注TA
发私信
相关文章
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
ART-Pi
FinSH
USB
文件系统
DMA
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
cubemx
PWM
flash
packages_软件包
freemodbus
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
出出啊
1516
个答案
342
次被采纳
小小李sunny
1440
个答案
289
次被采纳
张世争
794
个答案
171
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
4
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部