
2.2 智能台灯HAL层硬件驱动设计与开发
2.2.1 硬件原理
本节主要介绍智能台灯中温湿度传感器、光照度传感器、LCD控制器的原理。
1.温湿度传感器的原理
本章介绍的智能台灯使用的温湿度传感器是HTU21D型温湿度传感器,该传感器采用适合回流焊的双列扁平无引脚DFN封装,底面积为3mm×3mm,高度为1.1mm,其输出的是经过标定的数字信号,符合标准I2C总线格式。HTU21D型温湿度传感器可为应用提供一个准确、可靠的温湿度数据,通过和微处理器的接口连接,可实现温湿度数值的输出。每一个HTU21D型温湿度传感器在芯片内都存储了电子识别码(可以通过输入命令读取电子识别码)。HTU21D型温湿度传感器的分辨率可以通过输入命令进行修改,可以检测到电池低电量状态并且输出校验和,有助于提高可靠性。
1)HTU21D型温湿度传感器的引脚
HTU21D型温湿度传感器的引脚如图2.14所示。

图2.14 HTU21D型温湿度传感器的引脚
HTU21D型温湿度传感器的引脚功能如表2.6所示。
表2.6 HTU21D型温湿度传感器引脚的功能

续表

HTU21D型温湿度传感器的供电范围为DC 1.8~3.6V,推荐电压为3.0V。VDD引脚和GND引脚之间需要连接一个100nF的去耦电容,该电容位置应尽可能靠近传感器。SCK引脚用于微处理器与HTU21D型温湿度传感器之间的通信同步,由于该引脚包含了完全静态逻辑,因而不存在最小SCK频率。HTU21D型温湿度传感器的DATA引脚为三态结构,用于读取HTU21D型温湿度传感器的数据。当向HTU21D型温湿度传感器发送命令时,DATA引脚电平在SCK引脚电平的上升沿有效且在SCK引脚为高电平时必须保持稳定,DATA引脚电平在SCK引脚电平的下降沿之后改变。当从HTU21D型温湿度传感器读取数据时,DATA引脚电平在SCK引脚电平变低以后有效,且维持到下一个SCK引脚电平的下降沿。为避免信号冲突,微处理器在DATA引脚电平为低电平时需要一个外部的上拉电阻(如10kΩ)将信号提拉至高电平,上拉电阻通常已包含在微处理器的I/O电路中。
2)微处理器与HTU21D型温湿度传感器的通信时序
微处理器与HTU21D型温湿度传感器的通信时序如图2.15所示。

图2.15 微处理器和HTU21D型温湿度传感器的通信时序
(1)启动传感器:将HTU21D型温湿度传感器上电,VDD引脚电平为1.8~3.6V。上电后传感器最多需要15ms(此时SCK引脚电平为高电平)达到空闲状态,即做好准备接收由主机(微处理器)发送的命令。
(2)起始信号:开始传输,发送一位数据时,DATA引脚电平在SCK引脚电平为高电平期间由高电平向低电平的跳变。起始信号如图2.16所示。
(3)停止信号:终止传输,在停止发送数据时,DATA引脚电平在SCK引脚电平为高电平期间由低电平向高电平的跳变。停止信号如图2.17所示。

图2.16 起始信号

图2.17 停止信号
3)主机/非主机模式
微处理器与HTU21D型温湿度传感器之间的通信有两种工作模式:主机模式和非主机模式。
主机模式的通信时序如图2.18所示,灰色部分由HTU21D型温湿度传感器控制。如果要省略校验和(Checksum)传输,可将第45位改为NACK,后接一个传输停止时序(P)。

图2.18 主机模式的通信时序
非主机模式的通信时序如图2.19所示。

图2.19 非主机模式的通信时序
无论采用哪种模式,由于测量的最大分辨率为14位,第2个字节SDA上的最低2(bit43和bit44)用来传输相关的状态(Status)信息,bit1表明测量的类型(0表示温度,1表示湿度),bit0位当前没有赋值。
4)软复位
软复位无须先关闭再次打开电源,就可以重新启动传感器系统。在接收到软复位命令之后,传感器开始重新初始化,并恢复默认设置状态,软复位命令如图2.20所示,软复位所需时间不超过15ms。

