Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
多线程
国民技术_N32G45x
【N32G457 】开发板试用笔记三
发布于 2022-02-24 10:02:00 浏览:871
订阅该版
一、项目需求 一直想在一些小产品上用单片机替代通用的控制器提高性价比,当时申请的这块开发板也是看中了这个板子采用RISC-V的架构,资源丰富,并且采用国产的软件。 在上一篇试用笔记中实现了多串口的应用,这一篇主要是参考《RT-THREAD 编程指南》学习多线程的应用,和大家一起分享一下测试心得。 二、RT-Tthread 概述 RT-Thread,全称是 Real Time-Thread,顾名思义,它是一个嵌入式实时多线程操作系统,基本属性之一是支持多任务,允许多个任务同时运行并不意味着处理器在同一时刻真地执行了多个任务。事实上,一个处理器核心在某一时刻只能运行一个任务,由于每次对一个任务的执行时间很短、任务与任务之间通过任务调度器进行非常快速地切换(调度器根据优先级决定此刻该执行的任务),给人造成多个任务在一个时刻同时运行的错觉。在 RT-Thread 系统中,任务通过线程实现的,RT-Thread 中的线程调度器也就是以上提到的任务调度器。 三、主要功能 对于设备的控制,主要是接收操作面板的控制开关、旋钮等的输入、驱动继电器触点动作、与其他的模块如显示屏等通讯。主要涉及GPIO、ADC、UART等。 希望能通过这些功能的实现对嵌入式实时多线程操作系统有所理解。 对于设备的控制比较相似,所以想做一个通用的模板工程,对于不同的设备做最小的修改方便今后的应用。所以就将输入(input.c)、输出(output.c)、串口1(ser_uart1.c)、串口2(ser_uart2.c)、串口3(ser_uart3.c)、串口4(ser_uart4.c)分成不同的c源码文件,并分别创建不同优先级别的线程。 ![tp1.png](https://oss-club.rt-thread.org/uploads/20220224/31cba7efbefafd40505bda479ebc95a3.png) 为了演示方便,还增加了RTC的功能,需要打开模拟RTC组件。 ![tp2.png](https://oss-club.rt-thread.org/uploads/20220224/c1e8c2f8cc83df764db19433c50b89b9.png) 四、代码分析 4.1主线程 在系统启动时,系统会创建 main 线程,它的入口函数为 main_thread_entry(),用户的应用入口函数 main() 就是从这里真正开始的,系统调度器启动后,main 线程就开始运行,过程如下图,用户可以在main() 函数里添加自己的应用程序初始化代码。 主线程调用过程: ![tp3.png](https://oss-club.rt-thread.org/uploads/20220224/7452fdd3f985042f4a2d36c4c5986e61.png) 我这里的主线程主要是更新显示输入、输出状态以及RTC的实时时间。为了直观一些,本来想沿用模板中的闪灯功能,但是发现,PB4上的蓝色灯一直发出微弱的光,用表测量始终是2.4V,不知道什么原因。 ``` /* defined the LED1 pin: PB4 */ #define LED1_PIN 90 extern int D_IN_1,D_IN_2,D_IN_3,D_IN_4; extern int D_OUT_1,D_OUT_2,D_OUT_3,D_OUT_4; extern char *str1; int main(void) { char * str; char buf = 0; uint32_t Speed = 100; /* set LED1 pin mode to output */ rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); while (1) { rt_pin_write(LED1_PIN, PIN_LOW); rt_thread_mdelay(Speed); rt_pin_write(LED1_PIN, PIN_HIGH); rt_thread_mdelay(Speed); rt_kprintf("main----\n"); rt_kprintf("D_IN_1:%d,D_IN_2:%d\n",D_IN_1,D_IN_2); rt_kprintf("D_OUT_1:%d,D_OUT_2:%d\n",D_OUT_1,D_OUT_2); rt_kprintf("RTC:%s\n",str1); } } ``` 4.2输入线程 输入用开发板上的按键来演示,KEY1,KEY2,KEY3分别连接PA4,PA5,PA6。测试中发现,KEY3按键无输入,后来发现是按键本身的问题,直接从PA6引脚输入是有效的。 ``` #include
#include
#include
#define THREAD_PRIORITY 25 #define THREAD_TIMESLICE 5 /* defined the KEY1 pin: PA4 PA5 PA6 */ #define KEY1_PIN 29 #define KEY2_PIN 30 #define KEY3_PIN 31 int D_IN_1,D_IN_2,D_IN_3,D_IN_4; ALIGN(RT_ALIGN_SIZE) static char thread1_stack[1024]; static struct rt_thread thread1; static void thread1_entry(void *parameter) { uint32_t Speed = 200; rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP); rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP); rt_pin_mode(KEY3_PIN, PIN_MODE_INPUT_PULLUP); while (1) { if (rt_pin_read(KEY1_PIN)==PIN_LOW ) { //rt_kprintf("INPUT_1:---on\n"); D_IN_1=1; } else { D_IN_1=0; } if (rt_pin_read(KEY2_PIN)==PIN_LOW) { //rt_kprintf("INPUT_2:---on\n"); D_IN_2=1; } else { D_IN_2=0; } if (rt_pin_read(KEY3_PIN)==PIN_LOW) rt_kprintf("k_KEY3--on\n"); } } int key_sample(void) { rt_thread_init(&thread1, "thread1", thread1_entry, RT_NULL, &thread1_stack[0], sizeof(thread1_stack), THREAD_PRIORITY, THREAD_TIMESLICE); rt_thread_startup(&thread1); return 0; } INIT_APP_EXPORT(key_sample); ``` 4.3输出线程 输出通过开发板上的红色和绿色led灯来演示。分别是PB5和PA8。 ``` #include
#include
#include
#define THREAD_PRIORITY 11 #define THREAD_TIMESLICE 5 /* defined the LED1 pin: PA8 */ #define LED1_PIN 67 /* defined the LED1 pin: PB5 */ #define LED2_PIN 91 /* defined the LED1 pin: PA4 */ #define LED3_PIN 90 int D_OUT_1,D_OUT_2,D_OUT_3,D_OUT_4; ALIGN(RT_ALIGN_SIZE) static char thread1_stack[1024]; static struct rt_thread thread1; /* 线 程 1 入 口 */ static void thread1_entry(void *parameter) { uint32_t Speed = 50; /* set LED1 pin mode to output */ rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); rt_pin_mode(LED3_PIN, PIN_MODE_OUTPUT); while (1) { D_OUT_1=PIN_LOW; D_OUT_2= PIN_HIGH; rt_pin_write(LED1_PIN, PIN_LOW); rt_pin_write(LED2_PIN, PIN_HIGH); rt_pin_write(LED3_PIN, PIN_HIGH); rt_thread_mdelay(Speed); D_OUT_1=PIN_HIGH; D_OUT_2= PIN_LOW; rt_pin_write(LED1_PIN, PIN_HIGH); rt_pin_write(LED2_PIN, PIN_LOW); rt_pin_write(LED3_PIN, PIN_LOW); rt_thread_mdelay(Speed*10); } } int out_sample(void) { rt_thread_init(&thread1, "thread1", thread1_entry, RT_NULL, &thread1_stack[0], sizeof(thread1_stack), THREAD_PRIORITY, THREAD_TIMESLICE); rt_thread_startup(&thread1); return 0; } INIT_APP_EXPORT(out_sample); ``` 4.4串口通讯 串口通信的线程是一样的,这里只把uart2的代码贴出来,其他的可以参考我的上一篇多串口的笔记。 ``` #include
struct serial_configure config2 = RT_SERIAL_CONFIG_DEFAULT; static struct rt_semaphore rx_sem; rt_device_t serial2; static rt_err_t uart_input(rt_device_t dev, rt_size_t size) { rt_sem_release(&rx_sem); return RT_EOK; } static void serial_thread_entry(void *parameter) { char ch; while (1) { while (rt_device_read(serial2, -1, &ch, 1) != 1) { rt_sem_take(&rx_sem, RT_WAITING_FOREVER); } ch = ch + 1; rt_device_write(serial2, 0, &ch, 1); // rt_kprintf("%c",ch); } } int thread_serial2(void) { rt_err_t ret = RT_EOK; char uart_name[RT_NAME_MAX]; char str[] = "hello RT-Thread_2!\r\n"; rt_strncpy(uart_name, SAMPLE_UART_NAME2, RT_NAME_MAX); serial2 = rt_device_find(uart_name); if (!serial2) { rt_kprintf("find %s failed!\n", uart_name); return RT_ERROR; } config2.baud_rate = BAUD_RATE_115200; config2.data_bits = DATA_BITS_8; config2.stop_bits = STOP_BITS_1; config2.bufsz = 64; config2.parity = PARITY_NONE; rt_device_control(serial2, RT_DEVICE_CTRL_CONFIG, &config2); rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); rt_device_open(serial2, RT_DEVICE_FLAG_INT_RX); rt_device_set_rx_indicate(serial2, uart_input); rt_device_write(serial2, 0, str, (sizeof(str) - 1)); rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 4, 10); if (thread != RT_NULL) { rt_thread_startup(thread); } else { ret = RT_ERROR; } return ret; } INIT_APP_EXPORT(thread_serial2); ``` 五、运行效果 5.1编译、下载后可以在终端看到下图的信息。在main函数中定时更新显示输入、输出、以及RTC的状态:按KEY1,KEY2按钮可以看到D_IN_1,D_IN_2的数据变化,D_OUT_1,D_OUT_2的数据也是变化的,同时可以看到红、绿两个LED的闪动。RTC显示实时时钟。 ![tp4.png](https://oss-club.rt-thread.org/uploads/20220224/0fb27d76aa79dc84bf7c11e15377236b.png) 5.2串口通讯 因uart1用于msh通讯,这里使用uart2,uart3,uart4实现与其他设备的通讯,通过串口调试助手,可以实现数据收发。从代码中可以看到,串口收到数据后会,将每个字符的ascii码值加一,再发送回去。 ![tp5.png](https://oss-club.rt-thread.org/uploads/20220224/1069a116e6f0ba5b94ba7bc798a86f7c.png) 六、总结 6.1 线程的优先级 在测试中发现,线程的优先级设置会影响程序的运行,但是具体的影响机理以及如何设置还没有学会,只是发现:输出线程的优先级低于输入线程时,输出线程就不运行了(红、绿led不闪烁),串口的优先级设置太低,串口就不能收发数据。 6.2 邮箱和信息队列 按照指南上的说明,邮箱以及信息队列,更适合于线程间的信息传递,后续还要继续学习。 6.3 ADC和PWM的功能 ADC和PWM是设备控制中常用的功能,但是,对照指南一直没有测试成功。 我不是专业学习嵌入式的,更侧重于应用,希望厂家能在完善产品上多下功夫,并提供更多的参考例程,让大家能通过更多的应用来测试产品。
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
xxxx
这家伙很懒,什么也没写!
文章
4
回答
2
被采纳
0
关注TA
发私信
相关文章
1
大家有没有遇到过多线程使用同一个串口发送数据,数据是交叉的
2
workqueue中调用rt_i2c_transfer互斥锁线程bug
3
micropython和本地线程的通信
4
大神们,我发现一个问题,RTT这个系统是不是没有查看其他线程状态的函数?
5
不知道该如何使用线程?
6
线程错误怎么判断哪里的问题(其他线程都ok)
7
rt_kprintf 多线程使用问题
8
线程优先级被中断影响
9
挂载在操作系统上的文件系统操作,需要用互斥锁防止多线程操作问题吗?
10
socket多线程操作转为单线程处理,断开连接检测代码展示
推荐文章
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总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
xiaorui
1
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部