一、先来张照片
art-pi的做工我看着是真的舒服。很符合RT-Thread官网的那句话"小而美"了。
二、出厂程序体验
出厂例程是通过蓝牙对开发板进行配网,内置一个web服务器,配网成功后能够通过网页显示开发板的基本信息,并对开发板的板载LED进行简单的控制。
蓝牙配网流程直接看GitHub的文档即可
配网成功以后,这个网页是真的骚,可以查看内存、norflash、SD等信息。
三、驱动I2C的OLED屏幕
其实拿到art-pi之后,并没有什么好的创意来发挥H7的实力。RT-Thread最近半年多也一直在学习,也有几个比赛我也上了rtt,但是学艺不精,比赛只取得了一个勉强看得过去的成绩。
没有新的整活,于是就只好旧活新整,把原来F103上的东西搬到ART-Pi上。
物料:
OLED * 1
ART-Pi * 1
平台:
RT-Thread Studio
主要代码
本来是打算用原来的方式开发的,即:用RT-Thread Nano。但是体验过了rtt软件的方便,就不想自己手写外设驱动了,抱着试一下的心态,搜索了一下OLED的软件包,还真的有。果断用起来。这个原来是用在arduino上的库已经被大佬移植的好好的了,直接用轮子就好了;而且还提供了example,一些重复代码直接复制粘贴就可以了。
如图配置即可
在cv过程中遇到的小坑
仔细观察ART-Pi的板子,就会发现上边没有标注引脚名称…最后找到了ART-Pi扩展引脚说明.pdf这个文档
在这里插入图片描述
从上图可以看出PH11、PH12分别是I2C的SCL、SDA。随后,回到rtt-studio打开drv_gpio.c
找到PH11、PH12对应的引脚号(如下图所示)。但是这个方法略显麻烦。
由于这是stm32的mcu,所以我们可以直接通过这个GET_PIN(port,pin)
这个宏来获取引脚编号,这个宏在drv_common.h
中定义:
#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN)
所以代码有两种写法:
#define OLED_I2C_PIN_SCL 123 // PH11
#define OLED_I2C_PIN_SDA 124 // PH12
或者
#define OLED_I2C_PIN_SCL GET_PIN(H,11) // PH11
#define OLED_I2C_PIN_SDA GET_PIN(H,12) // PH12
值得注意的是使用第二种写法时,一定要添加头文件 #include “drv_common.h”
,不然会报错。
在OLED显示这方面,参考了其他大佬的代码。但是他们的代码都是跑在死循环里边的,一旦使用了就不能用Finsh控制台了,就很烦。我稍微改了一下,加了一个线程并且导出了MSH命令:
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <U8g2lib.h>
#include <stdio.h>
#include "drv_common.h"
#include <drv_soft_i2c.h>
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 1024
#define THREAD_TIMESLICE 5
static rt_thread_t tid1 = RT_NULL;
#define OLED_I2C_PIN_SCL GET_PIN(H,11) // PH11
#define OLED_I2C_PIN_SDA GET_PIN(H,12) // PH12
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);
static void oled_display(void *param)
{
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 Sakura"); // write something to the internal memory
u8g2.sendBuffer();
rt_thread_mdelay(2000);
char mstr[3];
char hstr[3];
time_t now;
struct tm *p;
int min = 0, hour = 0;
while(1)
{
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(50);
}
}
int thread_sample(void)
{
/* 创建线程 1,名称是 thread1,入口是 thread1_entry*/
tid1 = rt_thread_create("thread1",
oled_display, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
/* 如果获得线程控制块,启动这个线程 */
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(thread_sample, thread sample);
效果
先联网。使用的是板载WiFi模块,使用命令 wifi join [SSID] [PASSWORD]
连网即可。
导出的msh命令列表里边还有个同步网络时间的命令 date
最后输入 thread_sample
:
遗留问题
-
这个功能就是一个简单的网络助手。但是从上边的演示过程中,可以看到,需要手动输入命令才能跑起来。这样很不智能啊,但是板载的WiFi模块(AP6212)我在工程中找了半天也没看到关于它的代码在哪儿。有空仔细研究研究,怎么在系统初始化时就连上网络、同步网络时间
-
PH11、PH12的引脚应该是属于硬件iic,但是我配置的是软件iic。这其中会不会有不同目前还没有深究,下回试试其他引脚来模拟iic