图2.20 软复位命令
5)CRC-8校验和计算
当HTU21D型温湿度传感器通过I2C总线通信时,8位的CRC校验可用于检测传输错误,CRC校验可覆盖所有由传感器传送的读取数据。I2C总线的CRC校验属性如表2.7所示。
表2.7 I2C总线的CRC校验属性

6)信号转换
HTU21D型温湿度传感器内部设置的默认分辨率为:相对湿度为12位和温度为14位。SDA引脚输的数据被转换成2个字节的数据包,高字节MSB在前(左对齐),每个字节后面都跟随1个应答位、2个状态位,即LSB的最低2位在进行物理计算前必须置0。例如,所传输的16位相对湿度数据为0110001101010000(二进制)=25424(十进制)。
(1)相对湿度的转换。不论基于哪种分辨率,相对湿度RH都可以根据SDA引脚输出的相对湿度信号SRH以及下面的公式获得(结果以%RH表示):
RH=-6+125×SRH/216
例如,16位的湿度数据为0x6350,即25424,相对湿度的计算结果为42.5%RH。
(2)温度的转换。不论基于哪种分辨率,温度T都可以通过将温度输出信号ST代入到下面的公式中得到(结果以温度℃表示):
T=-46.85+175.72×ST/216
7)基本命令集
HTU21D型温湿度传感器的基本命令集如表2.8所示。
表2.8 基本命令集(RH代表相对湿度、T代表温度)

2.光照度传感器的原理
本章介绍的智能台灯使用的光照度传感器是BH1750FVI-TR型光照度传感器,该传感器集成了数字处理芯片,可以将检测信息转换为光照度,微处理器可以通过I2C总线获取光照度的信息。
BH1750FVI-TR型是一种用于二线式串行总线接口的数字型光照度传感器,该传感器可根据收集的光线强度数据来调整液晶或者键盘背景灯的亮度,利用它的高分辨率可以检测较大范围的光照度的变化,其测量范围为1~65535lx。
BH1750FVI-TR型光照度传感器芯片的特点如下:
● 接近视觉灵敏度的光谱灵敏度特性(峰值灵敏度波长的典型值为560nm);
● 输入光范围广(相当于1~65535lx);
● 对光源的依赖性弱,可使用白炽灯、荧光灯、卤素灯、白光LED、日光灯;
● 可测量的范围为1.1~100000lx/min。
● 受红外线影响很小。
BH1750FVI-TR型光照度传感器的工作参数如表2.9所示。
表2.9 BH1750FVI-TR型光照度传感器的工作参数

BH1750FVI-TR型光照度传感器的运行条件如表2.10所示。
表2.10 BH1750FVI-TR型光照度传感器的运行条件

BH1750FVI-TR型光照度传感器有5个引脚,分别是电源(VCC)、地(GND)、设备地址引脚(DVI)、时钟引脚(SCL)、数据引脚(SDA)。DVI接电源或接地决定了不同的设备地址(接电源时为0x47,接地时为0x46)。BH1750FVI-TR型光照度传感器的结构框图如图2.21所示。

图2.21 BH1750FVI-TR型光照度传感器的结构框图
图2.21中,PD是接近人眼反应的光敏二极管。AMP是集成运算放大器,其作用是将PD电流转换为PD电压。ADC将模拟信号转换为16位数字信号。Logic+I2C接口是光照度计算和I2C总线接口,包括下列寄存器:数据寄存器,用于光照度数据的寄存,初始值是0000 0000 0000 0000;测量时间寄存器,用于时间测量数据的寄存,初始值是0100 0101。OSC是内部振荡器(时钟频率典型值为320kHz),该时钟为内部逻辑时钟。传感器共有6种测量光照强度的模式,分别对应不同的测量分辨率和测量时间。
从BH1750FVI-TR型光照度传感器的结构框图可看出,外部光线被接近人眼反应的光敏二极管PD探测到后,通过集成运算放大器(AMP)将PD电流转换为PD电压,由模/数转换器(ADC)获取16位数字信号,然后由Logic+I2C接口进行数据处理与存储。OSC为内部的振荡器提供内部逻辑时钟,通过相应的指令操作即可读取出内部存储的光照度数据。数据传输使用标准的I2C总线,按照时序要求操作起来非常方便。各种模式的指令集如表2.11所示。
表2.11 BH1750FVI-TR型光照度传感器的指令集

续表

