本文中作者基于rt-thread操作系统搭建了一个迷你时钟,用来显示时间和温湿度。rt-thread studio是一款用于rt-thread开发的软件。目前了解到的作用大概为端口设置,代码调试,引入别的库函数。其优点为操作系统是中文,对中文用户相对来说更加友好;以及可以通过rt-thread软件包下载需要的软件,然后可以直接在主函数中调用,相当方便。对新手上手嵌入式开发是一款相当友好的入门级系统。
作者基于自身学习以及对嵌入式系统开发的热情,打造了一个相同的迷你时钟系统。不得不承认,教程相当详细,按部就班可以较快完成。
1. 事物视频演示
基于STM32L432KC,通过RT-Thread Studio打造一个迷你时钟
2.预期功能
1. 联网获取NTP时间
2. 获取温湿度数据
3.通过OLED显示传感器获取的温湿度数据以及联网得到的时间信息
注:本项目核心是要是想模块之间的通信,需求的核心是要实现两组I2C和一组UART通信。
3.所需器材
开发板:NUCLEO-L432KC
温湿度传感器:SHT31(连接I2C1)
WIFI模块:ESP-8266(连接UART1)
OLED模块:SSD1306(连接I2C3)
注:这里选材跟教程中选择的小熊派不同,但实际上只要是任何拥有两个及以上SPI通信接口以及UART接口的单片机(开发板)都能完成该项目。
4.代码部分
1. main函数部分
#include 《rtthread.h》
#include《drv_soft_i2c.h》
#include《arpa/inet.h》
#include《netdev.h》
#include《ntp.h》
#define DBG_TAG “main”
#define DBG_LVL DBG_LOG
#include 《rtdbg.h》
int sh31_ccollcet(void);
int main(void)
{
LOG_D(“HELLO!”);
struct netdev* net = netdev_get_by_name(“esp0”);
while(netdev_is_internet_up(net) != 1)
{
rt_thread_mdelay(200);
}
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”);
}
return RT_EOK;
}
2. 温湿度传感器SHT31部分代码
#include 《rtthread.h》
#include 《board.h》
#include 《sht3x.h》
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
static rt_thread_t tid1 = RT_NULL;
static void sht31_collect_thread_entry(void *parameter)
{
sht3x_device_t sht3x_device;
sht3x_device = sht3x_init(“i2c1”, 0x44);
rt_thread_mdelay(150);
while (1)
{
if(RT_EOK == sht3x_read_singleshot(sht3x_device))
{
rt_kprintf(“sht31 humidity : %d.%d ”, (int)sht3x_device-》humidity, (int)(sht3x_device-》humidity * 10) % 10);
rt_kprintf(“temperature: %d.%dn”, (int)sht3x_device-》temperature, (int)(sht3x_device-》temperature * 10) % 10);
}
else
{
rt_kprintf(“read sht3x fail.rn”);
break;
}
rt_thread_mdelay(2000);
}
}
int sht31_collect(void)
{
tid1 = rt_thread_create(“sht30_collect_thread”,
sht31_collect_thread_entry, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
return 0;
}
3. OLED代码部分
#include 《rthw.h》
#include 《rtthread.h》
#include 《rtdevice.h》
#include 《U8g2lib.h》
#include 《stdio.h》
#include 《drv_soft_i2c.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 7 // PA7
#define OLED_I2C_PIN_SDA 20 // PB4
static 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 4
static void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol)
{
switch(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 hym”); // 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;
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_EOK == sht3x_read_singleshot(sht3x_device))
{
temperature = (int)sht3x_device-》temperature;
}
else
{
temperature = 0;
}
u8g2.clearBuffer();
drawWeather(SUN, temperature);
u8g2.sendBuffer();
rt_thread_mdelay(5000);
status = 2;
break;
case 2:
if(RT_EOK == sht3x_read_singleshot(sht3x_device))
{
humidity = (int)sht3x_device-》humidity;
}
else
{
humidity = 0;
}
u8g2.clearBuffer();
drawHumidity(RAIN, humidity);
u8g2.sendBuffer();
rt_thread_mdelay(5000);
status = 0;
break;
}
}
}
MSH_CMD_EXPORT(oled_display, oled start);
4. 端口查询代码,方便查询各个端口代码(仅提供跟本次项目有关的部分,全部请查看目录中的board.h文件)
#include “board.h”
#include “drv_common.h”
#ifdef RT_USING_PIN
#include 《rtdevice.h》
#define __STM32_PIN(index, gpio, gpio_index)
{
index, GPIO##gpio, GPIO_PIN_##gpio_index
}
#define __STM32_PIN_RESERVE
{
-1, 0, 0
}
/* STM32 GPIO driver */
struct pin_index
{
int index;
GPIO_TypeDef *gpio;
uint32_t pin;
};
struct pin_irq_map
{
rt_uint16_t pinbit;
IRQn_Type irqno;
};
static const struct pin_index pins[] =
{
#if defined(GPIOA)
__STM32_PIN(0 , A, 0 ),
__STM32_PIN(1 , A, 1 ),
__STM32_PIN(2 , A, 2 ),
__STM32_PIN(3 , A, 3 ),
__STM32_PIN(4 , A, 4 ),
__STM32_PIN(5 , A, 5 ),
__STM32_PIN(6 , A, 6 ),
__STM32_PIN(7 , A, 7 ),
__STM32_PIN(8 , A, 8 ),
__STM32_PIN(9 , A, 9 ),
__STM32_PIN(10, A, 10),
__STM32_PIN(11, A, 11),
__STM32_PIN(12, A, 12),
__STM32_PIN(13, A, 13),
__STM32_PIN(14, A, 14),
__STM32_PIN(15, A, 15),
#if defined(GPIOB)
__STM32_PIN(16, B, 0),
__STM32_PIN(17, B, 1),
__STM32_PIN(18, B, 2),
__STM32_PIN(19, B, 3),
__STM32_PIN(20, B, 4),
__STM32_PIN(21, B, 5),
__STM32_PIN(22, B, 6),
__STM32_PIN(23, B, 7),
__STM32_PIN(24, B, 8),
__STM32_PIN(25, B, 9),
__STM32_PIN(26, B, 10),
__STM32_PIN(27, B, 11),
__STM32_PIN(28, B, 12),
__STM32_PIN(29, B, 13),
__STM32_PIN(30, B, 14),
__STM32_PIN(31, B, 15),
5.心得体会
rt-thread是一款对初学者非常友好的OS,里面有着丰富的库可以被直接调用,例如这次项目中,我的最主要的工作就是基于教程中提供的源代码,修改端口信息来适配本次选择的开发板。其次让我惊艳的是丰富的软件包资源。
从搜索到添加以及使用,都能极快上手,可以说是很好的一次体验了。个人认为RT-Thread的一点不足是,有的时候明明代码没有报错,但却始终无法在硬件端显示想要的内容,只能多次尝试。不过所幸最终还是不辱使命。最后感谢教程博主的详细教程,以及ZKY同学一下午的指导,让我少走了很多弯路。希望有兴趣的读者一定要去仔细看之前提到的博文,相信你一定会有所收获。
本文中作者基于rt-thread操作系统搭建了一个迷你时钟,用来显示时间和温湿度。rt-thread studio是一款用于rt-thread开发的软件。目前了解到的作用大概为端口设置,代码调试,引入别的库函数。其优点为操作系统是中文,对中文用户相对来说更加友好;以及可以通过rt-thread软件包下载需要的软件,然后可以直接在主函数中调用,相当方便。对新手上手嵌入式开发是一款相当友好的入门级系统。
作者基于自身学习以及对嵌入式系统开发的热情,打造了一个相同的迷你时钟系统。不得不承认,教程相当详细,按部就班可以较快完成。
1. 事物视频演示
基于STM32L432KC,通过RT-Thread Studio打造一个迷你时钟
2.预期功能
1. 联网获取NTP时间
2. 获取温湿度数据
3.通过OLED显示传感器获取的温湿度数据以及联网得到的时间信息
注:本项目核心是要是想模块之间的通信,需求的核心是要实现两组I2C和一组UART通信。
3.所需器材
开发板:NUCLEO-L432KC
温湿度传感器:SHT31(连接I2C1)
WIFI模块:ESP-8266(连接UART1)
OLED模块:SSD1306(连接I2C3)
注:这里选材跟教程中选择的小熊派不同,但实际上只要是任何拥有两个及以上SPI通信接口以及UART接口的单片机(开发板)都能完成该项目。
4.代码部分
1. main函数部分
#include 《rtthread.h》
#include《drv_soft_i2c.h》
#include《arpa/inet.h》
#include《netdev.h》
#include《ntp.h》
#define DBG_TAG “main”
#define DBG_LVL DBG_LOG
#include 《rtdbg.h》
int sh31_ccollcet(void);
int main(void)
{
LOG_D(“HELLO!”);
struct netdev* net = netdev_get_by_name(“esp0”);
while(netdev_is_internet_up(net) != 1)
{
rt_thread_mdelay(200);
}
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”);
}
return RT_EOK;
}
2. 温湿度传感器SHT31部分代码
#include 《rtthread.h》
#include 《board.h》
#include 《sht3x.h》
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
static rt_thread_t tid1 = RT_NULL;
static void sht31_collect_thread_entry(void *parameter)
{
sht3x_device_t sht3x_device;
sht3x_device = sht3x_init(“i2c1”, 0x44);
rt_thread_mdelay(150);
while (1)
{
if(RT_EOK == sht3x_read_singleshot(sht3x_device))
{
rt_kprintf(“sht31 humidity : %d.%d ”, (int)sht3x_device-》humidity, (int)(sht3x_device-》humidity * 10) % 10);
rt_kprintf(“temperature: %d.%dn”, (int)sht3x_device-》temperature, (int)(sht3x_device-》temperature * 10) % 10);
}
else
{
rt_kprintf(“read sht3x fail.rn”);
break;
}
rt_thread_mdelay(2000);
}
}
int sht31_collect(void)
{
tid1 = rt_thread_create(“sht30_collect_thread”,
sht31_collect_thread_entry, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
return 0;
}
3. OLED代码部分
#include 《rthw.h》
#include 《rtthread.h》
#include 《rtdevice.h》
#include 《U8g2lib.h》
#include 《stdio.h》
#include 《drv_soft_i2c.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 7 // PA7
#define OLED_I2C_PIN_SDA 20 // PB4
static 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 4
static void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol)
{
switch(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 hym”); // 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;
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_EOK == sht3x_read_singleshot(sht3x_device))
{
temperature = (int)sht3x_device-》temperature;
}
else
{
temperature = 0;
}
u8g2.clearBuffer();
drawWeather(SUN, temperature);
u8g2.sendBuffer();
rt_thread_mdelay(5000);
status = 2;
break;
case 2:
if(RT_EOK == sht3x_read_singleshot(sht3x_device))
{
humidity = (int)sht3x_device-》humidity;
}
else
{
humidity = 0;
}
u8g2.clearBuffer();
drawHumidity(RAIN, humidity);
u8g2.sendBuffer();
rt_thread_mdelay(5000);
status = 0;
break;
}
}
}
MSH_CMD_EXPORT(oled_display, oled start);
4. 端口查询代码,方便查询各个端口代码(仅提供跟本次项目有关的部分,全部请查看目录中的board.h文件)
#include “board.h”
#include “drv_common.h”
#ifdef RT_USING_PIN
#include 《rtdevice.h》
#define __STM32_PIN(index, gpio, gpio_index)
{
index, GPIO##gpio, GPIO_PIN_##gpio_index
}
#define __STM32_PIN_RESERVE
{
-1, 0, 0
}
/* STM32 GPIO driver */
struct pin_index
{
int index;
GPIO_TypeDef *gpio;
uint32_t pin;
};
struct pin_irq_map
{
rt_uint16_t pinbit;
IRQn_Type irqno;
};
static const struct pin_index pins[] =
{
#if defined(GPIOA)
__STM32_PIN(0 , A, 0 ),
__STM32_PIN(1 , A, 1 ),
__STM32_PIN(2 , A, 2 ),
__STM32_PIN(3 , A, 3 ),
__STM32_PIN(4 , A, 4 ),
__STM32_PIN(5 , A, 5 ),
__STM32_PIN(6 , A, 6 ),
__STM32_PIN(7 , A, 7 ),
__STM32_PIN(8 , A, 8 ),
__STM32_PIN(9 , A, 9 ),
__STM32_PIN(10, A, 10),
__STM32_PIN(11, A, 11),
__STM32_PIN(12, A, 12),
__STM32_PIN(13, A, 13),
__STM32_PIN(14, A, 14),
__STM32_PIN(15, A, 15),
#if defined(GPIOB)
__STM32_PIN(16, B, 0),
__STM32_PIN(17, B, 1),
__STM32_PIN(18, B, 2),
__STM32_PIN(19, B, 3),
__STM32_PIN(20, B, 4),
__STM32_PIN(21, B, 5),
__STM32_PIN(22, B, 6),
__STM32_PIN(23, B, 7),
__STM32_PIN(24, B, 8),
__STM32_PIN(25, B, 9),
__STM32_PIN(26, B, 10),
__STM32_PIN(27, B, 11),
__STM32_PIN(28, B, 12),
__STM32_PIN(29, B, 13),
__STM32_PIN(30, B, 14),
__STM32_PIN(31, B, 15),
5.心得体会
rt-thread是一款对初学者非常友好的OS,里面有着丰富的库可以被直接调用,例如这次项目中,我的最主要的工作就是基于教程中提供的源代码,修改端口信息来适配本次选择的开发板。其次让我惊艳的是丰富的软件包资源。
从搜索到添加以及使用,都能极快上手,可以说是很好的一次体验了。个人认为RT-Thread的一点不足是,有的时候明明代码没有报错,但却始终无法在硬件端显示想要的内容,只能多次尝试。不过所幸最终还是不辱使命。最后感谢教程博主的详细教程,以及ZKY同学一下午的指导,让我少走了很多弯路。希望有兴趣的读者一定要去仔细看之前提到的博文,相信你一定会有所收获。
举报