描述
一、硬件介绍
通过查看环境监测板的原理图,发现该板子主要有两个种资源:12864O
LED显示屏,两个模拟按键。两个模拟按键分别按下时,因为电阻分压,在SWITCH端的电压都一样,根据
测量这个SWITCH端电压值,可以读取到按键的状态。
其中OLED兼容两种
通信接口SPI和I2C,这里我选择使用I2C。
它们使用主控的GPIO口分别为:AHT20温
湿度传感器SDA --》 GPIO13 可复用为I2C0_SDASCL --》 GPIO14 可复用为I2C0_SCL模拟按键ADC --》 GPIO05 可复用为ADC2
二、软件设计1、新建文件
在wifi-iot/app目录下,新建OLED文件夹,
存放与显示板和环境监测板相关的代码。所含文件如下所示。
其中aht20.c、aht20.h、envrionment_demo.c。是从上一篇帖子移植过来的,主要跟环境监测板有关。oled_demo.c 、oled_fonts.h 、 oled_
ssd1306.h 、oled_ssd1306.c从许思维老师例程中移植过来。
timeconv.c timeconv.h与时间转换有关。
2、timeconv.c
该c文件主要跟时间戳转换有关,在这个例程中,每一秒时间戳数值加1,然后再把时间戳转换为北京时间即可到的时间戳对应的北京时间。
-
#include "timeconv.h"
-
#include
-
#include
-
-
static uint8_t month_day[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //平年
-
static uint8_t Leap_month_day[12]={31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //闰年
-
const uint16_t dayPerYear[4] = {365, 365, 365, 366};
-
-
// 判断是否是闰年
-
// year: 需要判断的年
-
// return:1:闰年
-
// 0: 平年
-
uint8_t isLeapYear(uint16_t year)
-
{
-
uint8_t res=0;
-
-
if(year%4 == 0) // 能够被4整除
-
{
-
if((year%100 == 0) && (year%400 != 0)) //能够被100整除,但是不能够被400整除
-
{
-
res = 0;
-
}
-
else
-
{
-
res =1;
-
}
-
}
-
return res;
-
}
-
-
// 将Unix时间戳转换为北京时间
-
// unixTime: 需要判断的Unix时间戳
-
// *tempBeijing:返回的北京时间
-
// return:none
-
// note:没对输入参数正确性做判断
-
void covUnixTimeStp2Beijing(uint32_t unixTime, rtc_time_t *tempBeijing)
-
{
-
uint32_t totleDaynum=0, totleSecNum=0;
-
uint16_t remainDayofYear;
-
uint8_t *pr, tempYear=0;
-
totleDaynum = (uint32_t)unixTime/(((uint32_t)24*60*60)); //总天数(注意加括号)
-
totleSecNum = (uint32_t)unixTime%((uint32_t)24*60*60); //当天剩余的秒速
-
memset(tempBeijing, 0x00, sizeof(rtc_time_t));
-
// 1.计算哪一年
-
tempBeijing->ui8Year = 1970 + (totleDaynum/((uint32_t)FOURYEARDAY))*4;
-
remainDayofYear = totleDaynum%((uint32_t)FOURYEARDAY)+1;
-
//Delay_1ms(1000);
-
while(remainDayofYear > dayPerYear[tempYear])
-
{
-
remainDayofYear -= dayPerYear[tempYear];
-
tempBeijing->ui8Year++;
-
tempYear++;
-
}
-
//2.计算哪一月的哪一天
-
pr = isLeapYear(tempBeijing->ui8Year)?Leap_month_day:month_day;
-
while(remainDayofYear > *(pr+tempBeijing->ui8Month))
-
{
-
remainDayofYear -= *(pr+tempBeijing->ui8Month);
-
tempBeijing->ui8Month++;
-
}
-
tempBeijing->ui8Month++; //month
-
tempBeijing->ui8DayOfMonth = remainDayofYear; //day
-
//3.计算当天时间
-
tempBeijing->ui8Hour = (totleSecNum)/3600;
-
tempBeijing->ui8Minute = (totleSecNum%3600)/60; //error:变量搞错
-
tempBeijing->ui8Second = (totleSecNum%3600)%60;
-
-
//4.时区调整
-
tempBeijing->ui8Hour +=TIMEZONE;
-
if(tempBeijing->ui8Hour>23){
-
tempBeijing->ui8Hour -= 24;
-
tempBeijing->ui8DayOfMonth++;
-
}
-
}
-
-
// 将北京时间转换为Unix时间戳
-
// year: 需要判断的年
-
// return:Unix时间戳(从1970/1/1 00:00:00 到现在的秒数)
-
// note:没对输入参数正确性做判断
-
uint32_t covBeijing2UnixTimeStp(rtc_time_t *beijingTime)
-
{
-
uint32_t daynum=0, SecNum=0; //保存北京时间到起始时间的天数
-
uint16_t tempYear=1970, tempMonth=0;
-
-
-
//1.年的天数
-
while(tempYear < beijingTime->ui8Year)
-
{
-
if(isLeapYear(tempYear)){
-
daynum += 366;
-
}
-
else{
-
daynum += 365;
-
}
-
tempYear++;
-
}
-
//2.月的天数
-
while(tempMonth < beijingTime->ui8Month-1)
-
{
-
if(isLeapYear(beijingTime->ui8Year)){ //闰年
-
daynum += Leap_month_day[tempMonth];
-
}
-
else{
-
daynum += month_day[tempMonth];
-
}
-
tempMonth++;
-
}
-
//3.天数
-
daynum += (beijingTime->ui8DayOfMonth-1);
-
-
//4.时分秒
-
SecNum = daynum*24*60*60; //s
-
SecNum += beijingTime->ui8Hour*60*60;
-
SecNum += beijingTime->ui8Minute*60;
-
SecNum += beijingTime->ui8Second;
-
-
//5.时区调整
-
SecNum -= TIMEZONE*60*60;
-
-
return SecNum;
-
}
复制代码
3.timeconv.h
-
#ifndef __TIMECONV_H
-
#define __TIMECONV_H
-
-
#include
-
#include
-
#include
-
#include "ohos_init.h"
-
#include "cmsis_os2.h"
-
#define FOURYEARDAY (((uint32_t)365+365+365+366)) //4年一个周期内的总天数(1970~2038不存在2100这类年份,故暂不优化)
-
#define TIMEZONE (8) //北京时区调整
-
-
typedef struct rtc_time_struct
-
{
-
uint16_t ui8Year; // 1970~2038
-
uint8_t ui8Month; // 1~12
-
uint8_t ui8DayOfMonth; // 1~31
-
uint8_t ui8Week;
-
uint8_t ui8Hour; // 0~23
-
uint8_t ui8Minute; // 0~59
-
uint8_t ui8Second; // 0~59
-
-
}rtc_time_t;
-
-
uint8_t isLeapYear(uint16_t year);
-
void covUnixTimeStp2Beijing(uint32_t unixTime, rtc_time_t *tempBeijing);
-
uint32_t covBeijing2UnixTimeStp(rtc_time_t *beijingTime);
-
-
#endif /*__TIMECONV_H*/
-
复制代码
4、oled_demo.c
该c文件主要是oled显示屏显示程序、包括时间转换显示、温湿度显示。
-
extern float humidity;
-
extern float temperature;
-
static void OledTask(void *arg)
-
{
-
rtc_time_t mData;
-
(void)arg;
-
-
GpioInit();
-
-
OledInit();
-
OledFillScreen(0x00);
-
while (1) {
-
static char text[128] = {0};
-
unsigned short data = 0;
-
AdcRead(analog_KEY_CHAN_NAME, &data, WIFI_IOT_ADC_EQU_MODEL_4, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0);
-
float voltage = ConvertToVoltage(data);
-
snprintf(text, sizeof(text), "voltage: %.3f!", voltage);
-
//OledShowString(0, 5, text, 1);
-
-
OLED_ShowCHinese(0,3,0);//温
-
OLED_ShowCHinese(16,3,2);//度
-
OledShowChar(32,3,':',2);
-
sprintf((char *)TimeStr,"%02d",
-
(uint32_t)temperature);
-
OledShowString(40,3,(char *)TimeStr,2);
-
OLED_ShowCHinese(64,3,1);//湿
-
OLED_ShowCHinese(80,3,2);//度
-
OledShowChar(96,3,':',2);
-
sprintf((char *)TimeStr,"%02d",
-
(uint32_t)humidity);
-
OledShowString(104,3,(char *)TimeStr,2);
-
-
timedata++;
-
covUnixTimeStp2Beijing(timedata, &mData);
-
sprintf((char *)TimeStr,"%04d-%02d-%02d",
-
mData.ui8Year, mData.ui8Month, mData.ui8DayOfMonth);
-
OledShowString(24,0,(char *)TimeStr,1);
-
sprintf((char *)TimeStr,"%02d:%02d:%02d",
-
mData.ui8Hour,mData.ui8Minute,mData.ui8Second);
-
OledShowString(32,1,(char *)TimeStr,1);
-
sleep(1);
-
}
-
}
复制代码
5、oled_ssd1306.c
原来例程上是不能中文的,现在把显示中文功能加上,但是需要提前使用取模软件把字取模。
-
//显示汉字
-
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
-
{
-
uint8_t t,adder=0;
-
OledSetPosition(x,y);
-
for(t=0;t<16;t++)
-
{
-
WriteData(Hzk[2*no][t]);
-
adder+=1;
-
}
-
OledSetPosition(x,y+1);
-
for(t=0;t<16;t++)
-
{
-
WriteData(Hzk[2*no+1][t]);
-
adder+=1;
-
}
-
}
复制代码
-
static const unsigned char Hzk[][16]={
-
{0x10,0x60,0x02,0x8C,0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00},
-
{0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00},/*"温",0*/
-
/* (16 X 16 , 宋体 )*/
-
{0x10,0x60,0x02,0x8C,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00},
-
{0x04,0x04,0x7E,0x01,0x44,0x48,0x50,0x7F,0x40,0x40,0x7F,0x50,0x48,0x44,0x40,0x00},/*"湿",1*/
-
/* (16 X 16 , 宋体 )*/
-
{0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00},
-
{0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00},/*"度",2*/
-
};
复制代码
6、BUILD.gn
BUILD.gn内容为
-
# Copyright (c) 2020, HiHope Community.
-
#
-
# Redistribution and use in source and binary forms, with or without
-
# modification, are permitted provided that the following conditions are met:
-
#
-
# 1. Redistributions of source code must retain the above copyright notice, this
-
# list of conditions and the following disclaimer.
-
#
-
# 2. Redistributions in binary form must reproduce the above copyright notice,
-
# this list of conditions and the following disclaimer in the documentation
-
# and/or other materials provided with the distribution.
-
#
-
# 3. Neither the name of the copyright holder nor the names of its
-
# contributors may be used to endorse or promote products derived from
-
# this software without specific prior written permission.
-
#
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
static_library("oled_example") {
-
sources = [
-
"oled_demo.c",
-
"oled_ssd1306.c",
-
"timeconv.c",
-
"envrionment_demo.c",
-
"aht20.c"
-
]
-
-
include_dirs = [
-
"//utils/native/lite/include",
-
"//kernel/liteos_m/components/cmsis/2.0",
-
"//base/iot_hardware/inteRFaces/kits/wifiiot_lite",
-
]
-
}
复制代码
这样还不行,还要修改app文件夹下的BUILD.gn。在features下增加"OLED:oled_example",
-
lite_component("app") {
-
features = [
-
"startup",
-
"SSL:ssl_example",
-
"EM:em_example",
-
"OLED:oled_example"
-
]
-
}
复制代码
三、 编译烧录
演示结果
四、总结
显示的时间是没有进行对时的,下一篇讲写关于如何连接网络,并且如何获取网络时间。然后把显示屏上时间更新为网络时间。
`
打开APP阅读更多精彩内容