RT-Thread 基础项目实战(F407ZGT6+DHT11+OLED)

1. 基于STM32芯片创建HelloWorld工程

下载安装RT-Thread Studio、新建项目、构建项目、烧录程序、输出HelloWorld、点亮LED灯等均在上一篇博客中已经写过,这里根据参考资料1的步骤写一下正点原子探索者STM32F407ZGT6怎么修改系统时钟为外部高速晶振HSE。

上一篇博客:https://blog.csdn.net/m0_53488817/article/details/118458086

关于改用外部晶振时钟,参考博客中是这么写的:
在这里,根据正点原子探索者F407进行一些修正:

1.1 SystemClock_config函数

首先,该函数的位置并不在board.c中,在新建项目的时候可以看到如下的提示:

在左侧项目结构中选择drivers文件夹,其中有个drv_clk.c文件,双击打开如下:

这样我们就找到了SystemClock_config函数,对其进行如下修改:

重新构建项目后,烧录程序,可以看到开发板上的红色led灯每0.5秒循环亮灭。

备注:
①不要只顾着修改等号右边,等号左侧的变量名也要注意修改
②PLLM这一项,参考资料中写的为1,我将其改为1之后烧录程序led灯是没有反应的,打开Terminal,可以看到串口也没有打印数据,PLLM的定义如下:

输入1并没有超过该范围,首先怀疑了是不是板子上的纽扣电子是不是没电了导致外部晶振没有正常起振,用电压表进行了测量发现有电、之后将PLLM改回8,重新烧录程序后led灯正常闪烁,初步判断,可能是设置的频率不对。
③代码中PLLN以及后面的设置与参考资料中的代码均不同,经查证,target_freq_mhz在系统初始化后会被赋值为168,刚好是探索者的系统时钟频率,168Mhz,因此,后面的代码部分不需要进行修改。

2. 获取温湿度传感器数据

参考资料中用的是(I2C设备驱动+SHT3x软件包)

博主手头上只有DHT11,一样可以测试温湿度数据,只不过DHT11采取单总线的方式依赖时序进行通信,并非I2C,不过一样可以做。

2.1 添加DHT11软件包

双击RT-Thread Settings,在软件包中心点立即添加,在弹出来的界面中输入DHT11,如下图所示:
双击即可查看概要,打开后发现并没有特别重要的内容,即使没有查看概要,直接点了添加,ctrl+s保存之后,也可以在左侧工程目录中找到README.md文件,打开后发现与概要说明内容一样。

2.2 “个性化”修改

双击打开上图中的dht11_sample.c文件,可以在该文件中找到很明显的两行代码,如下图所示:

DHT11为单总线通信,三个引脚,一个VCC,一个GND,中间那个就是数据传输用的,因此,最关心的也是这个引脚,我用的板子是正点原子探索者STM32F407ZGT6,查阅电路原理图后发现,开发板上预留了DHT11/DS18B20的快捷接口,但因为口太小,DHT11无法直接插进去,因此引了三根线,如下图所示:绿色为VCC,橙色为数据线,蓝色为GND,查阅电路原理图得知数据线接的是PG9,因此将代码中的PIN脚改为PG9。

重新构建后发现报错,原因为找不到头文件“drv_gpio.h”,在左侧工程目录中找到drv_gpio.c文件,怎么会没有对应的头文件呢?打开后发现,确实没有,他用的是"board.h"、“drv_common.h”,在DHT11的源代码中进行修改,如下图:

2.3 运行结果

重新构建后可以烧录程序,烧录程序后打开控制台,可以看到DHT11初始化成功,温湿度数据正常输出,但是此时的温湿度数据并不是在main函数中输出的,因为我根本没改main函数,效果如下图:

3. 获取NTP时间

3.1 添加ESP8266设备驱动

3.1.1 使能libc组件

使用at_device软件包之前,需要先开启libc组件:

3.1.2 添加at_device软件包

项目中使用的是ESP8266设备,其基于AT框架的驱动示例代码在at_device软件包中提供,在RT-Thread软件包中心搜索at_device后添加,之后在at_device右键选择详细配置进入软件包配置页面,勾选乐鑫 ESP8266,修改如下:

注意:
①Wifi SSID和Wifi 密码设置为真实的可以连上网的wifi。
②修改AT 客户端设备名称
按照上述要求,需要在board.h文件中进行设备uart2的开启(这里为什么用uart2请往后看)

