diff --git "a/Fifth_Day_7_22/RTT \345\244\217\344\273\244\350\220\245\347\254\254\344\272\224\345\244\251\346\200\273\347\273\223.md" "b/Fifth_Day_7_22/RTT \345\244\217\344\273\244\350\220\245\347\254\254\344\272\224\345\244\251\346\200\273\347\273\223.md" new file mode 100644 index 0000000..f9537f0 --- /dev/null +++ "b/Fifth_Day_7_22/RTT \345\244\217\344\273\244\350\220\245\347\254\254\344\272\224\345\244\251\346\200\273\347\273\223.md" @@ -0,0 +1,298 @@ +# RTT 夏令营第五天总结 + +## WDT 看门狗 + +硬件看门狗(watchdog timer)是一个**定时器**,其定时输出**连接到电路的复位端**。在产品化的嵌入式系统中,为了使系统在**异常情况下能自动复位**,一般都需要引入看门狗。 + +当看门狗启动后,计数器开始自动计数,在计数器溢出前如果没有被复位,计数器溢出就会对 CPU 产生一个复位信号使系统重启(俗称 “被狗咬”)。系统正常运行时,需要在看门狗允许的时间间隔内对看门狗计数器清零(俗称“喂狗“),不让复位信号产生。如果系统不出问题,程序能够按时“喂狗”。一旦程序跑飞,没有“喂狗”,系统“被咬” 复位。 + +### 相关 API + +* 查找看门狗 + + ```c + /* 查找看门狗 */ + rt_device_t rt_device_find(const char* name); //看门狗设备名称 + ``` + + 应用程序可根据该函数接口获取设备句柄,进而可以操作看门狗设备。 + +* 初始化看门狗 + + ```c + /* 初始化看门狗 */ + rt_err_t rt_device_init(rt_device_t dev); //看门狗设备句柄 + ``` + + 使用看门狗设备前需要使用该函数接口进行看门狗设备的初始化。 + +* 控制看门狗 + + ```c + /* 控制看门狗 */ + rt_err_t rt_device_control(rt_device_t dev, //看门狗设备句柄 + rt_uint8_t cmd, //命令控制字 + void* arg); //控制的参数 + ``` + + 通过命令控制字,应用程序可以通过该函数接口对看门狗设备进行配置。 + + 命令控制字可取如下宏定义值: + + ```c + #define RT_DEVICE_CTRL_WDT_GET_TIMEOUT (1) /* 获取溢出时间 */ + #define RT_DEVICE_CTRL_WDT_SET_TIMEOUT (2) /* 设置溢出时间 */ + #define RT_DEVICE_CTRL_WDT_GET_TIMELEFT (3) /* 获取剩余时间 */ + #define RT_DEVICE_CTRL_WDT_KEEPALIVE (4) /* 喂狗 */ + #define RT_DEVICE_CTRL_WDT_START (5) /* 启动看门狗 */ + #define RT_DEVICE_CTRL_WDT_STOP (6) /* 停止看门狗 */ + ``` + +* 关闭看门狗 + + ```c + /* 关闭看门狗 */ + rt_err_t rt_device_close(rt_device_t dev); //看门狗设备句柄 + ``` + + 当应用程序完成看门狗操作后,可以关闭看门狗设备。 + + 值得注意的是:关闭设备接口和打开设备接口需配对使用,打开一次设备对应要关闭一次设备,这样设备才会被完全关闭,否则设备仍处于未关闭状态。 + +### 代码实现: + +```c +#define WDT_DEVICE_NAME "wdt" /* 看门狗设备名称 */ +static rt_device_t wdg_dev; /* 看门狗设备句柄 */ + +void LED_Toggle(void *args) +{ + rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); + if (rt_pin_read(LED0_PIN) == 0) + { + rt_pin_write(LED0_PIN, 1); + rt_kprintf("LED OFF\r\n"); + } + else + { + rt_pin_write(LED0_PIN, 0); + rt_kprintf("LED ON\r\n"); + } +} + +MSH_CMD_EXPORT(LED_Toggle, use to toggle led_pin); + +void LED_Blink(void *args) +{ + rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); + while(1) + { + rt_pin_write(LED0_PIN, 0); + rt_thread_mdelay(500); + rt_pin_write(LED0_PIN, 1); + rt_thread_mdelay(500); + } +} + +void Key_scan(void *args) +{ + rt_err_t ret = RT_EOK; + rt_uint32_t timeout = 1; /* 溢出时间,单位:秒 */ + + rt_pin_mode(13,PIN_MODE_INPUT_PULLUP); + + wdg_dev = rt_device_find(WDT_DEVICE_NAME); + if (!wdg_dev) + { + rt_kprintf("find %s failed!\n", WDT_DEVICE_NAME); + return RT_ERROR; + } + /* 设置看门狗溢出时间 */ + ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout); + if (ret != RT_EOK) + { + rt_kprintf("set %s timeout failed!\n", WDT_DEVICE_NAME); + return RT_ERROR; + } + /* 启动看门狗 */ + ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL); + if (ret != RT_EOK) + { + rt_kprintf("start %s failed!\n", WDT_DEVICE_NAME); + return -RT_ERROR; + } + + while(1) + { + if(rt_pin_read(13) == 0) + { + rt_thread_mdelay(10); + if(rt_pin_read(13) == 0) + { + rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);//喂狗 + rt_kprintf("feed the dog!\n "); + } + } + rt_thread_mdelay(10); + } +} + +void test_thread_init(void) +{ + rt_thread_t err; + err = rt_thread_create("blink", LED_Blink, RT_NULL, 1024, 16, 100); + if(err != RT_NULL) + { + rt_thread_startup(err); + } + else + { + rt_kprintf("blink thread create fault\r\n"); + } + + rt_thread_t tid; + tid = rt_thread_create("key", Key_scan, RT_NULL, 1024, 15, 100); + if(tid != RT_NULL) + { + rt_thread_startup(tid); + } + else + { + rt_kprintf("key thread create fault\r\n"); + } +} +MSH_CMD_EXPORT(test_thread_init,test thread init); +``` + +程序思路及效果: + +```mermaid +graph LR +A[按下按键] +B[LED闪烁线程运行] +C[系统重启] +D[超时未按下按键] +E[将按键设置为'喂狗'入口] +E --> A --> B +E --> D --> C +``` + +![WDT](.\assets\image-20220723141521310.png) + +## RTC 使用 + +RTC (Real-Time Clock)实时时钟可以提供精确的实时时间,它可以用于产生年、月、日、时、分、秒等信息。目前实时时钟芯片大多采用精度较高的晶体振荡器作为时钟源。 + +### 相关 API + +* 设置日期 + + ```c + /* 设置日期 */ + rt_err_t set_date(rt_uint32_t year, //待设置生效的年份 + rt_uint32_t month, //待设置生效的月份 + rt_uint32_t day) //待设置生效的日 + ``` + +* 设置时间 + + ```c + /* 设置时间 */ + rt_err_t set_time(rt_uint32_t hour, //待设置生效的时 + rt_uint32_t minute, //待设置生效的分 + rt_uint32_t second) //待设置生效的秒 + ``` + +* 获取当前时间 + + ```c + /* 获取当前时间 */ + time_t time(time_t *t) //时间数据指针 + ``` + +### 代码实现 + +```c +static int rtc_test(void *args) +{ + rt_err_t ret = RT_EOK; + time_t now; + + /* 设置日期 */ + ret = set_date(2022, 7, 23); + if (ret != RT_EOK) + { + rt_kprintf("set RTC date failed\n"); + return ret; + } + + /* 设置时间 */ + ret = set_time(00, 00, 00); + if (ret != RT_EOK) + { + rt_kprintf("set RTC time failed\n"); + return ret; + } + while(1) + { + /* 延时3秒 */ + rt_thread_mdelay(3000); + + /* 获取时间 */ + now = time(RT_NULL); + rt_kprintf("%s\n", ctime(&now)); + } + + return ret; +} +/* 导出到 msh 命令列表中 */ +MSH_CMD_EXPORT(rtc_test, rtc sample); +``` + +![rtc](.\assets\image-20220723153256640.png) + +## 串口驱动对接 + +串口设备驱动框架可浅析为三个层:设备管理层、设备驱动框架层、设备驱动层。 + +以 CH32V307 为例: + +* 设备管理层(**device.c**):**rt_device_find、rt_device_open、rt_device_read等**。 + +* 设备驱动框架层(**serial.c**):**rt_serial_init、rt_serial_control、rt_serial_open等**。 + +* 设备驱动层(**drv_usart.c**):**ch32_configure、ch32_control、ch32_putc、ch32_getc等**。 + + + +设备管理层的作用为: + +* **通过设备管理接口获得正确的设备驱动,然后通过这个设备驱动与底层硬件设备进行交互**。 + +* **为用户提供标准操作接口**。 + + + +设备驱动框架层的作用为: + +* **向下为设备驱动层提供:需要被实现的操作硬件的基本函数、设备注册函数、中断处理调用函数和需要被实现的结构体等**。 + +* **在内部调用操作底层硬件的基本函数实现更为复杂的驱动功能**。 + +* **向上提供标准的驱动接口**。 + + + +设备驱动层的作用为: + +* **提供硬件层的驱动,如引脚初始化等**。 + + + +**由此可见:RT-Thread 利用设备驱动框架层将驱动层的底层代码封装成一个又一个标准的驱动接口,再由设备管理层进行进一步的封装,形成应用所用到的标准设备接口函数,从而实现应用层和底层驱动的解耦合,再利用设备驱动框架层提供的接口实现硬件层的控制,实现驱动对接**。 + +## 更换rt_kprintf的输出终端 + +![uart](.\assets\image-20220723165709477.png) + +可在 RT-Thread Setting 中更改 FinSH 控制台 和 rt_kprintf 的默认输出串口。 \ No newline at end of file diff --git a/Fifth_Day_7_22/assets/image-20220723141521310.png b/Fifth_Day_7_22/assets/image-20220723141521310.png new file mode 100644 index 0000000..befd87d Binary files /dev/null and b/Fifth_Day_7_22/assets/image-20220723141521310.png differ diff --git a/Fifth_Day_7_22/assets/image-20220723153256640.png b/Fifth_Day_7_22/assets/image-20220723153256640.png new file mode 100644 index 0000000..e6f82aa Binary files /dev/null and b/Fifth_Day_7_22/assets/image-20220723153256640.png differ diff --git a/Fifth_Day_7_22/assets/image-20220723165709477.png b/Fifth_Day_7_22/assets/image-20220723165709477.png new file mode 100644 index 0000000..e1f3741 Binary files /dev/null and b/Fifth_Day_7_22/assets/image-20220723165709477.png differ diff --git "a/Forth_Day_7_21/RTT \345\244\217\344\273\244\350\220\245\347\254\254\345\233\233\345\244\251\346\200\273\347\273\223.md" "b/Forth_Day_7_21/RTT \345\244\217\344\273\244\350\220\245\347\254\254\345\233\233\345\244\251\346\200\273\347\273\223.md" new file mode 100644 index 0000000..76306dc --- /dev/null +++ "b/Forth_Day_7_21/RTT \345\244\217\344\273\244\350\220\245\347\254\254\345\233\233\345\244\251\346\200\273\347\273\223.md" @@ -0,0 +1,142 @@ +# RTT 夏令营第四天总结 + +## 点亮一个 LED 灯 + +### 流程 + +```mermaid +graph LR +定义引脚号 --> 设置引脚模式 --> 设置引脚电平 +``` + +### 代码 + +```c +void LED_Toggle(void *args) +{ + rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);//配置引脚为输出模式 + if (rt_pin_read(LED0_PIN) == 0)//读取引脚状态并判断 + { + rt_pin_write(LED0_PIN, 1);//引脚置高 + rt_kprintf("LED OFF\r\n"); + } + else + { + rt_pin_write(LED0_PIN, 0);//引脚置低 + rt_kprintf("LED ON\r\n"); + } +} + +MSH_CMD_EXPORT(LED_Toggle, use to toggle led_pin);//导出命令到 MSH 列表 +``` + +代码逻辑:在 Finsh 控制台输入 LED_Toggle 命令,之后读取 LED 电平状态,进行电平翻转,实现 LED 亮灭控制。 + +### 效果 + +![LED_OFF](.\img\image-20220722194803367.png) + +![LED_ON](.\img\image-20220722194817324.png) + +## 使用 AHT10 读取温湿度 + +### 流程 + +```mermaid +graph LR +在RT-Thread_Settings中使能模拟IIC和AHT10软件包 --> 配置AHT10传感器 --> 初始化AHT10 --> 读取温湿度数据 +``` + +### 代码 + +```c +#define AHT10_I2C_BUS "i2c1" +struct aht10_device *temp_humi_dev;//aht10设备句柄 +float hum, tem; +int rt_hw_aht10_port(void)//AHT10 传感器配置 +{ + struct rt_sensor_config cfg; + cfg.intf.dev_name = AHT10_I2C_BUS;//通信设备名称 + cfg.intf.user_data = (void *)AHT10_I2C_ADDR;//传感器私有数据 (在此为iic通信地址) + rt_hw_aht10_init("aht10", &cfg); + return RT_EOK; +} + +static void aht10_thread_entry(void *args)//温湿度读取线程入口函数 +{ + aht10_device_t dev; + + rt_hw_aht10_port();//配置 AHT10 + dev = aht10_init(AHT10_I2C_BUS);//初始化 AHT10 + + if(dev == RT_NULL) + { + rt_kprintf("The sensor init fail!\r\n"); + return; + } + else + { + rt_kprintf("The sensor init ok\r\n"); + } + + while(1) + { + hum = aht10_read_humidity(dev);//读取湿度 + rt_kprintf("humidity : %d.%d \r\n",(int)hum,(int)(hum * 10) % 10); + tem = aht10_read_temperature(dev);//读取温度 + rt_kprintf("temperature: %d.%d \r\n",(int)tem,(int)(tem * 10) % 10); + + rt_thread_mdelay(5000); + } +} + +static int app_aht10_init(void)//创建温湿度读取线程 +{ + rt_err_t err; + rt_thread_t aht10_thread; + aht10_thread = rt_thread_create("aht10", + aht10_thread_entry, + RT_NULL, + 1024, + 25, + 10); + + if(aht10_thread != RT_NULL) + { + err = rt_thread_startup(aht10_thread); + } + else + { + rt_kprintf("aht10 thread create fault \r\n"); + } + + if(err != RT_EOK) + { + rt_kprintf("aht10 thread start fault \r\n"); + } + + return RT_EOK; +} +INIT_APP_EXPORT(app_aht10_init);//应用程序初始化 +``` + +### 效果 + +![AHT10](.\img\image-20220722202503135.png) + +## 总结 + +### RT-Thread I/O 设备框架 + +RT-Thread 提供了一套 I/O 设备模型框架,它位于硬件和应用程序之间,共分成三层,从上到下分别是 I/O 设备管理层、设备驱动框架层、设备驱动层。 + +![设备框架](.\img\image-20220722202837657.png) + +应用程序通过 I/O 设备管理接口获得正确的设备驱动,然后通过这个设备驱动与底层 I/O 硬件设备进行数据(或控制)交互。 + +I/O 设备管理层实现了对设备驱动程序的封装。应用程序通过 I/O 设备层提供的标准接口访问底层设备。 + +设备驱动框架层是对同类硬件设备驱动的抽象,将不同厂家的同类硬件设备驱动中相同的部分抽取出来,将不同部分留出接口,由驱动程序实现。 + +**这种方式使得设备的硬件操作相关的代码能够独立于应用程序而存在,双方只需关注各自的功能实现,从而降低了代码的耦合性、复杂性,提高了系统的可靠性。** + diff --git a/Forth_Day_7_21/img/image-20220722194803367.png b/Forth_Day_7_21/img/image-20220722194803367.png new file mode 100644 index 0000000..db288dc Binary files /dev/null and b/Forth_Day_7_21/img/image-20220722194803367.png differ diff --git a/Forth_Day_7_21/img/image-20220722194817324.png b/Forth_Day_7_21/img/image-20220722194817324.png new file mode 100644 index 0000000..49af5c7 Binary files /dev/null and b/Forth_Day_7_21/img/image-20220722194817324.png differ diff --git a/Forth_Day_7_21/img/image-20220722202503135.png b/Forth_Day_7_21/img/image-20220722202503135.png new file mode 100644 index 0000000..5648dcb Binary files /dev/null and b/Forth_Day_7_21/img/image-20220722202503135.png differ diff --git a/Forth_Day_7_21/img/image-20220722202837657.png b/Forth_Day_7_21/img/image-20220722202837657.png new file mode 100644 index 0000000..7022eb3 Binary files /dev/null and b/Forth_Day_7_21/img/image-20220722202837657.png differ diff --git "a/Sixth_Day_7_23/RTT \345\244\217\344\273\244\350\220\245\347\254\254\345\205\255\345\244\251\346\200\273\347\273\223.md" "b/Sixth_Day_7_23/RTT \345\244\217\344\273\244\350\220\245\347\254\254\345\205\255\345\244\251\346\200\273\347\273\223.md" new file mode 100644 index 0000000..47a7e53 --- /dev/null +++ "b/Sixth_Day_7_23/RTT \345\244\217\344\273\244\350\220\245\347\254\254\345\205\255\345\244\251\346\200\273\347\273\223.md" @@ -0,0 +1,40 @@ +# RTT 夏令营第六天总结 + +## RT-Thread 的网络框架结构 + +![网络框架](.\assets\image-20220723202409729.png) + +RT-Thread 网络框架最顶层是**网络应用层**,提供一套**标准 BSD Socket APl** ,.如 socket、connect 等函数,用于系统中大部分网络开发应用。 + +往下第二部分为**SAL套接字抽象层**,通过它 RT-Thread 系统能够适配下层不同的网络协议栈,并**提供给上层统一的网络编程接口**,方便不同协议栈的接入。套接字抽象层为上层应甬层提供接口有: accept、connect、send、recv 等。 + +第三部分为 **netdev 网卡层**,主要作用是解决多网卡情况设备网络连接和网络管理相关问题,通过 netdev 网卡层,用户可以统一管理客个网卡信息和网络连接状态,并且可以使用统一的网卡调试命令接口。 + +第四部分为**协议栈层**,该层包括几种常用的 **TCP/IP 协议栈**,例如嵌入式开发中常用的轻型 TCP/IP协议栈lwlP 以及 RT-Thread 自主研发的 AT Socket 网络功能实现等。这些协议栈或网络功能实现直接和硬件接触,完成数据从网络层到传输层的转化。 + +RT-Thread 的网络应用层提供的接口主要以标准 **BSD Socket API 为主**,这样能确保程序可以在 PC 上编写、调试,然后再移植到 RT-Thread 操作系统上。 + +## AT 指令 + +AT 命令(AT Commands)最早是由发明拨号调制解调器(MODEM)的贺氏公司(Hayes)为了控制 MODEM 而发明的控制协议。后来随着网络带宽的升级,速度很低的拨号 MODEM 基本退出一般使用市场,但是 AT 命令保留下来。当时主要的移动电话生产厂家共同为 GSM 研制了一整套 AT 命令,用于控制手机的 GSM 模块。AT 命令在此基础上演化并加入 GSM 07.05 标准以及后来的 GSM 07.07 标准,实现比较健全的标准化。 + +在随后的 GPRS 控制、3G 模块等方面,均采用的 AT 命令来控制,AT 命令逐渐在产品开发中成为实际的标准。如今,AT 命令也广泛的应用于嵌入式开发领域,AT 命令作为主芯片和通讯模块的协议接口,硬件接口一般为串口,这样主控设备可以通过简单的命令和硬件设计完成多种操作。 + +**AT 命令集是一种应用于 AT 服务器(AT Server)与 AT 客户端(AT Client)间的设备连接与数据通信的方式**。 + +```mermaid +graph LR +A[AT 客户端] +B[AT 服务器] +A --AT 命令请求--> B +B --响应数据+结果--> A +B --URC 数据--> A +``` + +AT 组件是基于 RT-Thread 系统的 **AT Server** 和 **AT Client** 的实现,组件完成 AT 命令的发送、命令格式及参数判断、命令的响应、响应数据的接收、响应数据的解析、URC 数据处理等整个 AT 命令数据交互流程。 + +通过 AT 组件,设备可以作为 AT Client 使用串口连接其他设备发送并接收解析数据,可以作为 AT Server 让其他设备甚至电脑端连接完成发送数据的响应,也可以在本地 shell 启动 CLI 模式使设备同时支持 AT Server 和 AT Client 功能,该模式多用于设备开发调试。 + +## 作业截图 + +![work](.\assets\image-20220723203830992.png) \ No newline at end of file diff --git a/Sixth_Day_7_23/assets/image-20220723202409729.png b/Sixth_Day_7_23/assets/image-20220723202409729.png new file mode 100644 index 0000000..99f4e02 Binary files /dev/null and b/Sixth_Day_7_23/assets/image-20220723202409729.png differ diff --git a/Sixth_Day_7_23/assets/image-20220723203830992.png b/Sixth_Day_7_23/assets/image-20220723203830992.png new file mode 100644 index 0000000..2fcc847 Binary files /dev/null and b/Sixth_Day_7_23/assets/image-20220723203830992.png differ