Funpack5-4 - 用FRDM-MCXN236开发板+彩屏+SHT31制作温湿度时钟
该项目使用了FRDM-MCXN236开发板、彩屏、SHT31,实现了温湿度时钟的设计,它的主要功能为:彩屏和串口显示温湿度信息、RTC时钟,可以通过按键调整时间,掉电后时间保持。
标签
嵌入式系统
Funpack活动
开发板
温湿度
参加活动/培训
RTC时钟
FRDM-MCXN236
Snapdragon
更新2026-10-19
10

一、项目介绍

活动项目是基于MCXN236的官方开发板搭配7寸彩屏SSD1963、0.96寸彩屏ST7735S、温湿度传感器SHT31、MicroSD卡、按键等实现的温湿度时钟。下面介绍分别介绍各部分。

1、MCXN236开发板

mcxn236是由NXP推出的通用高性能MCU,搭载Cortex-M33内核,主频高达150MHz,集成1MiB的Flash、352KiB的ECC RAM。板卡自带调试器,并附有串口桥接功能。

2、7寸彩屏SSD1963

此项目设计之初由于是演示项目,并未考虑加入7寸屏。后在开发过程中,发现NXP官方对SSD1963进行了支持,所以加入此屏幕,让这个演示项目与实际项目的距离更近一步。SSD1963采用FlexIO驱动,为了兼容MCXN236开发板,制作了一个转接板,加入外部供电TypeC口,防止供电不足导致的板卡运行不稳定。

3、0.96寸彩屏

考虑到mikroBUS扩展卡的大小,使用0.96寸彩屏可以兼顾显示效果与整体美观。ST7735S采用SPI接口驱动。

4、mikroBUS扩展板

此扩展板板载SHT31温湿度传感器与MicroSD卡卡槽。SHT31由IIC接口驱动,温度精度可达±0.2℃,湿度精度可达±2%RH,体积小巧,搭配mikroBUS正好;MicroSD卡由SPI接口驱动(与ST7735S共用),此设计使用的是一款16GB的SDHC卡。

二、设计思路

1、项目功能设计思路

本项目最初以任务一为目标,完成一套电子时钟系统,实现时间显示与时间设置功能。

项目初期,按照基础任务要求,结合手头有的模块,选用0.96寸彩屏作为显示设备。先是通过排线连接开发板进行调试,结合板载的按键,实现了任务要求的基本功能,但排线数量一多,显得很杂乱,而且很不稳定,经常接触不良或者短路。

突然想到,可以结合任务三,设计一款扩展卡。开发板板载按键数量少、位置分散,且整个任务只是显示个时间,感觉比较单一。因此设计制作了mikroBUS接口的扩展板,板载0.96寸彩屏接口、SHT31 温湿度传感器、MicroSD卡槽以及三个按键,在原有时钟功能基础上增加温湿度采集显示,完善系统外设资源。

扩展板调试完成后,感觉0.96寸屏幕显示尺寸较小,无法同时显示时间与温湿度。再加上查看官方例程的时候,发现已适配SSD1963,就考虑使用7寸彩屏作为显示设备,7寸屏幕接口与主控板接口不兼容,设计并制作屏幕转接板,7寸屏功耗较高,所以同时加上Type-C 外置独立供电结构,保证板卡稳定运行。

2、软件功能设计思路

由于做了扩展卡,外设比较多,但软件功能设计上想把所有的外设都用上。

首先针对显示功能进行设计:7寸屏作为主显示界面,使用大字体展示时间信息,保证时间显示清晰,同时同步显示环境温度与湿度数据。0.96寸小型彩屏作为辅助显示设备,只显示温湿度数据。

三个按键主要用于系统人机交互,承担时间调节功能,可对时、分、秒进行手动修改并写入RTC。

SHT31温湿度传感器没什么好说的,就采集温湿度信息。

MicroSD的功能是比较难设计的,开始是在屏幕上显示SD卡的容量信息,但感觉偏离了主题。后来在屏幕字体调试过程中发现,大字体字模体积很大,修改字体查看效果每次都需要重新编译烧录。想到可以通过SD卡+FatFs,使用电脑直接将字模文件存储进去,可以自由的选择不同字体。由于时间关系,项目决定只在SD卡内置两套字体,仅通过按键切换演示。

三、硬件设计

1、mikroBUS扩展板