在H分辨率模式下,足够长的测量时间(积分时间)能够抑制一些噪声(包括50Hz和60Hz的光噪声);同时,H分辨率模式的分辨率为1lx,适用于黑暗场合下(小于10lx)。H分辨率模式2同样适用于黑暗场合下的检测。
3.LCD控制器的原理
1)液晶显示器
相对于CRT显示器(阴极射线管显示器),液晶显示器(Liquid Crystal Display, LCD)具有功耗低、体积小、承载的信息量大,以及不伤人眼的优点,因而成为现在的主流显示设备,如电视机、计算机显示器、手机屏幕及各种嵌入式设备的显示屏。
液晶是一种介于固体和液体之间的特殊物质,它是一种有机化合物,常态下呈液态,但是它的分子排列和固体晶体一样有规则,因此取名液晶。如果给液晶施加电场,则会改变它的分子排列,从而改变光线的传播方向,配合偏振光片,它就具有控制光线透过率的作用,再配合彩色滤光片并改变加给液晶电压大小,就能改变某一颜色的透光量。利用这种原理,可做出红、绿、蓝光输出强度可控的显示结构,把三种显示结构组成一个显示单位,通过控制红、绿、蓝光的强度,可以使该显示单位产生不同的色彩,这样的一个显示单位称为像素。液晶屏的显示结构如图2.22所示。

图2.22 液晶屏的显示结构
2)LED点阵显示器
彩色LED点阵显示器的单个像素内包含红、绿、蓝三色LED,显示原理类似大型电子屏的LED,通过控制红、绿、蓝颜色的强度进行混色,可实现全彩颜色输出,多个像素构成一个屏幕。由于每个像素都是LED自发光的,所以在户外白天也显示得非常清晰。但由于LED的体积较大,导致屏幕的像素密度低,所以它一般只适合用于户外的大型显示器。相对来说,单色LED点阵显示器应用得更广泛,如公交车上的信息展示牌等。
3)显示器的基本参数
显示器的基本参数如下:
(1)像素:像素是组成图像的最基本的单元要素,显示器的像素指它成像最小的点,即液晶显示器的一个显示单元。
(2)分辨率:显示器常以“行像素值×列像素值”来表示屏幕的分辨率,如800×480表示该显示器的每行有800个像素,每列有480个像素,也可理解为有800列、480行。
(3)色彩深度:色彩深度指显示器的每个像素能表示多少种颜色,一般用位(bit)来表示。例如,单色显示器的每个像素有亮或灭两种状态(实际上能显示两种颜色),用1bit就可以表示像素的所有状态,所以它的色彩深度为1bit,其他常见的显示器色彩深度为16bit、24bit。
(4)显示器尺寸:显示器的大小一般以英寸表示,如5英寸、21英寸、24英寸等,这个长度是指屏幕对角线的长度,通过显示器的对角线长度及长宽比可确定显示器的实际长宽尺寸。
(5)点距:点距指两个相邻像素之间的距离,它会影响画质的细腻度及观看距离,相同尺寸的屏幕,若分辨率越高,则点距越小,画质越细腻。现在有些手机屏幕的画质比电脑显示器的还细腻,这是手机屏幕点距小的原因;LED点阵显示屏的点距一般都比较大,所以适合远距离观看。
4)FSMC
STM32F407或STM32F417系列微处理器都带有FSMC模块。FSMC,即灵活的静态存储控制器,能够与同步或异步存储器、16位PC存储器卡连接,STM32F4的FSMC模块支持与SRAM、NAND Flash、NOR Flash和PSRAM等存储器的连接。FSMC模块的框图如图2.23所示。
从图2.23可以看出,STM32F4的FSMC模块将外部设备分为两类:NOR Flash/PSRAM存储器、NAND Flash/PC存储卡,它们共用地址总线和数据总线,通过不同的片选信号来区分不同的设备。例如,当用到TFT LCD时使用FSMC_NE[4:1]作为片选信号,将TFT LCD当成PSRAM来控制。
5)TFT LCD作为PSRAM设备使用
为什么可以把TFT LCD当成PSRAM设备使用呢?外部PSRAM的控制信号一般有:地址总线(如A0~A18)、数据总线(如D0~D15)、写信号(WE)、读信号(OE)、片选信号(CS),如果PSRAM支持字节控制,那么还有UB/LB信号。而TFT LCD的信号包括:RS、D0~D15、WR、RD、CS、RST和BL等,其中在实际操作LCD时需要用到的只有RS、D0~D15、WR、RD和CS,其操作时序和PSRAM的控制完全类似,唯一不同就是TFT LCD有RS信号,但是没有地址总线。
TFT LCD通过RS信号来决定传输的数据是数据还是命令,本质上可以理解为一个地址信号,例如,把RS接在A0上,那么当FSMC控制器写地址0时,会使A0变为0,对TFT LCD来说,就是写命令;而当FSMC控制器写地址1时,A0将会变为1,对TFT LCD来说,就是写数据。这样就把数据和命令区分开了,它们其实就是对应PSRAM操作的两个连续地址。当然RS也可以接在其他地址线上。

