except SHT30Error as ex: # 捕获异常
print(ex)
RuntimeError
创建主函数
def main():
# 设置背光
Blk = 100
blk.duty(int((Blk/1000)*1023))
# 显示文字
font.text(lcd,"sht30 module",16,0,color=1,font_size = 16,reverse = False,clear = False,show = True,half_char = True,auto_wrap = True)
# 显示2个横线
lcd.hline(0,18,128,1)
lcd.hline(0,20,128,1)
lcd.show()
while True:
dispaly()
if name == "main": main()
演示效果:

**四、sht30驱动**
sht30.py
""" space.bilibili.com/1349435951?…
""" from machine import Pin,I2C import time
I2C address B 0x44 ADDR (pin 2) connected to GND
DEFAULT_I2C_ADDRESS = 0x44
class SHT30:
POLYNOMIAL = 0x131 # P(x) = x^8 + x^5 + x^4 + 1 = 100110001
ALERT_PENDING_MASK = 0x8000 # 15
HEATER_MASK = 0x2000 # 13
RH_ALERT_MASK = 0x0800 # 11
T_ALERT_MASK = 0x0400 # 10
RESET_MASK = 0x0010 # 4
CMD_STATUS_MASK = 0x0002 # 1
WRITE_STATUS_MASK = 0x0001 # 0
# MSB = 0x2C LSB = 0x06 Repeatability = High, Clock stretching = enabled
MEASURE_CMD = b'\x2C\x10'
STATUS_CMD = b'\xF3\x2D'
RESET_CMD = b'\x30\xA2'
CLEAR_STATUS_CMD = b'\x30\x41'
ENABLE_HEATER_CMD = b'\x30\x6D'
DISABLE_HEATER_CMD = b'\x30\x66'
def __init__(self, i2c=None, delta_temp=0, delta_hum=0, i2c_address=None):
if i2c is None:
raise ValueError('An I2C object is required.')
self.i2c = i2c
self.i2c_addr = i2c_address
self.set_delta(delta_temp, delta_hum)
time.sleep_ms(50)
def is_present(self):
"""
Return true if the sensor is correctly conneced, False otherwise
"""
return self.i2c_addr in self.i2c.scan()
def set_delta(self, delta_temp=0, delta_hum=0):
"""
Apply a delta value on the future measurements of temperature and/or humidity
The units are Celsius for temperature and percent for humidity (can be negative values)
"""
self.delta_temp = delta_temp
self.delta_hum = delta_hum
def _check_crc(self, data):
# calculates 8-Bit checksum with given polynomial
crc = 0xFF
for b in data[:-1]:
crc ^= b
for _ in range(8, 0, -1):
if crc & 0x80:
crc = (crc << 1) ^ SHT30.POLYNOMIAL
else:
crc <<= 1
crc_to_check = data[-1]
return crc_to_check == crc
def send_cmd(self, cmd_request, response_size=6, read_delay_ms=100):
"""
Send a command to the sensor and read (optionally) the response
The responsed data is validated by CRC
"""
try:
self.i2c.writeto(self.i2c_addr, cmd_request)
if not response_size:
return
time.sleep_ms(read_delay_ms)
data = self.i2c.readfrom(self.i2c_addr, response_size)
for i in range(response_size//3):
if not self._check_crc(data[i*3:(i+1)*3]): # pos 2 and 5 are CRC
raise SHT30Error(SHT30Error.CRC_ERROR)
if data == bytearray(response_size):
raise SHT30Error(SHT30Error.DATA_ERROR)
return data
except OSError:
raise SHT30Error(SHT30Error.BUS_ERROR)
except Exception as ex:
raise ex
def clear_status(self):
"""
Clear the status register
"""
return self.send_cmd(SHT30.CLEAR_STATUS_CMD, None)
def reset(self):
"""
Send a soft-reset to the sensor
"""
return self.send_cmd(SHT30.RESET_CMD, None)
def status(self, raw=False):
"""
Get the sensor status register.
It returns a int value or the bytearray(3) if raw==True
"""
data = self.send_cmd(SHT30.STATUS_CMD, 3, read_delay_ms=20)
if raw:
return data
status_register = data[0] << 8 | data[1]
return status_register
def measure(self, raw=False):
"""
If raw==True returns a bytearrya(6) with sensor direct measurement otherwise
It gets the temperature (T) and humidity (RH) measurement and return them.
The units are Celsius and percent
"""
data = self.send_cmd(SHT30.MEASURE_CMD, 6)
if raw:
return data
t_celsius = (((data[0] << 8 | data[1]) * 175) / 0xFFFF) - 45 + self.delta_temp
rh = (((data[3] << 8 | data[4]) * 100.0) / 0xFFFF) + self.delta_hum
return t_celsius, rh
def measure_int(self, raw=False):
"""
Get the temperature (T) and humidity (RH) measurement using integers.
If raw==True returns a bytearrya(6) with sensor direct measurement otherwise
It returns a tuple with 4 values: T integer, T decimal, H integer, H decimal
For instance to return T=24.0512 and RH= 34.662 This method will return
(24, 5, 34, 66) Only 2 decimal digits are returned, .05 becomes 5
Delta values are not applied in this method
The units are Celsius and percent.
"""
data = self.send_cmd(SHT30.MEASURE_CMD, 6)
if raw:
return data
aux = (data[0] << 8 | data[1]) * 175
t_int = (aux // 0xffff) - 45
t_dec = (aux % 0xffff * 100) // 0xffff
aux = (data[3] << 8 | data[4]) * 100
h_int = aux // 0xffff
h_dec = (aux % 0xffff * 100) // 0xffff
return t_int, t_dec, h_int, h_dec
class SHT30Error(Exception): """ Custom exception for errors on sensor management """ BUS_ERROR = 0x01 DATA_ERROR = 0x02 CRC_ERROR = 0x03
def __init__(self, error_code=None):
self.error_code = error_code
super().__init__(self.get_message())
def get_message(self):
if self.error_code == SHT30Error.BUS_ERROR:
return "Bus error"
elif self.error_code == SHT30Error.DATA_ERROR:
return "Data error"
elif self.error_code == SHT30Error.CRC_ERROR:
return "CRC error"
else:
return "Unknown error"
**五、LCD屏幕驱动**
st7567.py
#Micro Python ST7567 128*64 lcd driver #You may need to set elecvolt and regratio to drive your screen properly
from micropython import const import framebuf import time
SET_BIAS =const(0xA2)
POWER_CTRL=const(0x28)
SET_BOOST =const(0xF8)
SOFT_RST =const(0xE2)
SEG_DIR =const(0xA0)
COM_DIR =const(0xC0)
REGU_RATIO=const(0x20)
EVSET_MODE=const(0x81)
DISP_ONOFF=const(0xAE)
INV_DISP =const(0xA6)#0:normal display 1:inverse
ALL_PIX_ON=const(0xA4)
SRTLIN_SET=const(0x40)#407F
PAGEAD_SET=const(0xB0)#b0b8
COLHAD_SET=const(0x10)#0x100x1F
COLLAD_SET=const(0x00)#0x000x0F
class ST7567(framebuf.FrameBuffer): def init(self,spi,dc,cs,rst,elecvolt=0x1F,regratio=0x03,invX=0x00,invY=0x00,invdisp=0x00): dc.init(dc.OUT,value=0) cs.init(cs.OUT,value=1)#disable device port rst.init(rst.OUT,value=0)#reset device self.dc=dc self.cs=cs self.rst=rst self.spi=spi
self.EV=elecvolt
self.RR=regratio
self.invX=0x00 if(invX==0) else 0x01#0x00:MX=0 normal dir, 0x01:MX=1 reverse dir
self.invY=0x00 if(invY==0) else 0x08#0x00:MY=0 0x08:MY=1
self.invdisp=0x00 if(invdisp==0) else 0x01
self.buffer=bytearray(128*64//8)
super().__init__(self.buffer,128,64,framebuf.MONO_VLSB)
time.sleep_ms(1)
self.rst.value(1)
time.sleep_ms(1)#reset done
self.initscreen()
time.sleep_ms(50)
self.fill(0)
self.show()
self.write_cmd(DISP_ONOFF|0x01)#1:display on normal display mode
def initscreen(self):
self.write_cmd(SOFT_RST)#optional, I think it's useless
self.write_cmd(SET_BOOST)#set booster mode
self.write_cmd(0x00)#boost: 0x00:x4 0x01:x5
self.write_cmd(SET_BIAS|0x01)# 0:1/9 1:1/7
self.write_cmd(EVSET_MODE)#put device into EV setting mode
self.write_cmd(self.EV)#0x00~0x3F set contrast to 0x1f with last command
self.write_cmd(REGU_RATIO|self.RR)#0x00~0x07 3.0~6.5
self.write_cmd(POWER_CTRL|0x07)#7:{booster on,regulator on,follower on}
self.write_cmd(INV_DISP|self.invdisp)#normal display
self.write_cmd(ALL_PIX_ON|0x00)#0x00:normal display 0x01:all pixel on
self.write_cmd(SEG_DIR|self.invX)#0:MX=0 normal dir, 1:MX=1 reverse dir
self.write_cmd(COM_DIR|self.invY)#0x00:MY=0 0x08:MY=1 (may change to reverse y)
def write_cmd(self,cmd):
self.cs.value(0)#enable device port
self.dc.value(0)#cmd mode
self.spi.write(bytearray([cmd]))
#time.sleep_ms(1)
self.cs.value(1)#disable device port
def write_data(self,data):
self.cs.value(0)#enable device port
self.dc.value(1)#display data mode
self.spi.write(data)
#time.sleep_ms(1)
self.cs.value(1)#disable device port
def show(self):
self.write_cmd(DISP_ONOFF|0x00)
self.write_cmd(SRTLIN_SET|0x00)
colcnt=0
pagcnt=0
while (pagcnt<9):
self.write_cmd(PAGEAD_SET|pagcnt)
self.write_cmd(COLHAD_SET|0x00)
self.write_cmd(COLLAD_SET|0x00)
if(pagcnt<8):
self.write_data(self.buffer[(128*pagcnt):(128*pagcnt+128)])
else:
while (colcnt<128):
colcnt+=1
self.write_data(b"\x00")
pagcnt+=1
self.write_cmd(DISP_ONOFF|0x01)
def clear(self):
self.fill(0)
self.show()
**六、字体库**
ufont.py
version = 3
import time import struct
import framebuf
DEBUG = False
def timeit(f, *args, **kwargs): try: myname = str(f).split(' ')[1] except: myname = "UNKONW"
def new_func(*args, **kwargs):
if DEBUG:
try:
t = time.ticks_us()
result = f(*args, **kwargs)
delta = time.ticks_diff(time.ticks_us(), t)
print('Function {} Time = {:6.3f}ms'.format(myname, delta / 1000))
except AttributeError:
t = time.perf_counter_ns()
result = f(*args, **kwargs)
delta = time.perf_counter_ns() - t
print('Function {} Time = {:6.3f}ms'.format(myname, delta / 1000000))
return result
else:
return f(*args, **kwargs)
return new_func
class BMFont: @staticmethod def _list_to_byte(arr): b = 0 for a in arr: b = (b << 1) + a return bytes([b])
@timeit
def _bit_list_to_byte_data(self, bit_list):
"""将点阵转换为字节数据
Args:
bit_list:
Returns:
"""
byte_data = b''
for _col in bit_list:
for i in range(0, len(_col), 8):
byte_data += self._list_to_byte(_col[i:i + 8])
return byte_data
@timeit
def __init__(self, font_file):
self.font_file = font_file
self.font = open(font_file, "rb", buffering=0xff)
self.bmf_info = self.font.read(16)
if self.bmf_info[0:2] != b"BM":
raise TypeError("字体文件格式不正确: " + font_file)
self.version = self.bmf_info[2]
if self.version != 3:
raise TypeError("字体文件版本不正确: " + str(self.version))
self.map_mode = self.bmf_info[3] # 映射方式
self.start_bitmap = struct.unpack(">I", b'\x00' + self.bmf_info[4:7])[0] # 位图开始字节
self.font_size = self.bmf_info[7] # 字体大小
self.bitmap_size = self.bmf_info[8] # 点阵所占字节
@timeit
def _to_bit_list(self, byte_data, font_size, *, _height=None, _width=None):
"""将字节数据转换为点阵数据
Args:
byte_data: 字节数据
font_size: 字号大小
_height: 字体原高度
_width: 字体原宽度
Returns:
"""
_height = _height or self.font_size
_width = _width or self.bitmap_size // self.font_size * 8
new_bitarray = [[0 for j in range(font_size)] for i in range(font_size)]
for _col in range(len(new_bitarray)):
for _row in range(len(new_bitarray[_col])):
_index = int(_col / (font_size / _height)) * _width + int(_row / (font_size / _width))
new_bitarray[_col][_row] = byte_data[_index // 8] >> (7 - _index % 8) & 1
return new_bitarray
@timeit
def _color_render(self, bit_list, color):
"""将二值点阵图像转换为 RGB565 彩色字节图像
Args:
bit_list:
color:
Returns:
"""
color_array = b""
for _col in range(len(bit_list)):
for _row in range(len(bit_list)):
color_array += struct.pack("<H", color) if bit_list[_col][_row] else b'\x00\x00'
return color_array
@timeit
def _get_index(self, word):
"""获取索引
Args:
word: 字符
Returns:
"""
word_code = ord(word)
start = 0x10
end = self.start_bitmap
while start <= end:
mid = ((start + end) // 4) * 2
self.font.seek(mid, 0)
target_code = struct.unpack(">H", self.font.read(2))[0]
if word_code == target_code:
return (mid - 16) >> 1
elif word_code < target_code:
end = mid - 2
else:
start = mid + 2
return -1
@timeit
def get_bitmap(self, word):
"""获取点阵图
Args:
word: 字符
Returns:
bytes 字符点阵
"""
index = self._get_index(word)
if index == -1:
return b'\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x0f\xcf\xf3\xcf\xf3\xff\xf3\xff\xcf\xff?\xff?\xff\xff\xff' \
b'?\xff?\xff\xff\xff\xff'
self.font.seek(self.start_bitmap + index * self.bitmap_size, 0)
return self.font.read(self.bitmap_size)
@timeit
def text(self, display, string, x, y, color=1, *, font_size=None, reverse=False, clear=False, show=False,
half_char=True, auto_wrap=False, **kwargs):
"""通过显示屏显示文字
使用此函数显示文字,必须先确认显示对象是否继承与 framebuf.FrameBuffer。
收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!