原理图:

原理图比较简单,左上图是连接mikroBUS两侧IO的排针;右上是0.96寸彩屏接口(也可以接0.96寸OLED)、MicroSD卡槽,!!!注意这里有一个问题!!!,SPI的MOSI与MISO反了,但是MCXN236支持交换收发引脚,软件上没问题,所以也没再做新板;中间是三个按键,加了104电容滤波,可以不加消抖直接使用(测试程序,正式研发还是建议加上消抖);最下面是SHT31的电路,由于IO口不足,ALERT引脚悬空未使用,R3、R4空焊,板卡上已经内置上拉电阻。剩下的为滤波电容。

PCB:

左侧为顶层,右侧为底层。

3D效果图

右侧是底面,与板卡上的排母连接;左侧是正面,提供显示、按键等功能。

2、并口彩屏转接板

彩屏转接板只是做了pin脚位置的转换,增加了独立5V供电电路,两边的功能定义完全一致。这里没有把触摸连上,开发板上给的是IIC的电容触摸IO,而彩屏是类SPI的串行电阻屏。

四、软件设计

1、程序框图

结合程序框图,下面介绍程序整体运行流程,顺便也把功能介绍一下。

系统上电后,先完成内部外设、硬件外设以及全局变量的初始化,再初始化FatFs文件系统与毫秒(将SysTick设置为1毫秒的定时器)定时器。初始化结束后进入主轮询循环。

程序包含两种工作模式:正常显示模式与时间设置模式。正常显示模式下,温湿度、时间实时刷新;时间设置模式下,暂停温湿度采集与时间走时,等待用户修改时间。

主循环每次执行1ms阻塞延时,避免外设频繁操作,该延时不影响项目的正常运行。循环分为两大模块:第一模块首先会进行100ms的定时检测,判断距离上次检测是否达到100ms,未达到则继续等待;达到100ms后判断当前工作模式,

若为正常显示模式,则在7寸彩屏上显示RTC时间与温湿度,0.96寸彩屏显示温湿度,串口向上位机发送RTC日期、时间以及温湿度数据。若为时间设置模式,则直接退出到主循环,不刷新显示。

第二模块为按键检测,每1ms执行一次。首先判断按下哪个键:①中间按键按下,判断当前模式,若为正常显示模式,切换至时间设置模式;若为时间设置模式,则判断光标位置,光标到达最后一位,切换回正常显示模式,未到末尾,则移动光标至下一个时间字段,回到按键判断流程。②如果按下上键或下键,同样先判断当前工作模式,若为正常显示模式,则切换MicroSD卡内存储的字体;若为时间设置模式,修改光标指向的时间字段数值(上键+1,下键-1),修改完成后返回主循环,等待下一次操作。

2、关键代码介绍

        static void LCD_DrawSelect(uint8_t index);
static void AdjustTime(irtc_datetime_t *dateTime, uint8_t index, uint8_t addFlag);
static void LCD_DrawHMS(uint8_t hms, uint8_t n);

volatile uint32_t systemMsTick = 0;
static uint8_t cursorIndex = 0;

业务代码的子函数与全局变量

① cursorIndex存储光标位置与模式信息,取值范围是0~6,0代表正常显示模式,1代表当前修改光标指向小时的十位,2代表当前的修改光标指向小时的个位,以此类推,3、4负责修改分钟,5、6负责修改秒。cursorIndex从0~6不断循环,光标位置也随着改变。

② LCD_DrawSelect,作用是显示当前光标位置,其代码如下:

static uint16_t LCD_GetSelectXStart(uint8_t index)
{
if (index)
{
if (index >= 5) {
index += 2;
} else if (index >= 3) {
index += 1;
}
index--;
return 16 + index * 96;
}
return 0;
}

static void LCD_DrawSelect(uint8_t index)
{
static uint8_t lastIndex = 0;

if (index != lastIndex)
{
if (lastIndex)
{
uint16_t x = LCD_GetSelectXStart(lastIndex);
SSD1963_DrawRectangle(x, 200, x + 95, 295, 0);
}
if (index)
{
uint16_t x = LCD_GetSelectXStart(index);
SSD1963_DrawChar(FONT_TYPE_96x96, x, 200, FONT_SIGN_UP, COLOR_RED, COLOR_BLACK);
}

lastIndex = index;
}
}