图2.23 FSMC模块的框图
STM32F4的FSMC模块支持8、16、32位的数据宽度,智能台灯用到的TFT LCD是16位数据宽度,所以在设置时,选择16位就可以了。
6)FSMC模块的外部设备地址映像
STM32F4的FSMC模块将外部存储器划分为固定大小为256MB的4个存储块,FSMC存储块地址映像如图2.24所示。
从图2.24可以看出,FSMC模块总共管理1GB空间,拥有4个存储块(Bank),下述介绍仅讨论存储块1的相关配置,其他存储块的配置请参考芯片相关资料。
STM32F4的FSMC模块的存储块1(Bank1)被分为4个区,每个区管理64MB的空间,每个区都有独立的寄存器对所连接的存储器进行配置。Bank1的256MB空间由28根地址线(HADDR[27:0])寻址。
HADDR是内部AHB地址总线,其中HADDR[25:0]来自外部存储器地址FSMC_A[25:0],而HADDR[26:27]对4个区进行寻址,Bank1存储区选择表如表2.12所示。

图2.24 FSMC存储块地址映像
表2.12 Bank1存储区选择表

要特别注意HADDR[25:0]的对应关系,当Bank1接的是16位数据宽度的存储器时,HADDR[25:1]对应FSMC_A[24:0];当Bank1接的是8位数据宽度的存储器时,HADDR[25:0]对应FSMC_A[25:0]。
不论8位或16位数据宽度的设备,FSMC_A[0]永远接在外部设备地址A[0]。对于本章介绍的智能台灯,TFT LCD使用的是16位数据宽度,所以HADDR[0]并没有用到,只有HADDR[25:1]是有效的,因此HADDR[25:1]对应FSMC_A[24:0],相当于右移1位。另外,HADDR[27:26]的设置是不需要干预的,例如,当选择使用Bank1的第3区,即使用FSMC_NE3来连接外部设备时,即对应HADDR[27:26]=10,要做的就是配置对应第3区的寄存器组来适应外部设备即可。
2.2.2 HAL层驱动开发分析
1.温湿度传感器的驱动开发
1)硬件连接
HTU21D型温湿度传感器的硬件连接如图2.25所示。

图2.25 HTU21D型温湿度传感器的硬件连接
HTU21D型温湿度传感器通过I2C总线与微处理器进行通信,其SCL引脚连接微处理器的PA1引脚,SDA引脚连接微处理器的PA0引脚。
2)驱动函数分析
HTU21D型温湿度传感器是通过I2C总线来驱动的,驱动函数如表2.13所示。
表2.13 HTU21D型温湿度传感器的驱动函数

(1)HTU21D型温湿度传感器的初始化。代码如下:

(2)读取温度。微处理器通过I2C总线向HTU21D型温湿度传感器写入读取温度的指令,经过计算后可得到实际的温度。代码如下:

(3)读取湿度。微处理器通过I2C总线向HTU21D型温湿度传感器写入读取湿度的指令,经过计算后可得到实际的湿度。代码如下:

(4)温湿度数据的更新进程。代码如下:


(5)I2C总线的驱动。代码如下:





2.光照度传感器的驱动开发
1)硬件连接
BH1750FVI-TR型光照度传感器的硬件连接如图2.26所示。

图2.26 BH1750FVI-TR型光照度传感器的硬件连接
BH1750FVI-TR型光照度传感器通过I2C总线与微处理器进行通信,其SCL引脚连接微处理器的PB8引脚,SDA引脚连接微处理器的PB9引脚。
2)驱动函数分析
BH1750FVI-TR型光照度传感器是通过I2C总线来驱动的,其驱动函数如表2.14所示。
表2.14 光照度传感器的驱动函数

(1)BH1750FVI-TR型光照度传感器的初始化。代码如下:


(2)读取光照度。微处理器通过I2C总线向BH1750FVI-TR型光照度传感器写入读取光照度的指令,经过计算后可得到实际的光照度数据。代码如下:

3.LCD模块的驱动开发
1)硬件连接
LCD模块通过FSMC并口与微处理器进行通信,硬件连接如图2.27所示。

图2.27 LCD模块的硬件连接
2)驱动函数分析
本章介绍的智能台灯中的LCD模块采用ST7789型LCD,其驱动函数如表2.15所示。
表2.15 LCD模块的驱动函数

续表

相关的宏定义如下:

(1)初始化GPIO。代码如下:


(2)获取ST7789型LCD的ID。代码如下:

(3)初始化ST7789型LCD。代码如下:


(4)向ST7789型LCD写入数据。代码如下:

(5)设置光标位置。代码如下:

(6)设置LCD的显示窗口。代码如下:

(7)设置填充窗口。代码如下:

(8)在指定的位置描点。代码如下:


(9)读取点的RGB颜色。代码如下:

(10)设置填充的颜色。代码如下:

(11)设置填充的数据。代码如下:

2.2.3 HAL层驱动程序运行测试
在Contiki 3.0协议开发包的“contiki-3.0\zonesion”目录下创建“lamp”文件夹,将“SmartLamp-HAL”文件夹下“common”和“SmartLamp”复制到“lamp”文件夹中。打开“SmartLamp”中的工程进行编译,如图2.28所示。工程编译之后下载程序,进入调试模式。

图2.28 工程编译
1.温湿度传感器的驱动测试
在test_init进程中,当按键K1未按下时进入正常模式,调用StartProcesslist()函数处理各种进程,如图2.29所示。

图2.29 调用StartProcesslist()函数处理各种进程
在板载传感器处理进程onboard_sensors中设置断点,如图2.30所示,程序运行到断点处执行htu21d_update进程。

图2.30 在板载传感器处理进程onboard_sensors中设置断点
在htu21d_update进程中设置断点,如图2.31所示,将htu21dValue_t添加到Watch 1窗口,程序运行到断点处时继续运行一步,在Watch 1窗口中可以看到温度值。

图2.31 在htu21d_update进程中设置断点(用于查看温度)
在htu21d_update进程中继续设置断点,如图2.32所示,将htu21dValue_t添加到Watch 1窗口,程序运行到断点处时继续运行一步,在Watch 1窗口中可以看到温度值。
2.光照度传感器驱动测试
在test_init进程中,在未按下按键K1时会进入正常模式,并调用StartProcesslist()函数处理各种进程。进入guiProcess进程中,执行guiProcess_Init()函数,执行lightProcess进程,在该进程中设置断点,可获取光照度数据,将lightVal添加到Watch 1窗口,程序运行至断点处可以在Watch 1窗口中查看lightVal的值,如图2.33所示。

图2.32 在htu21d_update进程中设置断点(用于查看湿度)

图2.33 在lightProcess进程中设置断点并在Watch 1窗口中查看lightVal的值
3.LCD显示屏驱动测试
在main函数中执行test_init进程,在该进程中设置断点,如图2.34所示,按住K1按键,程序运行到断点处可进入test_plus进程。

图2.34 在test_init进程中设置断点
进入test_plus进程中设置断点,如图2.35所示,当程序运行到断点处时,执行test_ui进程。

图2.35 在test_plus进程中设置断点
在test_ui进程设置断点,如图2.36所示,当程序运行到断点处时,执行LCD初始化、清屏,然后更新屏幕显示。

图2.36 在test_ui进程中设置断点
进入testUIupdate()函数,在该函数中设置断点,如图2.37所示,当程序运行到断点处时,更新LCD的显示,LCD上显示的信息如图2.38所示。
在St7789_DrawPoint()函数中设置断点,如图2.39所示,该函数用来描点,程序运行运行到断点处时,在LCD上显示描点,如图2.40所示。

图2.37 在testUIupdate()函数中设置断点

图2.38 LCD上显示的信息

图2.39 在St7789_DrawPoint()函数中设置断点

图2.40 LCD上显示的描点
2.2.4 小结
通过本节的学习和实践,读者可以了解温湿度传感器、光照度传感器和LCD模块的原理及驱动程序的设计,并在智能台灯板卡上进行驱动程序测试,提高读者编写驱动程序的能力。