上述step1 翻译过来就是:根据串口号定义宏定义打开串口相关的内容,比如:……这里的示例代码中居然写成了UATR1,下面写的却是UART1,迷惑行为。

step2为定义对应的引脚,step3和step4是和DMA相关的,项目中没用到,所以不需要定义。

备注:参考资料2中命名为lpuart1,他也成功了,我一开始用的esp8266,报错,后来换成他用的lpuart1也报错,最后换成实例代码中的uart1,发现程序中uart1已经被用来与控制台交互了,因此换成了uart2,好了。

修改如下图所示,在原来UART1的基础上直接“照抄”了一下:

重新构建项目后运行,控制台输出下列字样:

备注:

①如果出现了提示RT_SERIAL_RB_BUFSZ的值不够用的警告,可以参考资料2中进行缓冲区大小的调整,我是直接调整后运行的,所以没有出现这种警告。

②在调试过程中,我出现了另一个错误(警告),如下图所示:

大概意思就是我的esp8266固件版本低了,需要升级才能支持AT+CIPDNS_CUR?指令,于是我把我的esp8266模块拆下来单独测试,它长这样:
用USB-TTL模块对应引脚相连,用AT指令测试了一下,内置的固件版本是1.5.4的,去安信可官网查了一下,最新的居然也是1.5.4的不过后面多了个1.5.4.1,是的,就多一个“.1”,本来不想整的,结果RT-Thread Studio报红出来让我更新,不更新看着难受,结果我就去了,结果……我就被坑了。

记不得在哪里下载到了v3.8.8的flash_download_tool固件烧写工具,然后下载了安信可官网1.5.4.1的最新固件包,然后打开烧写软件:

这个图上你们所看到的每一个勾选项我都查网上的资料或者通过AT指令查过了,不管怎么试,最后点击START都会卡在等待上电的界面,固件就是刷不进去,网上有人说8266模组要把IO_0接地,要在出现等待上电界面的时候将原本悬空的RST先接地再松开,让8266重启,要注意共地问题等,我全都试了,全都……不行。这个问题只能先放着,已经浪费了我很长时间了。

3.1.3 测试网络

1.ifconfig //使用该命令查看当前网卡配置
2.ping www.baidu.com //使用该命令测试外网是否可以ping通

ifconfig指令:

ping指令:

这里从测试结果中可以看到,www.baidu.com就是不行,用百度的ip地址就可以了,暂时是无法理解的,一度让我以为网络ping失败了,又让我联想到之前报的那个固件版本错误,可能是那个问题导致的。

3.2 添加NTP对时功能

3.2.1 添加netutils工具软件包

同样,在RT-Thread Setting软件中心搜索并添加“netutils”包,右键选择详细配置,如下图:
这里的网址并不需要修改。

3.2.2 开启软件模拟RTC

因为NTP工具在获取到网络时间后,需要同步到本地RTC,所以需要开启本地模拟RTC功能:

点亮之后,ctrl+s即自动导入工程。

3.2.3 测试NTP工作是否正常

使用NTP工具包自带的命令进行测试:

ntp_sync //获取NTP时间并同步到本地

可以从终端观察到有时间日期等信息返回。

3.2.4 编写上电自动同步时间代码

① 检测当前网络是否正常

在本项目中,需要上电连接网络之后,自动获取NTP时间同步到本地,供后续显示使用,这段代码放在main函数中执行。

netdev(network interface device),即网络接口设备,又称网卡。每一个用于网络连接的设备都可以注册成网卡,为了适配更多的种类的网卡,避免系统中对单一网卡的依赖,RT-Thread 系统提供了 netdev 组件用于网卡管理和控制。

使用 netdev 网卡功能相关操作函数,需要包含如下头文件:

#include <arpa/inet.h>         /* 包含 ip_addr_t 等地址相关的头文件 */
#include <netdev.h>            /* 包含全部的 netdev 相关操作接口函数 */

首先获取要操作的网卡对象,每个网卡中有唯一的网卡名称,可以通过网卡名称获取网卡对象:

struct netdev *netdev_get_by_name(const char *name);

netdev 网卡提供了一个宏定义用于判断网卡是否为 internet_up 状态,如下:(注意此行代码并不需要添加到main函数中,只是参考资料2的博主讲解(秀)给你看的)

#define netdev_is_internet_up(netdev)

