├── README.md ├── boot.py ├── bufTest.py ├── connectwifi.py ├── font.py ├── font_new.py ├── image.png ├── localtime.py ├── ssd1306.py ├── xmlConvert.py └── 字模.jpg /README.md: -------------------------------------------------------------------------------- 1 | # -ESP32-Micropython-SSD1306-Chinese 2 | 在ESP32上用Micropython控制SSD1306显示中文,并获取天气信息和时间信息 3 | 4 | #### 文件介绍 5 | 6 | ##### 1.boot.py 7 | 8 | ​ 启动文件,esp32默认运行的文件 9 | 10 | ​ 文件中包括三个子线程,分别控制时间获取,天气信息获取和OLED显示 11 | 12 | ##### 2.connectwifi.py 13 | 14 | ​ Micropython官网上esp32连接wifi的例程,将其作为一个模块 15 | 16 | ##### 3.font.py 17 | 18 | ​ 一个存储字模的字典模块,字模为`pctolcd2002`软件生成的,具体配置在`字模.jpg`图片中 19 | 20 | ```python 21 | 0x00,0x3F,0x01,0x01,0x01,0x01,0xFF,0x01,0x02,0x02,0x04,0x04,0x08,0x10,0x20,0xC0, 22 | 0x00,0xF8,0x00,0x00,0x00,0x00,0xFE,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x08,0x06,天0 23 | ``` 24 | 25 | ​ 然后通过一个python程序进行格式化处理 26 | 27 | ```python 28 | def single_word(i): 29 | lattice = i[:-2] # 获取数据 30 | word = i[-2:-1] # 获取文本 31 | print(word) 32 | try: 33 | # 进行编码 34 | utf = word.encode('utf-8') 35 | byte_utf = 0x00 36 | byte_utf |= utf[0] << 16 37 | byte_utf |= utf[1] << 8 38 | byte_utf |= utf[2] 39 | # 进行数据保存 40 | result = '{}:\n [{}], #{}\n'.format(hex(byte_utf), lattice, word) 41 | print(result) 42 | 43 | except IndexError: 44 | print(word) 45 | if __name__ == '__main__': 46 | signle_word('''0x00,0x3F,0x01,0x01,0x01,0x01,0xFF,0x01,0x02,0x02,0x04,0x04,0x08,0x10,0x20,0xC0, 47 | 0x00,0xF8,0x00,0x00,0x00,0x00,0xFE,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x08,0x06,天0''') 48 | ``` 49 | 50 | ​ 得到结果,将结果作为字典的键值对放入`font.py`中 51 | 52 | ```py 53 | 0xe5a4a9: [0x00,0x3F,0x01,0x01,0x01,0x01,0xFF,0x01,0x02,0x02,0x04,0x04,0x08,0x10,0x20,0xC0, 54 | 0x00,0xF8,0x00,0x00,0x00,0x00,0xFE,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x08,0x06,], #天 55 | ``` 56 | 57 | ##### 4.font_new.py 58 | 59 | ​ 同样是字模模块,对`font.py`内的字模进行进一步处理,使用不同的方法进行显示 60 | 61 | ​ 处理方法如下: 62 | 63 | ```python 64 | byte3 = { 65 | 0xe998b5: 66 | [0x00,0x7C,0x44,0x4B,0x48,0x50,0x49,0x49,0x44,0x44,0x44,0x6B,0x50,0x40,0x40,0x40, 67 | 0x40,0x40,0x40,0xFE,0x80,0xA0,0x20,0xFC,0x20,0x20,0x20,0xFE,0x20,0x20,0x20,0x20,], #阵 68 | } 69 | #在第一种数据创建的方法,创建第二种数据,用framebuf显示中文的数据 70 | keys = byte3.keys() 71 | value = byte3.values() 72 | #获取数据的键值对 73 | #print(keys,value) 74 | dict_new = {} 75 | #由于使用字模生成器生成的字模数据,这个数据将字模分为两个部分,先显示汉字的左半部分,然后是右半部分 76 | #然而在第二种用blit显示,不会一半一半的显示,而是直接将整个汉字写入缓冲区,因此需要进行处理 77 | for key in keys: 78 | l1 = [] 79 | l2 = [] 80 | print(key) 81 | byte_list = byte3[key] 82 | s = '' 83 | n = 0 84 | print(len(byte_list)) 85 | for i in byte_list: 86 | if n < 16: 87 | l1.append(i) 88 | else: 89 | l2.append(i) 90 | n += 1 91 | l3 = [] 92 | 93 | # print(l1, l2) 94 | for i in range(len(l1)): 95 | l3.append(l1[i]) 96 | l3.append(l2[i]) 97 | #print(l3) 98 | 99 | for i in l3: 100 | temp = hex(i) 101 | temp = temp[1:] 102 | #print(len(temp)) 103 | if len(temp) < 3: 104 | temp = temp[0] + '0' + temp[1] 105 | temp = '\\' + temp 106 | #print(temp) 107 | s += temp 108 | s = 'b\'' + s + '\'' 109 | print(s) 110 | dict_new[key] = s 111 | 112 | print(dict_new) 113 | 114 | new_str_dict = str(dict_new).replace('\\\\','\\') 115 | new_str_dict = new_str_dict.replace("\"",'') 116 | print(new_str_dict) 117 | ``` 118 | 119 | 处理结果: 120 | 121 | ```python 122 | {15308981: b'\x00\x40\x7c\x40\x44\x40\x4b\xfe\x48\x80\x50\xa0\x49\x20\x49\xfc\x44\x20\x44\x20\x44\x20\x6b\xfe\x50\x20\x40\x20\x40\x20\x40\x20'} 123 | ``` 124 | 125 | ​ 这样就得到了`font_new.py`中的内容 126 | 127 | ##### 5.localtime.py 128 | 129 | ​ 由于esp32初始化时时间从零开始,所以需要一个校时模块 130 | 131 | ##### 6.ssd1306.py 132 | 133 | ​ 模块主要内容为micropython官方源码,然后添加显示中文的功能,显示中文有两种方法 134 | 135 | ​ 方法一: 136 | 137 | ​ 利用官方模块的`pixel`方法进行像素的填充 138 | 139 | ```python 140 | def draw_chinese(ch_str,x_axis,y_axis): 141 | offset_=0 142 | y_axis=y_axis*16#中文高度一行占8个 143 | x_axis=(x_axis*16)#中文宽度占16个 144 | for k in ch_str: 145 | code = 0x00#将中文转成16进制编码 146 | data_code = k.encode("utf-8") 147 | code |= data_code[0]<<16 148 | code |= data_code[1]<<8 149 | code |= data_code[2] 150 | print(hex(code)) 151 | byte_data=font.byte2.get(code) 152 | for y in range(0,16): 153 | a_=bin(byte_data[y]).replace('0b','') 154 | while len(a_)<8: 155 | a_='0'+a_ 156 | b_=bin(byte_data[y+16]).replace('0b','') 157 | while len(b_)<8: 158 | b_='0'+b_ 159 | for x in range(0,8): 160 | self.pixel(x_axis+x-offset_,y+y_axis,int(a_[x]))#文字的上半部分 161 | self.pixel(x_axis+x+8-offset_,y+y_axis,int(b_[x]))#文字的下半部分 162 | 163 | offset_+=16 164 | ``` 165 | 166 | ​ 方法二: 167 | 168 | ​ 观察到整个SSD1306类继承自`framebuf.FrameBuffer`,所以可通过创建`framebuf`并通过`FrameBuffer`类中的`blit`方法进行缓冲区写入 169 | 170 | ```python 171 | def draw_chinese_fast(self,ch_str,x_axis,y_axis): 172 | offset_=0 173 | y_axis=y_axis*16#中文高度一行占8个 174 | x_axis=(x_axis*16)#中文宽度占16个 175 | for k in ch_str: 176 | code = 0x00#将中文转成16进制编码 177 | data_code = k.encode("utf-8") 178 | code |= data_code[0]<<16 179 | code |= data_code[1]<<8 180 | code |= data_code[2] 181 | 182 | try: 183 | byte_data=font_new.byte2.get(code) 184 | byte = bytearray(byte_data) 185 | buf = framebuf.FrameBuffer(byte,16,16,framebuf.MONO_HLSB) 186 | self.blit(buf,x_axis+offset_,y_axis) 187 | except: 188 | print(code) 189 | 190 | offset_+=16 191 | ``` 192 | 193 | 总结,直接进行缓冲区写入速度非常快,可以保证实时刷新oled显示 194 | 195 | ##### 7.xmlConvert.py 196 | 197 | ​ 对天气信息获取为xml格式文档,对文档中的数据进行处理,提取需要的数据 198 | -------------------------------------------------------------------------------- /boot.py: -------------------------------------------------------------------------------- 1 | import connectwifi,localtime 2 | import _thread,time 3 | import machine 4 | from machine import Pin, SPI 5 | import ssd1306 6 | import urequests 7 | import xmlConvert 8 | import font 9 | 10 | ts = '' 11 | ts2= '' 12 | weather_1='' 13 | tem_1='' 14 | tem_2='' 15 | 16 | debug = False 17 | 18 | lock = _thread.allocate_lock() 19 | def time_thread(): 20 | localtime.sync_ntp() 21 | while True: 22 | global ts 23 | global ts2 24 | 25 | t = localtime.getLocalTime() 26 | if lock.locked(): 27 | pass 28 | else: 29 | lock.acquire() 30 | ts = '{}-{}-{}'.format(t[0],t[1],t[2]) 31 | s = t[6] 32 | m = t[5] 33 | h = t[4] 34 | if int(s)<10: 35 | s = '0{}'.format(s) 36 | if int(m)<10: 37 | m = '0{}'.format(m) 38 | if int(h)<10: 39 | h = '0{}'.format(h) 40 | ts2 = '{}:{}:{}'.format(h,m,s) 41 | lock.release() 42 | global debug 43 | if debug: 44 | break 45 | print('结束time_thread') 46 | 47 | def weather_thread(): 48 | url = 'http://flash.weather.com.cn/wmaps/xml/jixi.xml' 49 | global weather_1 50 | global weather_2 51 | global tem_1 52 | global tem_2 53 | while True: 54 | response = urequests.get(url) 55 | xml = (response.content).decode('utf-8') 56 | result = xmlConvert.xml2DictInList(xml) 57 | 58 | for i in result: 59 | if 'cityname' in i.keys(): 60 | if i['cityname'] == '密山市': 61 | if lock.locked(): 62 | pass 63 | else: 64 | lock.acquire() 65 | weather_1 = i['stateDetailed']#天气 66 | tem_1 = i['tem1']#高 67 | tem_2 = i['tem2']#低 68 | lock.release() 69 | print('天气:{}'.format(i['stateDetailed'])) 70 | #print("气温:{}℃ ~ {}℃".format(i['tem2'],i['tem1'])) 71 | #print('当前气温:{}℃,湿度:{}'.format(i['temNow'],i['humidity'])) 72 | #print('风力:{}'.format(i['windState'])) 73 | 74 | 75 | 76 | global debug 77 | if debug: 78 | break 79 | time.sleep(1800) 80 | print('结束weather_thread') 81 | def lcd_thread(): 82 | 83 | spi = SPI(1, 10000000, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) 84 | display = ssd1306.SSD1306_SPI(128,64,spi,Pin(25),Pin(26),Pin(27)) 85 | display.poweron() 86 | display.init_display() 87 | 88 | global ts 89 | global ts2 90 | global weather_1 91 | global tem_1 92 | global tem_2 93 | 94 | while True: 95 | #time.sleep(1) 96 | display.text(ts,1,1) 97 | display.text(ts2,1,8) 98 | display.draw_chinese_fast('密山',5,0) 99 | display.draw_chinese_fast('温度',0,1) 100 | display.draw_chinese_fast('天气',0,2) 101 | display.draw_chinese_fast(weather_1,2,2) 102 | t1 = '{} C'.format(tem_1) 103 | t2 = '{} C'.format(tem_2) 104 | print(t1,t2) 105 | display.text(t1,40,16) 106 | display.text(t2,40,24) 107 | 108 | display.show() 109 | 110 | time.sleep(0.1) 111 | 112 | global debug 113 | if debug: 114 | break 115 | display.fill(0) 116 | print('结束lcd_thread') 117 | if __name__ =='__main__': 118 | connectwifi.do_connect() 119 | _thread.start_new_thread(lcd_thread,()) 120 | _thread.start_new_thread(time_thread,()) 121 | 122 | _thread.start_new_thread(weather_thread,()) 123 | 124 | 125 | -------------------------------------------------------------------------------- /bufTest.py: -------------------------------------------------------------------------------- 1 | import machine 2 | from machine import Pin, SPI 3 | import ssd1306 4 | import framebuf,time 5 | import font_new 6 | 7 | spi = SPI(1, 10000000, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) 8 | display = ssd1306.SSD1306_SPI(128,64,spi,Pin(25),Pin(26),Pin(27)) 9 | display.poweron() 10 | display.init_display() 11 | 12 | byte = b'11111111111111110000000000000000111111111111111100000000000000001111111111111111000000000000000011111111111111110000000000000000' 13 | 14 | byte = bytearray(byte) 15 | print(byte) 16 | buf = framebuf.FrameBuffer(byte,128,1,framebuf.MONO_VLSB) 17 | print(buf) 18 | display.fill(0) 19 | display.blit(buf,0,0) 20 | display.blit(buf,0,10) 21 | display.fill(0) 22 | 23 | byte_list = [0x01,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x02,0x02,0x04,0x04,0x08,0x10,0x20,0xC0, 24 | 0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x08,0x06,] 25 | n=0 26 | start = time.ticks_ms() 27 | for i in byte_list: 28 | s = '{:08b}'.format(i) 29 | byte = bytes(s.encode('utf-8')) 30 | byte = bytearray(byte) 31 | #print(byte) 32 | buf = framebuf.FrameBuffer(byte,8,1,framebuf.MONO_VLSB) 33 | if n<17: 34 | display.blit(buf,0,n) 35 | else: 36 | display.blit(buf,8,n-16) 37 | n+=1 38 | print(time.ticks_diff(start,time.ticks_ms())) 39 | display.show() 40 | 41 | display.fill(0) 42 | k='雨' 43 | code = 0x00#将中文转成16进制编码 44 | data_code = k.encode("utf-8") 45 | code |= data_code[0]<<16 46 | code |= data_code[1]<<8 47 | code |= data_code[2] 48 | print(code) 49 | byte_data=font_new.byte2.get(code) 50 | 51 | start = time.ticks_ms() 52 | byte = bytearray(byte_data) 53 | buf = framebuf.FrameBuffer(byte,16,16,framebuf.MONO_HLSB) 54 | display.blit(buf,0,0) 55 | print(time.ticks_diff(start,time.ticks_ms())) 56 | display.show() 57 | display.fill(0) 58 | display.draw_chinese_fast('小雨',2,0) 59 | display.show() 60 | -------------------------------------------------------------------------------- /connectwifi.py: -------------------------------------------------------------------------------- 1 | def do_connect(): 2 | import network 3 | wlan = network.WLAN(network.STA_IF) 4 | wlan.active(True) 5 | if not wlan.isconnected(): 6 | print('connecting to network...') 7 | wlan.connect('Tp-158327', 'gp2018.11.14.') 8 | while not wlan.isconnected(): 9 | pass 10 | print('network config:', wlan.ifconfig()) 11 | -------------------------------------------------------------------------------- /font.py: -------------------------------------------------------------------------------- 1 | 2 | byte2 = { 3 | 4 | 0xe69ab4: 5 | [0x1F,0x10,0x1F,0x10,0x1F,0x08,0x7F,0x08,0xFF,0x08,0x31,0xC9,0x05,0x09,0x15,0x22, 6 | 0xF0,0x10,0xF0,0x10,0xF0,0x20,0xFC,0x20,0xFE,0x20,0x18,0x26,0x40,0x20,0x10,0x08,], #暴 7 | 0xe58c97: 8 | [0x04,0x04,0x04,0x04,0x04,0x7C,0x04,0x04,0x04,0x04,0x04,0x04,0x1C,0xE4,0x44,0x04, 9 | 0x40,0x40,0x40,0x44,0x48,0x50,0x60,0x40,0x40,0x40,0x40,0x42,0x42,0x42,0x3E,0x00,], #北 10 | 0xe5a4a7: 11 | [0x01,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x02,0x02,0x04,0x04,0x08,0x10,0x20,0xC0, 12 | 0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x08,0x06,], #大 13 | 0xe4b89c: 14 | [0x02,0x02,0x02,0x7F,0x04,0x09,0x11,0x21,0x3F,0x01,0x09,0x11,0x21,0x41,0x05,0x02, 15 | 0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0xF8,0x00,0x20,0x10,0x08,0x04,0x00,0x00,], #东 16 | 0xe5baa6: 17 | [0x01,0x00,0x3F,0x22,0x22,0x3F,0x22,0x22,0x23,0x20,0x2F,0x24,0x42,0x41,0x86,0x38, 18 | 0x00,0x80,0xFE,0x20,0x20,0xFC,0x20,0x20,0xE0,0x00,0xF0,0x10,0x20,0xC0,0x30,0x0E,], #度 19 | 0xe9a38e: 20 | [0x00,0x3F,0x20,0x20,0x28,0x24,0x22,0x22,0x21,0x21,0x22,0x22,0x24,0x48,0x40,0x80, 21 | 0x00,0xF0,0x10,0x10,0x50,0x50,0x90,0x90,0x10,0x10,0x90,0x92,0x4A,0x4A,0x06,0x02,], #风 22 | 0xe9b8a1: 23 | [0x00,0x00,0x00,0xFC,0x04,0x04,0x48,0x28,0x10,0x10,0x28,0x24,0x45,0x80,0x00,0x00, 24 | 0x20,0x40,0xFC,0x84,0xA4,0x84,0x94,0x88,0x80,0xFE,0x02,0x02,0xFA,0x02,0x14,0x08,], #鸡 25 | 0xe7baa7: 26 | [0x10,0x13,0x20,0x20,0x48,0xF8,0x10,0x20,0x41,0xF9,0x41,0x01,0x1A,0xE2,0x44,0x01, 27 | 0x00,0xFC,0x84,0x88,0x88,0x90,0x9C,0x84,0x44,0x44,0x28,0x28,0x10,0x28,0x44,0x82,], #级 28 | 0xe58a9b: 29 | [0x02,0x02,0x02,0x02,0x7F,0x02,0x02,0x02,0x02,0x04,0x04,0x08,0x08,0x10,0x20,0x40, 30 | 0x00,0x00,0x00,0x00,0xF8,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x88,0x50,0x20,], #力 31 | 0xe5af86: 32 | [0x02,0x01,0x7F,0x40,0x82,0x09,0x28,0x4B,0x1C,0xE7,0x01,0x21,0x21,0x21,0x3F,0x00, 33 | 0x00,0x00,0xFE,0x02,0x24,0x40,0x88,0x14,0x10,0xF0,0x00,0x08,0x08,0x08,0xF8,0x08,], #密 34 | 0xe58d97: 35 | [0x01,0x01,0xFF,0x01,0x01,0x7F,0x48,0x44,0x4F,0x41,0x41,0x5F,0x41,0x41,0x41,0x40, 36 | 0x00,0x00,0xFE,0x00,0x00,0xFC,0x24,0x44,0xE4,0x04,0x04,0xF4,0x04,0x04,0x14,0x08,], #南 37 | 0xe6b094: 38 | [0x10,0x10,0x3F,0x20,0x4F,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 39 | 0x00,0x00,0xFC,0x00,0xF0,0x00,0xF0,0x10,0x10,0x10,0x10,0x10,0x0A,0x0A,0x06,0x02,], #气 40 | 0xe699b4: 41 | [0x00,0x00,0x7B,0x48,0x49,0x48,0x4B,0x78,0x49,0x49,0x49,0x49,0x79,0x49,0x01,0x01, 42 | 0x20,0x20,0xFE,0x20,0xFC,0x20,0xFE,0x00,0xFC,0x04,0xFC,0x04,0xFC,0x04,0x14,0x08,], #晴 43 | 0xe5b1b1: 44 | [0x01,0x01,0x01,0x01,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x3F,0x00,0x00, 45 | 0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xF8,0x08,0x00,], #山 46 | 0xe5b882: 47 | [0x02,0x01,0x00,0x7F,0x01,0x01,0x01,0x3F,0x21,0x21,0x21,0x21,0x21,0x21,0x01,0x01, 48 | 0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xF8,0x08,0x08,0x08,0x08,0x28,0x10,0x00,0x00,], #市 49 | 0xe5a4a9: 50 | [0x00,0x3F,0x01,0x01,0x01,0x01,0xFF,0x01,0x02,0x02,0x04,0x04,0x08,0x10,0x20,0xC0, 51 | 0x00,0xF8,0x00,0x00,0x00,0x00,0xFE,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x08,0x06,], #天 52 | 0xe5beae: 53 | [0x11,0x15,0x25,0x45,0x97,0x10,0x20,0x6F,0xA0,0x27,0x24,0x24,0x24,0x24,0x28,0x30, 54 | 0x08,0x48,0x48,0x50,0xDE,0x24,0x14,0xD4,0x14,0x94,0x94,0xA8,0xC8,0x94,0x14,0x22,], #微 55 | 0xe6b8a9: 56 | [0x00,0x23,0x12,0x12,0x83,0x42,0x42,0x13,0x10,0x27,0xE4,0x24,0x24,0x24,0x2F,0x00, 57 | 0x00,0xF8,0x08,0x08,0xF8,0x08,0x08,0xF8,0x00,0xFC,0xA4,0xA4,0xA4,0xA4,0xFE,0x00,], #温 58 | 0xe99bbe: 59 | [0x3F,0x01,0x7F,0x41,0x9D,0x01,0x1D,0x04,0x0F,0x14,0x03,0x1C,0xE2,0x0F,0x04,0x18, 60 | 0xF8,0x00,0xFE,0x02,0x74,0x00,0x70,0x00,0xE0,0x40,0x80,0x70,0x0E,0xE0,0x20,0x60,], #雾 61 | 0xe8a5bf: 62 | [0x00,0xFF,0x04,0x04,0x04,0x3F,0x24,0x24,0x24,0x24,0x28,0x30,0x20,0x20,0x3F,0x20, 63 | 0x00,0xFE,0x40,0x40,0x40,0xF8,0x48,0x48,0x48,0x48,0x38,0x08,0x08,0x08,0xF8,0x08,], #西 64 | 0xe5b08f: 65 | [0x01,0x01,0x01,0x01,0x01,0x11,0x11,0x11,0x21,0x21,0x41,0x81,0x01,0x01,0x05,0x02, 66 | 0x00,0x00,0x00,0x00,0x00,0x10,0x08,0x04,0x04,0x02,0x02,0x02,0x00,0x00,0x00,0x00,], #小 67 | 0xe99baa: 68 | [0x3F,0x01,0x7F,0x41,0x9D,0x01,0x1D,0x00,0x3F,0x00,0x00,0x1F,0x00,0x00,0x3F,0x00, 69 | 0xF8,0x00,0xFE,0x02,0x74,0x00,0x70,0x00,0xF8,0x08,0x08,0xF8,0x08,0x08,0xF8,0x08,], #雪 70 | 0xe99ba8: 71 | [0x00,0xFF,0x01,0x01,0x01,0x7F,0x41,0x41,0x49,0x45,0x41,0x49,0x45,0x41,0x41,0x40, 72 | 0x00,0xFE,0x00,0x00,0x00,0xFC,0x04,0x04,0x44,0x24,0x04,0x44,0x24,0x04,0x14,0x08,], #雨 73 | 0xe4b8ad: 74 | [0x01,0x01,0x01,0x01,0x3F,0x21,0x21,0x21,0x21,0x21,0x3F,0x21,0x01,0x01,0x01,0x01, 75 | 0x00,0x00,0x00,0x00,0xF8,0x08,0x08,0x08,0x08,0x08,0xF8,0x08,0x00,0x00,0x00,0x00,], #中 76 | 0xe8bdac: 77 | [0x20,0x20,0x20,0xFD,0x40,0x50,0x93,0xFC,0x10,0x11,0x1C,0xF0,0x50,0x10,0x10,0x10, 78 | 0x20,0x20,0x20,0xFC,0x20,0x40,0xFE,0x40,0x80,0xFC,0x04,0x88,0x50,0x20,0x10,0x10,], #转 79 | 80 | } 81 | 82 | -------------------------------------------------------------------------------- /font_new.py: -------------------------------------------------------------------------------- 1 | byte2 ={15112884: b'\x1f\xf0\x10\x10\x1f\xf0\x10\x10\x1f\xf0\x08\x20\x7f\xfc\x08\x20\xff\xfe\x08\x20\x31\x18\xc9\x26\x05\x40\x09\x20\x15\x10\x22\x08', 15043735: b'\x04\x40\x04\x40\x04\x40\x04\x44\x04\x48\x7c\x50\x04\x60\x04\x40\x04\x40\x04\x40\x04\x40\x04\x42\x1c\x42\xe4\x42\x44\x3e\x04\x00', 15049895: b'\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\xff\xfe\x01\x00\x01\x00\x02\x80\x02\x80\x04\x40\x04\x40\x08\x20\x10\x10\x20\x08\xc0\x06', 14989468: b'\x02\x00\x02\x00\x02\x00\x7f\xfc\x04\x00\x09\x00\x11\x00\x21\x00\x3f\xf8\x01\x00\x09\x20\x11\x10\x21\x08\x41\x04\x05\x00\x02\x00', 15055526: b'\x01\x00\x00\x80\x3f\xfe\x22\x20\x22\x20\x3f\xfc\x22\x20\x22\x20\x23\xe0\x20\x00\x2f\xf0\x24\x10\x42\x20\x41\xc0\x86\x30\x38\x0e', 15311758: b'\x00\x00\x3f\xf0\x20\x10\x20\x10\x28\x50\x24\x50\x22\x90\x22\x90\x21\x10\x21\x10\x22\x90\x22\x92\x24\x4a\x48\x4a\x40\x06\x80\x02', 15317153: b'\x00\x20\x00\x40\x00\xfc\xfc\x84\x04\xa4\x04\x84\x48\x94\x28\x88\x10\x80\x10\xfe\x28\x02\x24\x02\x45\xfa\x80\x02\x00\x14\x00\x08', 15186599: b'\x10\x00\x13\xfc\x20\x84\x20\x88\x48\x88\xf8\x90\x10\x9c\x20\x84\x41\x44\xf9\x44\x41\x28\x01\x28\x1a\x10\xe2\x28\x44\x44\x01\x82', 15043227: b'\x02\x00\x02\x00\x02\x00\x02\x00\x7f\xf8\x02\x08\x02\x08\x02\x08\x02\x08\x04\x08\x04\x08\x08\x08\x08\x08\x10\x88\x20\x50\x40\x20', 15052678: b'\x02\x00\x01\x00\x7f\xfe\x40\x02\x82\x24\x09\x40\x28\x88\x4b\x14\x1c\x10\xe7\xf0\x01\x00\x21\x08\x21\x08\x21\x08\x3f\xf8\x00\x08', 15043991: b'\x01\x00\x01\x00\xff\xfe\x01\x00\x01\x00\x7f\xfc\x48\x24\x44\x44\x4f\xe4\x41\x04\x41\x04\x5f\xf4\x41\x04\x41\x04\x41\x14\x40\x08', 15118484: b'\x10\x00\x10\x00\x3f\xfc\x20\x00\x4f\xf0\x80\x00\x3f\xf0\x00\x10\x00\x10\x00\x10\x00\x10\x00\x10\x00\x0a\x00\x0a\x00\x06\x00\x02', 15112628: b'\x00\x20\x00\x20\x7b\xfe\x48\x20\x49\xfc\x48\x20\x4b\xfe\x78\x00\x49\xfc\x49\x04\x49\xfc\x49\x04\x79\xfc\x49\x04\x01\x14\x01\x08', 15053233: b'\x01\x00\x01\x00\x01\x00\x01\x00\x21\x08\x21\x08\x21\x08\x21\x08\x21\x08\x21\x08\x21\x08\x21\x08\x21\x08\x3f\xf8\x00\x08\x00\x00', 15054978: b'\x02\x00\x01\x00\x00\x00\x7f\xfc\x01\x00\x01\x00\x01\x00\x3f\xf8\x21\x08\x21\x08\x21\x08\x21\x08\x21\x28\x21\x10\x01\x00\x01\x00', 15049897: b'\x00\x00\x3f\xf8\x01\x00\x01\x00\x01\x00\x01\x00\xff\xfe\x01\x00\x02\x80\x02\x80\x04\x40\x04\x40\x08\x20\x10\x10\x20\x08\xc0\x06', 15056558: b'\x11\x08\x15\x48\x25\x48\x45\x50\x97\xde\x10\x24\x20\x14\x6f\xd4\xa0\x14\x27\x94\x24\x94\x24\xa8\x24\xc8\x24\x94\x28\x14\x30\x22', 15120553: b'\x00\x00\x23\xf8\x12\x08\x12\x08\x83\xf8\x42\x08\x42\x08\x13\xf8\x10\x00\x27\xfc\xe4\xa4\x24\xa4\x24\xa4\x24\xa4\x2f\xfe\x00\x00', 15309758: b'\x3f\xf8\x01\x00\x7f\xfe\x41\x02\x9d\x74\x01\x00\x1d\x70\x04\x00\x0f\xe0\x14\x40\x03\x80\x1c\x70\xe2\x0e\x0f\xe0\x04\x20\x18\x60', 15246783: b'\x00\x00\xff\xfe\x04\x40\x04\x40\x04\x40\x3f\xf8\x24\x48\x24\x48\x24\x48\x24\x48\x28\x38\x30\x08\x20\x08\x20\x08\x3f\xf8\x20\x08', 15052943: b'\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x11\x10\x11\x08\x11\x04\x21\x04\x21\x02\x41\x02\x81\x02\x01\x00\x01\x00\x05\x00\x02\x00', 15309738: b'\x3f\xf8\x01\x00\x7f\xfe\x41\x02\x9d\x74\x01\x00\x1d\x70\x00\x00\x3f\xf8\x00\x08\x00\x08\x1f\xf8\x00\x08\x00\x08\x3f\xf8\x00\x08', 15309736: b'\x00\x00\xff\xfe\x01\x00\x01\x00\x01\x00\x7f\xfc\x41\x04\x41\x04\x49\x44\x45\x24\x41\x04\x49\x44\x45\x24\x41\x04\x41\x14\x40\x08', 14989485: b'\x01\x00\x01\x00\x01\x00\x01\x00\x3f\xf8\x21\x08\x21\x08\x21\x08\x21\x08\x21\x08\x3f\xf8\x21\x08\x01\x00\x01\x00\x01\x00\x01\x00', 2 | 15252908: b'\x20\x20\x20\x20\x20\x20\xfd\xfc\x40\x20\x50\x40\x93\xfe\xfc\x40\x10\x80\x11\xfc\x1c\x04\xf0\x88\x50\x50\x10\x20\x10\x10\x10\x10', 3 | 15049882:b'\x02\x00\x02\x00\x07\xf0\x08\x20\x38\x40\x04\x80\x03\x40\x0c\x80\x71\xf8\x02\x08\x0c\x10\x32\x20\x01\x40\x01\x80\x0e\x00\x70\x00', 4 | 14989969:b'\x00\x00\x3f\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x02\x00\x04\x00\x04\x00\x08\x40\x10\x20\x20\x10\x7f\xf8\x20\x08\x00\x08', 5 | 15308981:b'\x00\x40\x7c\x40\x44\x40\x4b\xfe\x48\x80\x50\xa0\x49\x20\x49\xfc\x44\x20\x44\x20\x44\x20\x6b\xfe\x50\x20\x40\x20\x40\x20\x40\x20', 6 | } 7 | 8 | 9 | -------------------------------------------------------------------------------- /image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beijizhidian/-ESP32-Micropython-SSD1306-Chinese/41d8d9930fc5f3ab6324b78fb218e49fbaa81a22/image.png -------------------------------------------------------------------------------- /localtime.py: -------------------------------------------------------------------------------- 1 | import ntptime,time 2 | from machine import RTC 3 | def sync_ntp(): 4 | ntptime.NTP_DELTA = 3155644800 # 可选 UTC+8偏移时间(秒),不设置就是UTC0 5 | ntptime.host = 'ntp1.aliyun.com' # 可选,ntp服务器,默认是"pool.ntp.org" 6 | ntptime.settime() # 修改设备时间,到这就已经设置好了 7 | 8 | def getLocalTime(): 9 | #sync_ntp() 10 | rtc = RTC() 11 | #print(rtc.datetime()) 12 | return rtc.datetime() 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ssd1306.py: -------------------------------------------------------------------------------- 1 | # MicroPython SSD1306 OLED driver, I2C and SPI interfaces 2 | 3 | from micropython import const 4 | import framebuf 5 | import font 6 | import font_new 7 | 8 | # register definitions 9 | SET_CONTRAST = const(0x81) 10 | SET_ENTIRE_ON = const(0xa4) 11 | SET_NORM_INV = const(0xa6) 12 | SET_DISP = const(0xae) 13 | SET_MEM_ADDR = const(0x20) 14 | SET_COL_ADDR = const(0x21) 15 | SET_PAGE_ADDR = const(0x22) 16 | SET_DISP_START_LINE = const(0x40) 17 | SET_SEG_REMAP = const(0xa0) 18 | SET_MUX_RATIO = const(0xa8) 19 | SET_COM_OUT_DIR = const(0xc0) 20 | SET_DISP_OFFSET = const(0xd3) 21 | SET_COM_PIN_CFG = const(0xda) 22 | SET_DISP_CLK_DIV = const(0xd5) 23 | SET_PRECHARGE = const(0xd9) 24 | SET_VCOM_DESEL = const(0xdb) 25 | SET_CHARGE_PUMP = const(0x8d) 26 | 27 | # Subclassing FrameBuffer provides support for graphics primitives 28 | # http://docs.micropython.org/en/latest/pyboard/library/framebuf.html 29 | class SSD1306(framebuf.FrameBuffer): 30 | def __init__(self, width, height, external_vcc): 31 | self.width = width 32 | self.height = height 33 | self.external_vcc = external_vcc 34 | self.pages = self.height // 8 35 | self.buffer = bytearray(self.pages * self.width) 36 | super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB) 37 | self.init_display() 38 | 39 | def init_display(self): 40 | for cmd in ( 41 | SET_DISP | 0x00, # off 42 | # address setting 43 | SET_MEM_ADDR, 0x00, # horizontal 44 | # resolution and layout 45 | SET_DISP_START_LINE | 0x00, 46 | SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 47 | SET_MUX_RATIO, self.height - 1, 48 | SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 49 | SET_DISP_OFFSET, 0x00, 50 | SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12, 51 | # timing and driving scheme 52 | SET_DISP_CLK_DIV, 0x80, 53 | SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1, 54 | SET_VCOM_DESEL, 0x30, # 0.83*Vcc 55 | # display 56 | SET_CONTRAST, 0xff, # maximum 57 | SET_ENTIRE_ON, # output follows RAM contents 58 | SET_NORM_INV, # not inverted 59 | # charge pump 60 | SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14, 61 | SET_DISP | 0x01): # on 62 | self.write_cmd(cmd) 63 | self.fill(0) 64 | self.show() 65 | 66 | def poweroff(self): 67 | self.write_cmd(SET_DISP | 0x00) 68 | 69 | def poweron(self): 70 | self.write_cmd(SET_DISP | 0x01) 71 | 72 | def contrast(self, contrast): 73 | self.write_cmd(SET_CONTRAST) 74 | self.write_cmd(contrast) 75 | 76 | def invert(self, invert): 77 | self.write_cmd(SET_NORM_INV | (invert & 1)) 78 | 79 | def show(self): 80 | x0 = 0 81 | x1 = self.width - 1 82 | if self.width == 64: 83 | # displays with width of 64 pixels are shifted by 32 84 | x0 += 32 85 | x1 += 32 86 | self.write_cmd(SET_COL_ADDR) 87 | self.write_cmd(x0) 88 | self.write_cmd(x1) 89 | self.write_cmd(SET_PAGE_ADDR) 90 | self.write_cmd(0) 91 | self.write_cmd(self.pages - 1) 92 | self.write_data(self.buffer) 93 | 94 | def draw_chinese(ch_str,x_axis,y_axis): 95 | offset_=0 96 | y_axis=y_axis*16#中文高度一行占8个 97 | x_axis=(x_axis*16)#中文宽度占16个 98 | for k in ch_str: 99 | code = 0x00#将中文转成16进制编码 100 | data_code = k.encode("utf-8") 101 | code |= data_code[0]<<16 102 | code |= data_code[1]<<8 103 | code |= data_code[2] 104 | print(hex(code)) 105 | byte_data=font.byte2.get(code) 106 | for y in range(0,16): 107 | a_=bin(byte_data[y]).replace('0b','') 108 | while len(a_)<8: 109 | a_='0'+a_ 110 | b_=bin(byte_data[y+16]).replace('0b','') 111 | while len(b_)<8: 112 | b_='0'+b_ 113 | for x in range(0,8): 114 | self.pixel(x_axis+x-offset_,y+y_axis,int(a_[x]))#文字的上半部分 115 | self.pixel(x_axis+x+8-offset_,y+y_axis,int(b_[x]))#文字的下半部分 116 | 117 | offset_+=16 118 | 119 | def draw_chinese_fast(self,ch_str,x_axis,y_axis): 120 | offset_=0 121 | y_axis=y_axis*16#中文高度一行占8个 122 | x_axis=(x_axis*16)#中文宽度占16个 123 | for k in ch_str: 124 | code = 0x00#将中文转成16进制编码 125 | data_code = k.encode("utf-8") 126 | code |= data_code[0]<<16 127 | code |= data_code[1]<<8 128 | code |= data_code[2] 129 | 130 | try: 131 | byte_data=font_new.byte2.get(code) 132 | byte = bytearray(byte_data) 133 | buf = framebuf.FrameBuffer(byte,16,16,framebuf.MONO_HLSB) 134 | self.blit(buf,x_axis+offset_,y_axis) 135 | except: 136 | print(code) 137 | 138 | offset_+=16 139 | 140 | 141 | class SSD1306_I2C(SSD1306): 142 | def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False): 143 | self.i2c = i2c 144 | self.addr = addr 145 | self.temp = bytearray(2) 146 | self.write_list = [b'\x40', None] # Co=0, D/C#=1 147 | super().__init__(width, height, external_vcc) 148 | 149 | def write_cmd(self, cmd): 150 | self.temp[0] = 0x80 # Co=1, D/C#=0 151 | self.temp[1] = cmd 152 | self.i2c.writeto(self.addr, self.temp) 153 | 154 | def write_data(self, buf): 155 | self.write_list[1] = buf 156 | self.i2c.writevto(self.addr, self.write_list) 157 | 158 | 159 | class SSD1306_SPI(SSD1306): 160 | def __init__(self, width, height, spi, dc, res, cs, external_vcc=False): 161 | self.rate = 10 * 1024 * 1024 162 | dc.init(dc.OUT, value=0) 163 | res.init(res.OUT, value=0) 164 | cs.init(cs.OUT, value=1) 165 | self.spi = spi 166 | self.dc = dc 167 | self.res = res 168 | self.cs = cs 169 | import time 170 | self.res(1) 171 | time.sleep_ms(1) 172 | self.res(0) 173 | time.sleep_ms(10) 174 | self.res(1) 175 | super().__init__(width, height, external_vcc) 176 | 177 | def write_cmd(self, cmd): 178 | self.spi.init(baudrate=self.rate, polarity=0, phase=0) 179 | self.cs(1) 180 | self.dc(0) 181 | self.cs(0) 182 | self.spi.write(bytearray([cmd])) 183 | self.cs(1) 184 | 185 | def write_data(self, buf): 186 | self.spi.init(baudrate=self.rate, polarity=0, phase=0) 187 | self.cs(1) 188 | self.dc(1) 189 | self.cs(0) 190 | self.spi.write(buf) 191 | self.cs(1) 192 | 193 | 194 | -------------------------------------------------------------------------------- /xmlConvert.py: -------------------------------------------------------------------------------- 1 | def xml2DictInList(xml): 2 | new_list_text = xml.split('\n') 3 | list_dict_text = [] 4 | for i in new_list_text: 5 | dict_text = {} 6 | item = i.split(' ') 7 | for j in item: 8 | j = j.replace('\"','') 9 | j = j.split('=') 10 | if len(j)>1: 11 | dict_text[j[0]]=j[1] 12 | if dict_text != {}: 13 | list_dict_text.append(dict_text) 14 | return list_dict_text 15 | -------------------------------------------------------------------------------- /字模.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beijizhidian/-ESP32-Micropython-SSD1306-Chinese/41d8d9930fc5f3ab6324b78fb218e49fbaa81a22/字模.jpg --------------------------------------------------------------------------------