首先判断当前的光标状态与要修改的光标状态是否一致,一致的话不做任何操作,不一致的话,首先清除当前的光标,再画要修改的光标。其位置信息由LCD_GetSelectXStart函数计算,Y坐标统一固定值,无需计算。

③ AdjustTime,作用是根据光标以及按键的状态,修改时间(时分秒),其代码如下:

static void AdjustTime(irtc_datetime_t *dateTime, uint8_t index, uint8_t addFlag)
{
uint8_t h1 = dateTime->hour / 10;
uint8_t h0 = dateTime->hour % 10;
uint8_t m1 = dateTime->minute / 10;
uint8_t m0 = dateTime->minute % 10;
uint8_t s1 = dateTime->second / 10;
uint8_t s0 = dateTime->second % 10;

switch (index)
{
case 1: h1 = (h1 + (addFlag ? 1 : 2)) % 3;
if ((h1 == 2) && (h0 > 3)) { h0 = 3; }
break;
case 2: h0 = (h1 == 2) ? ((h0 + (addFlag ? 1 : 3)) % 4)
: ((h0 + (addFlag ? 1 : 9)) % 10);
break;
case 3: m1 = (m1 + (addFlag ? 1 : 5)) % 6; break;
case 4: m0 = (m0 + (addFlag ? 1 : 9)) % 10; break;
case 5: s1 = (s1 + (addFlag ? 1 : 5)) % 6; break;
case 6: s0 = (s0 + (addFlag ? 1 : 9)) % 10; break;
}

dateTime->hour = h1 * 10 + h0;
dateTime->minute = m1 * 10 + m0;
dateTime->second = s1 * 10 + s0;

if (index >= 5) {
LCD_DrawHMS(2, dateTime->second);
} else if (index >= 3) {
LCD_DrawHMS(1, dateTime->minute);
} else {
LCD_DrawHMS(0, dateTime->hour);
}
}

由于修改光标可以单独修改每个时间单位的十位、个位,这里先把他们的十位、个位提取出来,再根据index(修改光标的位置)的值以及addFlag(1代表+1,0代表-1)对其进行单独修改。由于每个修改的值范围最大都在0~9之间,所以这里的“-1”操作由“+(最大取值-1)”的操作代替。需要注意的是,在小时的修改操作中,注意范围,要加入额外的判断处理,防止出现“29时”等问题。

④ LCD_DrawHMS,作用是单独刷新时、分、秒区域,这个是属于临时优化的产物,由于SDCard速度的限制及7寸彩屏的分辨率较高,如果修改时全局刷新,则会产生明显的卡顿感。其代码如下:

static void LCD_DrawHMS(uint8_t hms, uint8_t n)
{
uint16_t x = 16 + 96 * 3 * hms;
SSD1963_DrawChar(FONT_TYPE_192x96, x + 0 , 0, (n / 10) + '0', COLOR_WHITE, COLOR_BLACK);
SSD1963_DrawChar(FONT_TYPE_192x96, x + 96, 0, (n % 10) + '0', COLOR_WHITE, COLOR_BLACK);
}

这里首先会算出x的坐标,再调用SSD1963的显示字符的函数,将时或分或秒的值刷新显示。这里的hms,0代表小时;1代表分钟;2代表秒钟。

业务主轮询代码

① 负责刷新显示的部分

        if ((cursorIndex == 0) && (systemMsTick % 100))
{
RTC_GetDateTime(&dateTime);
if (oldSecond != dateTime.second)
{
char string[10];

printf("\r\nRTC Time: %d/%d/%d %02d:%02d:%02d\r\n", dateTime.year, dateTime.month, dateTime.day,
dateTime.hour, dateTime.minute, dateTime.second);
oldSecond = dateTime.second;

sprintf(string, "%02u:%02u:%02u", dateTime.hour, dateTime.minute, dateTime.second);
SSD1963_DrawString(FONT_TYPE_192x96, 16, 0, string, COLOR_WHITE, COLOR_BLACK);

float temperature, humidity;
SHT31_Read(&temperature, &humidity);
printf(" temperature = %f℃, humidity = %f%%\r\n", temperature, humidity);

sprintf(string, "%.5f", temperature);
ST7735S_DrawString(FONT_TYPE_36x18, 0, 0, string, COLOR_RED, 0);
SSD1963_DrawString(FONT_TYPE_36x18, 328, 408, string, COLOR_RED | COLOR_GREEN, COLOR_BLACK);

sprintf(string, "%.5f", humidity);
ST7735S_DrawString(FONT_TYPE_36x18, 0, 40, string, COLOR_BLUE, 0);
SSD1963_DrawString(FONT_TYPE_36x18, 328, 444, string, COLOR_GREEN, COLOR_BLACK);
}
}

