diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY1/005beffd8ad538b6d556eac6d0d57824.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY1/005beffd8ad538b6d556eac6d0d57824.png" new file mode 100644 index 0000000000000000000000000000000000000000..8dba7b6f834e73925908c133d49817c7150450fa Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY1/005beffd8ad538b6d556eac6d0d57824.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY1/339f83b1dc74a17e5b1e603e0807a07f.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY1/339f83b1dc74a17e5b1e603e0807a07f.png" new file mode 100644 index 0000000000000000000000000000000000000000..1591102c20e6f43aba28fc46b0a19763239ab384 Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY1/339f83b1dc74a17e5b1e603e0807a07f.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY1/8fd5630c000490bcd948ffc95fcb3bd8.png" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY1/8fd5630c000490bcd948ffc95fcb3bd8.png" new file mode 100644 index 0000000000000000000000000000000000000000..1f8aa9b586b7e916bda2ee2141ef8dcb1ed44b7d Binary files /dev/null and "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY1/8fd5630c000490bcd948ffc95fcb3bd8.png" differ diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY2/main.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY2/main.c" new file mode 100644 index 0000000000000000000000000000000000000000..439a2e41c1aea504b9bc064110eccd26a2c14d4d --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY2/main.c" @@ -0,0 +1,111 @@ +#include +#include +#include + +/* 线程控制块 */ +static rt_thread_t thread1 = RT_NULL; +static rt_thread_t thread2 = RT_NULL; +static rt_thread_t thread3 = RT_NULL; + +/* 线程1入口函数 */ +static void thread1_entry(void *parameter) +{ + while (1) + { + /* 打印线程1运行信息 */ + rt_kprintf("[Thread1] Running...\n"); + + /* 挂起线程1秒(1000ms) */ + rt_thread_delay(RT_TICK_PER_SECOND); + } +} + +/* 线程2入口函数 */ +static void thread2_entry(void *parameter) +{ + while (1) + { + /* 打印线程2运行信息 */ + rt_kprintf("[Thread2] Running...\n"); + + /* 挂起线程0.5秒(500ms) */ + rt_thread_delay(RT_TICK_PER_SECOND / 2); + } +} + +/* 线程3入口函数 */ +static void thread3_entry(void *parameter) +{ + while (1) + { + /* 打印线程3运行信息 */ + rt_kprintf("[Thread3] Running...\n"); + + /* 挂起线程0.5秒(500ms) */ + rt_thread_delay(RT_TICK_PER_SECOND / 2); + } +} + +/* 应用程序入口 */ +int main(void) +{ + /* 创建线程1 */ + thread1 = rt_thread_create( + "thread1", /* 线程名称 */ + thread1_entry, /* 线程入口函数 */ + RT_NULL, /* 线程参数 */ + 1024, /* 线程栈大小 */ + 4, /* 线程优先级 */ + 10 /* 线程时间片 */ + ); + + /* 创建线程2 */ + thread2 = rt_thread_create( + "thread2", + thread2_entry, + RT_NULL, + 1024, + 5, /* 优先级比线程1低 */ + 10 + ); + + /* 创建线程3 */ + thread3 = rt_thread_create( + "thread3", + thread3_entry, + RT_NULL, + 1024, + 5, /* 与线程2同级 */ + 10 + ); + + /* 检查线程创建是否成功 */ + if (thread1 != RT_NULL) + { + rt_thread_startup(thread1); + } + else + { + rt_kprintf("Thread1 create failed!\n"); + } + + if (thread2 != RT_NULL) + { + rt_thread_startup(thread2); + } + else + { + rt_kprintf("Thread2 create failed!\n"); + } + + if (thread3 != RT_NULL) + { + rt_thread_startup(thread3); + } + else + { + rt_kprintf("Thread3 create failed!\n"); + } + + return RT_EOK; +} \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/event.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/event.c" new file mode 100644 index 0000000000000000000000000000000000000000..e246be240104d2b99185be8fc0de1ca721261d62 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/event.c" @@ -0,0 +1,73 @@ +#include "board.h" +#include "rtthread.h" + +/* 线程控制块 */ +static rt_thread_t thread1 = RT_NULL; +static rt_thread_t thread2 = RT_NULL; +static rt_event_t test_event = RT_NULL; + +/* 事件定义 */ +#define KEY1_EVENT (0x01 << 0) /* 按键1事件 */ +#define KEY2_EVENT (0x01 << 1) /* 按键2事件 */ + +/* 线程1入口函数 - 事件接收 */ +static void thread1_entry(void* parm) +{ + rt_uint32_t recv; + while (1) { + /* 等待任一事件发生 */ + rt_event_recv(test_event, + KEY1_EVENT | KEY2_EVENT, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, + &recv); + + /* 事件处理 */ + if (recv & KEY1_EVENT) LED1_TOGGLE; + if (recv & KEY2_EVENT) LED1_TOGGLE; + } +} + +/* 线程2入口函数 - 事件发送 */ +static void thread2_entry(void* parm) +{ + while (1) { + /* 检测按键1 */ + if (Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PIN) == KEY_ON) { + rt_kprintf("[Event] Key1 pressed\n"); + rt_event_send(test_event, KEY1_EVENT); + } + + /* 检测按键2 */ + if (Key_Scan(KEY2_GPIO_PORT, KEY2_GPIO_PIN) == KEY_ON) { + rt_kprintf("[Event] Key2 pressed\n"); + rt_event_send(test_event, KEY2_EVENT); + } + + rt_thread_delay(20); /* 延时20ms消抖 */ + } +} + +/* 主函数 */ +int main(void) +{ + /* 创建事件集 */ + test_event = rt_event_create("test_event", RT_IPC_FLAG_PRIO); + if (!test_event) { + rt_kprintf("[Error] Event creation failed\n"); + return -RT_ERROR; + } + + /* 创建线程1 - 优先级3 */ + thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, + 1024, 3, 20); + /* 创建线程2 - 优先级2 */ + thread2 = rt_thread_create("thread2", thread2_entry, RT_NULL, + 1024, 2, 20); + + /* 启动线程 */ + if (thread1) rt_thread_startup(thread1); + if (thread2) rt_thread_startup(thread2); + + return RT_EOK; +} \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/mailbox.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/mailbox.c" new file mode 100644 index 0000000000000000000000000000000000000000..614f34de857913d83d80aaf3d53a2e7ffc93a96e --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/mailbox.c" @@ -0,0 +1,62 @@ +#include "board.h" +#include "rtthread.h" + +/* 线程控制块 */ +static rt_thread_t thread1 = RT_NULL; +static rt_thread_t thread2 = RT_NULL; +static rt_mailbox_t test_mb = RT_NULL; + +/* 测试消息 */ +static const char test_str[] = "Mailbox test message\n"; + +/* 线程1入口函数 - 接收消息 */ +static void thread1_entry(void* parm) +{ + char* r_str; + while (1) { + /* 接收消息(超时1秒) */ + if (rt_mb_recv(test_mb, (rt_ubase_t*)&r_str, 1000) == RT_EOK) { + rt_kprintf("[Mailbox] Received: %s", r_str); + } + rt_thread_delay(200); /* 延时200ms */ + } +} + +/* 线程2入口函数 - 发送消息 */ +static void thread2_entry(void* parm) +{ + while (1) { + /* 检测按键1 */ + if (Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PIN) == KEY_ON) { + /* 发送消息 */ + if (rt_mb_send(test_mb, (rt_ubase_t)test_str) != RT_EOK) { + rt_kprintf("[Error] Mail send failed\n"); + } + rt_thread_delay(20); /* 延时20ms消抖 */ + } + } +} + +/* 主函数 */ +int main(void) +{ + /* 创建邮箱(容量10) */ + test_mb = rt_mb_create("test_mb", 10, RT_IPC_FLAG_FIFO); + if (!test_mb) { + rt_kprintf("[Error] Mailbox creation failed\n"); + return -RT_ERROR; + } + + /* 创建线程1 - 优先级5 */ + thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, + 1024, 5, 20); + /* 创建线程2 - 优先级3 */ + thread2 = rt_thread_create("thread2", thread2_entry, RT_NULL, + 1024, 3, 20); + + /* 启动线程 */ + if (thread1) rt_thread_startup(thread1); + if (thread2) rt_thread_startup(thread2); + + return RT_EOK; +} \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/mutex.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/mutex.c" new file mode 100644 index 0000000000000000000000000000000000000000..c282f3d65a7145d9bf883e989696797ec2bba3f2 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/mutex.c" @@ -0,0 +1,70 @@ +#include "board.h" +#include "rtthread.h" + +/* 线程控制块 */ +static rt_thread_t thread1 = RT_NULL; +static rt_thread_t thread2 = RT_NULL; +static rt_mutex_t test_mutex = RT_NULL; + +/* 共享数据 */ +static int shared_data[2] = {0, 0}; + +/* 线程1入口函数 - 数据检查 */ +static void thread1_entry(void* parm) +{ + while (1) { + /* 获取互斥锁 */ + rt_mutex_take(test_mutex, RT_WAITING_FOREVER); + + /* 检查数据一致性 */ + if (shared_data[0] == shared_data[1]) { + rt_kprintf("[Mutex] Data consistent: %d\n", shared_data[0]); + } + + /* 释放互斥锁 */ + rt_mutex_release(test_mutex); + rt_thread_delay(1000); /* 延时1秒 */ + } +} + +/* 线程2入口函数 - 数据更新 */ +static void thread2_entry(void* parm) +{ + while (1) { + /* 获取互斥锁 */ + rt_mutex_take(test_mutex, RT_WAITING_FOREVER); + + /* 更新共享数据 */ + shared_data[0]++; + rt_thread_delay(100); /* 模拟处理延时 */ + shared_data[1]++; + + /* 释放互斥锁 */ + rt_mutex_release(test_mutex); + rt_thread_yield(); /* 主动让出CPU */ + } +} + +/* 主函数 */ +int main(void) +{ + /* 创建互斥锁 */ + test_mutex = rt_mutex_create("test_mutex", RT_IPC_FLAG_FIFO); + if (!test_mutex) { + rt_kprintf("[Error] Mutex creation failed\n"); + return -RT_ERROR; + } + + /* 创建线程1 - 优先级3 */ + thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, + 1024, 3, 20); + /* 创建线程2 - 优先级5 */ + thread2 = rt_thread_create("thread2", thread2_entry, RT_NULL, + 1024, 5, 20); + + /* 启动线程 */ + if (thread1) rt_thread_startup(thread1); + if (thread2) rt_thread_startup(thread2); + + return RT_EOK; +} \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/queue.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/queue.c" new file mode 100644 index 0000000000000000000000000000000000000000..0a4f7dbe5cf1ed8d7f6392a115d6628d81841206 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/queue.c" @@ -0,0 +1,61 @@ +#include "board.h" +#include "rtthread.h" + +/* 线程控制块 */ +static rt_thread_t thread1 = RT_NULL; +static rt_thread_t thread2 = RT_NULL; +static rt_mq_t test_mq = RT_NULL; + +/* 线程1入口函数 - 接收消息 */ +static void thread1_entry(void* parm) +{ + uint32_t rev_data; + while (1) { + /* 接收消息(超时100ms) */ + if (rt_mq_recv(test_mq, &rev_data, sizeof(rev_data), 100) == RT_EOK) { + rt_kprintf("[Queue] Received data: %d\n", rev_data); + } + rt_thread_delay(200); /* 延时200ms */ + } +} + +/* 线程2入口函数 - 发送消息 */ +static void thread2_entry(void* parm) +{ + static uint32_t send_data = 1; + while (1) { + /* 检测按键1 */ + if (Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PIN) == KEY_ON) { + /* 发送消息 */ + if (rt_mq_send(test_mq, &send_data, sizeof(send_data)) != RT_EOK) { + rt_kprintf("[Error] Queue send failed\n"); + } + send_data++; /* 数据递增 */ + rt_thread_delay(20); /* 延时20ms消抖 */ + } + } +} + +/* 主函数 */ +int main(void) +{ + /* 创建消息队列(消息大小4字节,容量20) */ + test_mq = rt_mq_create("test_mq", sizeof(uint32_t), 20, RT_IPC_FLAG_FIFO); + if (!test_mq) { + rt_kprintf("[Error] Message queue creation failed\n"); + return -RT_ERROR; + } + + /* 创建线程1 - 优先级5 */ + thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, + 1024, 5, 20); + /* 创建线程2 - 优先级3 */ + thread2 = rt_thread_create("thread2", thread2_entry, RT_NULL, + 1024, 3, 20); + + /* 启动线程 */ + if (thread1) rt_thread_startup(thread1); + if (thread2) rt_thread_startup(thread2); + + return RT_EOK; +} \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/sem.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/sem.c" new file mode 100644 index 0000000000000000000000000000000000000000..142366554cb473d7cda5dc94c5d1de1ef9434ceb --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/sem.c" @@ -0,0 +1,70 @@ +#include "board.h" +#include "rtthread.h" + +/* 线程控制块 */ +static rt_thread_t thread1 = RT_NULL; +static rt_thread_t thread2 = RT_NULL; +static rt_sem_t test_sem = RT_NULL; + +/* 共享数据 */ +static int shared_data[2] = {0, 0}; + +/* 线程1入口函数 - 数据检查 */ +static void thread1_entry(void* parm) +{ + while (1) { + /* 获取信号量 */ + rt_sem_take(test_sem, RT_WAITING_FOREVER); + + /* 检查数据一致性 */ + if (shared_data[0] == shared_data[1]) { + rt_kprintf("[Semaphore] Data consistent: %d\n", shared_data[0]); + } + + /* 释放信号量 */ + rt_sem_release(test_sem); + rt_thread_delay(1000); /* 延时1秒 */ + } +} + +/* 线程2入口函数 - 数据更新 */ +static void thread2_entry(void* parm) +{ + while (1) { + /* 获取信号量 */ + rt_sem_take(test_sem, RT_WAITING_FOREVER); + + /* 更新共享数据 */ + shared_data[0]++; + rt_thread_delay(100); /* 模拟处理延时 */ + shared_data[1]++; + + /* 释放信号量 */ + rt_sem_release(test_sem); + rt_thread_yield(); /* 主动让出CPU */ + } +} + +/* 主函数 */ +int main(void) +{ + /* 创建信号量(初始值1) */ + test_sem = rt_sem_create("test_sem", 1, RT_IPC_FLAG_FIFO); + if (!test_sem) { + rt_kprintf("[Error] Semaphore creation failed\n"); + return -RT_ERROR; + } + + /* 创建线程1 - 优先级5 */ + thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, + 1024, 5, 20); + /* 创建线程2 - 优先级3 */ + thread2 = rt_thread_create("thread2", thread2_entry, RT_NULL, + 1024, 3, 20); + + /* 启动线程 */ + if (thread1) rt_thread_startup(thread1); + if (thread2) rt_thread_startup(thread2); + + return RT_EOK; +} \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/signal.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/signal.c" new file mode 100644 index 0000000000000000000000000000000000000000..1079dd9b56ba0af3eb9fd50d506607cc1e6f940f --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY3/signal.c" @@ -0,0 +1,65 @@ +#include "board.h" +#include "rtthread.h" + +/* 自定义信号定义 */ +#define SIG_USER 0x01 + +/* 线程控制块 */ +static rt_thread_t thread1 = RT_NULL; +static rt_thread_t thread2 = RT_NULL; + +/* 信号处理函数 */ +static void signal_handler(int sig) +{ + rt_kprintf("[Signal] Thread %s received signal %d\n", + rt_thread_self()->name, sig); +} + +/* 线程1入口函数 */ +static void thread1_entry(void* parm) +{ + /* 安装信号处理函数 */ + rt_signal_install(SIG_USER, signal_handler); + /* 取消信号屏蔽 */ + rt_signal_unmask(SIG_USER); + + while (1) { + rt_thread_delay(500); /* 延时500ms */ + } +} + +/* 线程2入口函数 */ +static void thread2_entry(void* parm) +{ + /* 忽略SIG_USER信号 */ + rt_signal_install(SIG_USER, SIG_IGN); + rt_signal_unmask(SIG_USER); + + while (1) { + rt_thread_delay(500); /* 延时500ms */ + } +} + +/* 主函数 */ +int main(void) +{ + /* 创建线程1 - 优先级4 */ + thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, + 1024, 4, 20); + /* 创建线程2 - 优先级6 */ + thread2 = rt_thread_create("thread2", thread2_entry, RT_NULL, + 1024, 6, 20); + + /* 启动线程 */ + if (thread1) rt_thread_startup(thread1); + if (thread2) rt_thread_startup(thread2); + + /* 主线程延时100ms确保子线程运行 */ + rt_thread_delay(100); + + /* 向线程发送信号 */ + rt_thread_kill(thread1, SIG_USER); + rt_thread_kill(thread2, SIG_USER); + + return RT_EOK; +} \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY4/drv_vir.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY4/drv_vir.c" new file mode 100644 index 0000000000000000000000000000000000000000..d567b265ed7950de14610f980cbbdee612014d58 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY4/drv_vir.c" @@ -0,0 +1,84 @@ +#include + +#if defined(RT_USING_VIR) + +/* 虚拟设备结构体 */ +struct vir_test { + struct rt_device parent; /* 继承自RT-Thread设备基类 */ + rt_uint32_t val; /* 设备数值 */ + const char* info; /* 设备信息字符串 */ +} vir; + +/** + * @brief 打印设备信息 + * @param device 设备对象指针 + * @param str 要打印的信息字符串 + */ +void printfinfo(struct rt_device *device, rt_uint8_t *str) +{ + RT_ASSERT(device != RT_NULL); + rt_kprintf("[VIR] Device Info: %s\n", str); +} + +/** + * @brief 设置设备数值 + * @param device 设备对象指针 + * @param val 要设置的数值 + */ +void vir_set_val(struct rt_device *device, rt_uint32_t val) +{ + RT_ASSERT(device != RT_NULL); + vir.val = val; + rt_kprintf("[VIR] Set value: %d\n", val); +} + +/** + * @brief 获取设备数值 + * @param device 设备对象指针 + * @param val 用于存储数值的指针 + */ +void vir_get_val(struct rt_device *device, rt_uint32_t *val) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(val != RT_NULL); + *val = vir.val; + rt_kprintf("[VIR] Get value: %d\n", *val); +} + +/* 虚拟设备操作函数表 */ +static struct rt_vir_ops ops = { + .print_info = printfinfo, + .set_value = vir_set_val, + .get_value = vir_get_val, +}; + +/** + * @brief 虚拟设备初始化函数 + * @return 初始化状态 + * @retval RT_EOK 初始化成功 + * @retval -RT_ERROR 初始化失败 + */ +static int vir_init(void) +{ + /* 初始化默认值 */ + vir.val = 0; + vir.info = "Virtual_Device"; + + /* 注册虚拟设备 */ + if (rt_hw_vir_register(&vir.parent, + "vir", + &ops, + (void*)vir.info) != RT_EOK) + { + rt_kprintf("[VIR] Error: Device register failed\n"); + return -RT_ERROR; + } + + rt_kprintf("[VIR] Device initialized successfully\n"); + return RT_EOK; +} + +/* 使用组件自动初始化机制 */ +INIT_APP_EXPORT(vir_init); + +#endif /* RT_USING_VIR */ \ No newline at end of file diff --git "a/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY5/test.c" "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY5/test.c" new file mode 100644 index 0000000000000000000000000000000000000000..d1210474f38cbd115d768e835697a135df972f24 --- /dev/null +++ "b/2025/\347\254\2545\347\273\204(CanMV-K230)/\347\224\260\345\256\230\346\224\277/\344\275\234\344\270\232/DAY5/test.c" @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include +#include +#include "mqttclient.h" +#include + +/* MQTT 连接配置 */ +#define MQTT_BROKER "jiejie01.top" // MQTT服务器地址 +#define MQTT_PORT_NUM "1883" // MQTT端口号 +#define CLIENT_ID_STR "rtthread1209" // 客户端ID +#define MQTT_USER "rt-thread" // 用户名 +#define MQTT_PASS "rt-thread" // 密码 +#define SUBSCRIBE_TOPIC "rtt-sub" // 订阅主题 +#define PUBLISH_TOPIC "rtt-pub" // 发布主题 +#define DEVICE_NAME "xiaoming" // 设备名称 +#define STUDY_MESSAGE "Keep up the good work!" // 默认消息 + +static mqtt_client_t *mqtt_handle = NULL; // MQTT客户端句柄 + +/** + * @brief 构建JSON格式的MQTT消息负载 + * @return 生成的JSON字符串指针,使用后需要调用cJSON_free释放 + */ +static char* build_json_payload(void) +{ + cJSON *root_obj = cJSON_CreateObject(); + if (!root_obj) { + rt_kprintf("[MQTT][ERROR] Failed to create JSON object\n"); + return NULL; + } + + // 添加字段到JSON对象 + cJSON_AddStringToObject(root_obj, "study", STUDY_MESSAGE); + cJSON_AddStringToObject(root_obj, "name", DEVICE_NAME); + + // 生成无格式化的JSON字符串 + char *json_str = cJSON_PrintUnformatted(root_obj); + if (!json_str) { + rt_kprintf("[MQTT][ERROR] Failed to generate JSON string\n"); + } + + cJSON_Delete(root_obj); // 释放JSON对象 + return json_str; +} + +/** + * @brief MQTT消息接收回调函数 + * @param client MQTT客户端指针 + * @param msg 接收到的消息数据 + */ +static void incoming_msg_handler(void* client, message_data_t* msg) +{ + RT_ASSERT(msg != NULL); + RT_ASSERT(msg->message != NULL); + + char *msg_content = (char*)msg->message->payload; + rt_kprintf("\n[MQTT] << Received Message >>\n"); + rt_kprintf("Topic: %.*s\n", msg->topic_len, msg->topic_name); + rt_kprintf("Data: %.*s\n", msg->message->payloadlen, msg_content); + + /* 解析JSON数据 */ + cJSON *json_root = cJSON_Parse(msg_content); + if (!json_root) { + rt_kprintf("[MQTT][ERROR] Invalid JSON format\n"); + return; + } + + /* 提取JSON字段 */ + cJSON *study_field = cJSON_GetObjectItem(json_root, "study"); + cJSON *name_field = cJSON_GetObjectItem(json_root, "name"); + + /* 验证字段有效性 */ + if (cJSON_IsString(name_field) && cJSON_IsString(study_field)) { + /* 检查消息内容是否匹配 */ + if (strcmp(name_field->valuestring, DEVICE_NAME) == 0 && + strcmp(study_field->valuestring, STUDY_MESSAGE) == 0) { + + /* 准备响应消息 */ + mqtt_message_t response; + memset(&response, 0, sizeof(response)); + response.qos = QOS0; + response.payload = "辛苦了,下周的比赛加油!"; + + /* 发布响应消息 */ + if (mqtt_publish(mqtt_handle, PUBLISH_TOPIC, &response) == RT_EOK) { + rt_kprintf("[MQTT] Response sent: %s\n", (char*)response.payload); + } else { + rt_kprintf("[MQTT][ERROR] Failed to send response\n"); + } + } + } else { + rt_kprintf("[MQTT][ERROR] Missing required JSON fields\n"); + } + + cJSON_Delete(json_root); // 释放JSON对象 + rt_kprintf("[MQTT] << End of Message >>\n\n"); +} + +/** + * @brief 初始化MQTT客户端连接 + * @return 初始化结果 + * @retval RT_EOK 初始化成功 + * @retval -RT_ERROR 初始化失败 + */ +static int setup_mqtt_client(void) +{ + /* 获取MQTT客户端实例 */ + mqtt_handle = mqtt_lease(); + if (!mqtt_handle) { + rt_kprintf("[MQTT][ERROR] Failed to allocate MQTT client\n"); + return -RT_ERROR; + } + + /* 配置连接参数 */ + mqtt_set_host(mqtt_handle, MQTT_BROKER); + mqtt_set_port(mqtt_handle, MQTT_PORT_NUM); + mqtt_set_client_id(mqtt_handle, CLIENT_ID_STR); + mqtt_set_user_name(mqtt_handle, MQTT_USER); + mqtt_set_password(mqtt_handle, MQTT_PASS); + mqtt_set_clean_session(mqtt_handle, 1); // 启用clean session + + /* 建立MQTT连接 */ + if (mqtt_connect(mqtt_handle) != RT_EOK) { + rt_kprintf("[MQTT][ERROR] Connection to broker failed\n"); + mqtt_release(mqtt_handle); + return -RT_ERROR; + } + + /* 订阅主题 */ + if (mqtt_subscribe(mqtt_handle, SUBSCRIBE_TOPIC, QOS0, incoming_msg_handler) != RT_EOK) { + rt_kprintf("[MQTT][ERROR] Failed to subscribe topic\n"); + mqtt_disconnect(mqtt_handle); + mqtt_release(mqtt_handle); + return -RT_ERROR; + } + + rt_kprintf("[MQTT] Client initialized successfully\n"); + rt_kprintf("[MQTT] Broker: %s:%s\n", MQTT_BROKER, MQTT_PORT_NUM); + rt_kprintf("[MQTT] Client ID: %s\n", CLIENT_ID_STR); + rt_kprintf("[MQTT] Subscribed: %s\n", SUBSCRIBE_TOPIC); + rt_kprintf("[MQTT] Publishing: %s\n", PUBLISH_TOPIC); + + return RT_EOK; +} + +/** + * @brief 发布测试消息 + */ +static void publish_test_message(void) +{ + char *json_data = build_json_payload(); + if (!json_data) { + rt_kprintf("[MQTT][ERROR] Failed to build JSON payload\n"); + return; + } + + mqtt_message_t test_msg; + memset(&test_msg, 0, sizeof(test_msg)); + test_msg.qos = QOS0; + test_msg.payload = json_data; + + rt_kprintf("[MQTT] Sending: %s\n", json_data); + if (mqtt_publish(mqtt_handle, SUBSCRIBE_TOPIC, &test_msg) != RT_EOK) { + rt_kprintf("[MQTT][ERROR] Failed to publish message\n"); + } + + cJSON_free(json_data); // 释放JSON字符串内存 +} + +/** + * @brief MQTT主线程函数 + * @param param 线程参数(未使用) + */ +static void mqtt_main_thread(void *param) +{ + RT_ASSERT(param == RT_NULL); // 参数未使用 + + rt_thread_mdelay(5000); // 等待5秒确保网络就绪 + + /* 初始化MQTT客户端 */ + if (setup_mqtt_client() != RT_EOK) { + rt_kprintf("[MQTT][ERROR] Initialization failed, thread exiting\n"); + return; + } + + /* 发送初始测试消息 */ + publish_test_message(); + + /* 主循环保持连接 */ + while (1) { + rt_thread_mdelay(1000); // 1秒间隔 + } +} + +/** + * @brief 启动MQTT演示程序 + * @return 启动结果 + * @retval RT_EOK 启动成功 + * @retval -RT_ERROR 启动失败 + */ +int launch_mqtt_demo(void) +{ + rt_thread_t tid = rt_thread_create( + "mqtt_task", // 线程名称 + mqtt_main_thread, // 线程入口函数 + RT_NULL, // 参数 + 4096, // 栈大小 + 15, // 优先级 + 10 // 时间片 + ); + + if (tid != RT_NULL) { + rt_thread_startup(tid); + rt_kprintf("[MQTT] Demo thread started successfully\n"); + return RT_EOK; + } + + rt_kprintf("[MQTT][ERROR] Failed to create demo thread\n"); + return -RT_ERROR; +} + +/* 导出到MSH命令 */ +MSH_CMD_EXPORT(launch_mqtt_demo, Start MQTT client with JSON message processing); \ No newline at end of file