通过这个宏定义即可判断当前网络状态是否正常,在main函数中添加如下代码:

//获取网卡对象
struct netdev* net = netdev_get_by_name("esp0");
//阻塞判断当前网络是否正常连接
while(netdev_is_internet_up(net) != 1)
{rt_thread_mdelay(200);
}
//提示当前网络已就绪
rt_kprintf("network is ok!\n");

构建项目后下载,效果如下:

输出了一个network is ok!

② 网络正常后,获取NTP时间并同步到本地RTC

要使用NTP工具提供的API,首先包含头文件:

#include <ntp.h>

接着调用获取时间并同步的API,原型如下:(这行代码也不需要写到main函数里)

time_t ntp_sync_to_rtc(void);

在上面的代码之后继续添加NTP对时的代码:

//NTP自动对时
time_t cur_time;
cur_time = ntp_sync_to_rtc(NULL);
if (cur_time)
{rt_kprintf("Cur Time: %s", ctime((const time_t*) &cur_time));
}
else
{rt_kprintf("NTP sync fail.\n");
}

构建项目后下载,输出了两次当前时间,效果如下:

备注:

①感觉间隔挺长的,运行起来有点慢,等待后期学习再对此类问题优化。

4. OLED显示时钟和温湿度

4.1 开启C++组件支持

使用U8G2软件包需要C++组件支持,在RT-Thread项目设置中开启C++组件,如图:

开启之后保存设置,软件会自动添加C++组件到工程中,编译没有问题:

4.2 添加u8g2软件包并测试

c++组件测试编译没有问题之后,打开工程设置,搜索u8g2,添加软件包,添加之后右键详细设置,如下图,需使能基本示例:

ctrl+s保存配置,等系统重构工程之后双击打开在左侧工程目录中packages—>u8g2—>examples—>ssd1306……的.cpp文件,如下图:

需要根据开发板及个人喜好,修改i2c通信的端口:

这里我打开就是这样,所以oled屏直接SCL接PB6,SDA接PB7,但是由于之前我温湿度传感器没有用SHA3X,导致项目中还没添加i2c组件,在设置中点选i2c,如下图:

参考资料3中具体介绍了i2c怎么配置,其中还涉及到一个添加软件 I2C 源码的过程,我当时直接ctrl+s保存等待系统自动重构之后才想起来,在重新添加的时候发现工程中已经有了源码的两个文件,不过我还是选择了重新覆盖。

构建项目后下载,运行后可以看到oled被点亮(但是说实话特别糊,只能隐隐约约看到RT Thread字样)

4.3 编写OLED显示线程

在application分组下创建一个用户文件oled_display.cpp文件,存放本项目中的OLED显示代码。

参考资料4中有配合了SHA3X的源代码,能不能成功运行我不知道,由于我是采用的DHT11传感器,因此,对该代码进行了部分修改:

#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <U8g2lib.h>
#include <stdio.h>#include <drv_soft_i2c.h>
#include "board.h"
#include "drv_common.h"
#include "sensor.h"
//extern "C"
//{
//#include <sht3x.h>
//}
//extern "C"
//{
//sht3x_device_t sht3x_init(const char *i2c_bus_name, rt_uint8_t sht3x_addr);
//rt_err_t sht3x_read_singleshot(sht3x_device_t dev);
//}#define OLED_I2C_PIN_SCL                    22  // PB6
#define OLED_I2C_PIN_SDA                    23  // PB7static U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0,\/* clock=*/ OLED_I2C_PIN_SCL,\/* data=*/ OLED_I2C_PIN_SDA,\/* reset=*/ U8X8_PIN_NONE);#define SUN 0
#define SUN_CLOUD  1
#define CLOUD 2
#define RAIN 3
#define THUNDER 4static void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol)
{
// fonts used:
// u8g2_font_open_iconic_embedded_6x_t
// u8g2_font_open_iconic_weather_6x_t
// encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconicswitch(symbol)
{case SUN:u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);u8g2.drawGlyph(x, y, 69);break;case SUN_CLOUD:u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);u8g2.drawGlyph(x, y, 65);break;case CLOUD:u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);u8g2.drawGlyph(x, y, 64);break;case RAIN:u8g2.setFont(u8g2_font_open_iconic_weather_6x_t);u8g2.drawGlyph(x, y, 67);break;case THUNDER:u8g2.setFont(u8g2_font_open_iconic_embedded_6x_t);u8g2.drawGlyph(x, y, 67);break;
}
}static void drawWeather(uint8_t symbol, int degree)
{
drawWeatherSymbol(0, 63, symbol);
u8g2.setFont(u8g2_font_logisoso32_tf);
u8g2.setCursor(55, 63);
u8g2.print(degree);
u8g2.print("C");
}
static void drawHumidity(uint8_t symbol, int humidity)
{
drawWeatherSymbol(0, 63, symbol);
u8g2.setFont(u8g2_font_logisoso32_tf);
u8g2.setCursor(55, 63);
u8g2.print(humidity);
u8g2.print("%");
}void oled_display()
{u8g2.begin();u8g2.clearBuffer();u8g2.setFont(u8g2_font_logisoso32_tf);
u8g2.setCursor(48+3, 42);
u8g2.print("Hi~");     // requires enableUTF8Print()u8g2.setFont(u8g2_font_6x13_tr);            // choose a suitable font
u8g2.drawStr(30, 60, "By Mculover666");   // write something to the internal memory
u8g2.sendBuffer();//    sht3x_device_t  sht3x_device;
//    sht3x_device = sht3x_init("i2c1", 0x44);rt_thread_mdelay(2000);int status = 0;
char mstr[3];
char hstr[3];
time_t now;
struct tm *p;
int min = 0, hour = 0;
int temperature = 0,humidity = 0;
struct rt_sensor_data sensor_data;while(1)
{switch(status){case 0:now = time(RT_NULL);p=gmtime((const time_t*) &now);hour = p->tm_hour;min = p->tm_min;sprintf(mstr, "%02d", min);sprintf(hstr, "%02d", hour);u8g2.firstPage();do {u8g2.setFont(u8g2_font_logisoso42_tn);u8g2.drawStr(0,63,hstr);u8g2.drawStr(50,63,":");u8g2.drawStr(67,63,mstr);} while ( u8g2.nextPage() );rt_thread_mdelay(5000);status = 1;break;case 1:if(rt_device_read(rt_device_find("temp_dht11"), 0, &sensor_data, 1) == 1){if(sensor_data.data.temp >= 0){temperature = (sensor_data.data.temp & 0xffff) >> 0;      // get temp}}else{temperature = 0;}u8g2.clearBuffer();drawWeather(SUN, temperature);u8g2.sendBuffer();rt_thread_mdelay(5000);status = 2;break;case 2:if(rt_device_read(rt_device_find("temp_dht11"), 0, &sensor_data, 1) == 1){if(sensor_data.data.temp >= 0){humidity = (sensor_data.data.temp & 0xffff0000) >> 16;}}else{humidity = 0;}u8g2.clearBuffer();drawHumidity(RAIN, humidity);u8g2.sendBuffer();rt_thread_mdelay(5000);status = 0;break;}}
}
MSH_CMD_EXPORT(oled_display, oled start);

运行结果如下所示(循环刷新数据):

参考资料

1.https://blog.csdn.net/Mculover666/article/details/104146623
2.https://mculover666.blog.csdn.net/article/details/104418075
3.https://mculover666.blog.csdn.net/article/details/104153715
4.https://mculover666.blog.csdn.net/article/details/104422501

RTOS——桌面mini网络时钟相关推荐

  1. RT-Thread Studio 项目实战教程 | 快速打造一个桌面mini网络时钟

    寻求更清爽的阅读体验,请移步:Mculover666的个人博客. 项目效果视频 花半小时打造的桌面mini网络时钟(自动网络对时.温度显示.湿度显示) 1. RT-Thread Studio RT-T ...

  2. NTP网络时钟同步协议对计算机网络数据的重要性

    NTP网络时钟同步协议对计算机网络数据的重要性 概述:电脑时间走时不准是出了名的.它一般是以廉价的振荡电路或石英钟为基础,每天的误差可达数秒,经过一段时间的累积就会出现较大的误差.随着不断增加的分散式 ...

  3. 单片机课程设计--网络时钟

    单片机课程设计–网络时钟 测控1902 孙楷亮 文章目录 单片机课程设计--网络时钟 作品功能 目标功能 典型应用场景 总体计划 代码计划 时间规划 开发资源 开发环境 硬件资源 软件资源 文档资料 ...

  4. 在计算机桌面上添加小工具日历,实用桌面小工具时钟日历在win7中的添加方法...

    我们在win7系统的使用中,小伙伴们都是知道的系统可以直接选择安装不同的小工具在电脑中使用,比如电脑中的时钟日历等都是可以直接安装在桌面来使用的牡丹石有小伙伴对于时钟日历不知道是在哪里添加到桌面的,对 ...

  5. linux系统下ntp网络时钟服务器(NTP服务器)的搭建和使用

    linux系统下ntp网络时钟服务器(NTP服务器)的搭建和使用 linux系统下ntp网络时钟服务器(NTP服务器)的搭建和使用 安徽京准科技开发的NTP网络时间源设备 参考 ahjzsz.com  ...

  6. 分布式数据库服务器时钟同步(NTP网络时钟同步)北斗卫星同步时钟起到关键性作用

    分布式数据库服务器时钟同步(NTP网络时钟同步)北斗卫星同步时钟起到关键性作用 分布式数据库服务器时钟同步(NTP网络时钟同步)北斗卫星同步时钟起到关键性作用 文章由安徽京准科技公司提供请勿转载 时间 ...

  7. 探索:制药厂系统网络时钟同步(NTP时间同步服务器)

    探索:制药厂系统网络时钟同步(NTP时间同步服务器) 探索:制药厂系统网络时钟同步(NTP时间同步服务器) [摘要]SCADA系统通过I业环网完成数据的传输,存储在服务器的数据库,在通过软件的渠道集成 ...

  8. SDH通信网络时钟同步服务(NTP/PTP精密网络时钟源)精度分析

    SDH通信网络时钟同步服务(NTP/PTP精密网络时钟源)精度分析 SDH通信网络时钟同步服务(NTP/PTP精密网络时钟源)精度分析 安徽京准公司提供原创资料!! 3) 从站时钟要从高一级设备或同一 ...

  9. 西门子PCS7系统NTP网络时钟同步(NTP时钟发生器)介绍

    西门子PCS7系统NTP网络时钟同步(NTP时钟发生器)介绍 HR-901GB时钟服务器由安徽京准科技研制开发, 西门子PCS7系统时钟同步模式介绍 PCS7系统基于TIA构建方式,在整个系统下包含了 ...

最新文章

  1. 微信 Tinker 负责人张绍文关于 Android 热修复直播分享记录
  2. python的相对路径导入问题
  3. [云炬创业基础笔记]第二章创业者测试9
  4. PHP中array_merge函数与array+array的区别
  5. 基于LAMP实现web日志管理查看
  6. DevOps平台中的自动化部署框架设计
  7. c语言sizeof(test),解析C语言中的sizeof
  8. createsolidcaret 后 很快就不闪烁了_【文献推送】Adv. Mater. | 单分散硅基闪烁体实现X射线介导的深层肿瘤光动力治疗...
  9. Windows 下安装 Redis 1
  10. win7备份工具_u盘系统重装win7旗舰版详细图解教程
  11. Git版本控制:Github的使用之 多人协作及参与项目
  12. 响应式设计就是这个时代最值得学习、时间的趋势
  13. ARM Cortex-A53 Cache与内存的映射关系以及Cache的一致性分析
  14. 怎样看python源代码-如何查看python源代码
  15. 使用ACCESS数据库时出现“操作必须使用一个可更新的查询”的解决办法
  16. 谷歌浏览器代理服务器出现问题怎么办?(最快的解决办法)
  17. OSChina 周一乱弹 ——我们不应歧视任何语言,她们都是萌娘!(有图有真相)...
  18. 在Redhat9上安装Oracle 9.2
  19. 在数据挖掘中,经常犯的错误有哪些?
  20. 39.(前端)欢迎页面的设置

热门文章

  1. 测试自动化_Katalon
  2. 三、MySql03 SQL 高级(一)
  3. 40主题制作代码———更新手机颜色十六进制代码
  4. 使用CCProxy+Proxifier实现代理
  5. 计算机基础知识1作业,计算机作业1基础知识(含答案)-20210508182923.docx-原创力文档...
  6. 使用easyrsa3来制作证书
  7. 如何在MCU中使用二进制库(动态库)
  8. sql与mysql中2个表数据进行匹配_SQL语言中把数据库中两张表数据关联起来的语句...
  9. 网络rtk能连接服务器,没信号,RTK连接CORS网络设置
  10. webpack打包css