这里首先会判断当前的状态,如果是正常显示状态,再去判断systemMsTick是否是100的整数倍(相当于100毫秒定时)。如果达到了定时的时间,则去读取当前的RTC时间,并判断是否需要更新,如果秒发生了变化,则将RTC的日期时间通过串口发送到上位机,并将时间显示在7寸屏上;然后读取温湿度信息,将其显示在两个彩屏上。这里定时100毫秒就去读取一次的原因是为了时间更新的更均匀。

② 负责按键检测并修改时间​​的部分

        keyStatusType key = KEY_GetStatus();
if (key != KEY_NONE)
{
if (key == KEY_MIDDLE) {
if (++cursorIndex > 6) {
cursorIndex = 0;
IRTC_SetWriteProtection(RTC, false);
IRTC_SetDatetime(RTC, &dateTime);
}
LCD_DrawSelect(cursorIndex);
} else {
if (cursorIndex == 0) {
if (key == KEY_UP) {
SDCardFontSwitch(0);
} else if (key == KEY_DOWN) {
SDCardFontSwitch(1);
}
} else {
if (key == KEY_UP) {
AdjustTime(&dateTime, cursorIndex, 1);
} else if (key == KEY_DOWN) {
AdjustTime(&dateTime, cursorIndex, 0);
}
}
}

while (KEY_GetStatus() != KEY_NONE);
}

SDK_DelayAtLeastUs(1000, SystemCoreClock);

这里检测按键并修改时间的流程,在前面已有说明。这里再补充一点,在识别到按键按下之后,就会立刻按照键值进行处理,处理完成后,会等待按键释放后再继续运行。

五、功能展示图及说明

1、正常运行

这里是7寸彩屏的正常显示模式下的图示,此时,无光标显示,上方以192x96的字号显示是按,下面以小字号显示温湿度,黄色为温度,单位℃;绿色为湿度的百分值。

2、切换字体

这是切换另一款字体的正常显示模式下的图示,可以对比上一小节的图片,字体明显不同。

3、0.96寸小彩屏显示

这是0.96寸彩屏的正常显示模式下的图示,红色为温度,单位℃;蓝色为湿度的百分值。

4、修改时间模式

第一张图表示修改光标(红色箭头)指在了分钟的十位;第二张图是按了一下”上键“,分钟的十位加一后的结果。

第三张图展示了将修改后的内容写回RTC的功能。修改光标到达末尾后,会将修改后的内容写回RTC,并回到正常显示模式,第三张图的秒由58→59可说明修改、写入有效。

5、串口传输

如图,串口正常的每隔一秒将日期时间、温湿度信息发送到上位机(串口助手)。

六、项目中遇到的困难及解决办法

1、已解决问题

①、mikroBUS的扩展卡,SPI的MOSI与MISO画反

解决方案:MCXN236支持SPI的收发引脚互换,通过软件解决此问题。

②、采用官方例程,SSD1963显示不正常

解决方案:修改驱屏参数,不同的屏哪怕是同一个控制芯片,其配置参数也不尽相同。

③、MDK5下载程序到板卡后,板卡复位不运行,必须断电

解决方案:进入调试功能,全速运行后再关掉调试,板卡即可正常复位运行。

2、未解决问题

①、每次更新程序后,点击调试,首次下载程序几乎会失败,第二次基本成功

②、SPI无法挂到PLL OUT时钟上,导致运行频率较低

七、心得体会

这次活动主要收获是熟悉了NXP官方SDK的代码风格,熟悉了MCX系列MCU的性能与功能,对后续工作过程中,自己DIY设计选型都有一定的参考帮助。


软硬件
电路图
附件下载
Funpack5-4 - 用FRDM-MCXN236开发板+彩屏+SHT31制作温湿度时钟--源代码.zip
Funpack5-4 - 用FRDM-MCXN236开发板+彩屏+SHT31制作温湿度时钟--源代码
团队介绍
陈海
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号