差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
mp_oled [2021/10/05 17:22] gongyusu |
mp_oled [2023/08/01 10:49] (当前版本) group003 |
||
---|---|---|---|
行 13: | 行 13: | ||
import utime | import utime | ||
- | sda=machine.Pin(20) | + | sda=machine.Pin(11) |
- | scl=machine.Pin(21) | + | scl=machine.Pin(10) |
i2c=machine.I2C(0, sda=sda, scl=scl, freq=400000) | i2c=machine.I2C(0, sda=sda, scl=scl, freq=400000) | ||
行 107: | 行 107: | ||
</code> | </code> | ||
- | ### 3. 使用SSD1306 OLED显示 | + | |
+ | ### 3. Adafruit关于SSD1306的使用介绍 | ||
+ | |||
+ | #### I2C初始化 | ||
+ | <code python> | ||
+ | import machine | ||
+ | import ssd1306 | ||
+ | i2c = machine.I2C(-1, machine.Pin(5), machine.Pin(4)) | ||
+ | oled = ssd1306.SSD1306_I2C(128, 32, i2c) | ||
+ | </code> | ||
+ | |||
+ | #### SPI初始化 | ||
+ | |||
+ | <code python> | ||
+ | import machine | ||
+ | import ssd1306 | ||
+ | spi = machine.SPI(1, baudrate=8000000, polarity=0, phase=0) | ||
+ | oled = ssd1306.SSD1306_SPI(128, 32, spi, machine.Pin(15), machine.Pin(0), machine.Pin(16) | ||
+ | </code> | ||
+ | |||
+ | ### 4. SSD1306库的调用 | ||
+ | [[https://docs.micropython.org/en/latest/esp8266/tutorial/ssd1306.html|Using a SSD1306 OLED display]] | ||
SSD1306 OLED显示可以使用SPI或I2C接口,支持不同分辨率(128x64, 128x32, 72x40, 64x48)和颜色(白色, 黄色, 蓝色, 黄色 + 蓝色). | SSD1306 OLED显示可以使用SPI或I2C接口,支持不同分辨率(128x64, 128x32, 72x40, 64x48)和颜色(白色, 黄色, 蓝色, 黄色 + 蓝色). | ||
行 146: | 行 168: | ||
i2c = I2C(sda=Pin(4), scl=Pin(5)) | i2c = I2C(sda=Pin(4), scl=Pin(5)) | ||
display = ssd1306.SSD1306_I2C(128, 64, i2c) | display = ssd1306.SSD1306_I2C(128, 64, i2c) | ||
- | </code? | + | </code> |
在第一行打印Hello World: | 在第一行打印Hello World: | ||
行 204: | 行 226: | ||
</code> | </code> | ||
- | |||
- | ### 4. Adafruit关于SSD1306的使用介绍 | ||
- | |||
- | #### I2C初始化 | ||
- | <code python> | ||
- | import machine | ||
- | import ssd1306 | ||
- | i2c = machine.I2C(-1, machine.Pin(5), machine.Pin(4)) | ||
- | oled = ssd1306.SSD1306_I2C(128, 32, i2c) | ||
- | </code> | ||
- | |||
- | #### SPI初始化 | ||
- | |||
- | <code python> | ||
- | import machine | ||
- | import ssd1306 | ||
- | spi = machine.SPI(1, baudrate=8000000, polarity=0, phase=0) | ||
- | oled = ssd1306.SSD1306_SPI(128, 32, spi, machine.Pin(15), machine.Pin(0), machine.Pin(16) | ||
- | </code> | ||
### 5. MicroPython官方的驱动 | ### 5. MicroPython官方的驱动 | ||
行 390: | 行 393: | ||
self.spi.write(buf) | self.spi.write(buf) | ||
self.cs(1) | self.cs(1) | ||
+ | </code> | ||
+ | |||
+ | ### 6. 汉字的显示 | ||
+ | * 支持英文字号8x8,16x16,24x24,32x32 | ||
+ | * 支持中文字号16x16,24x24,32x32 | ||
+ | * 封装lcd操作常用接口 | ||
+ | |||
+ | #### API | ||
+ | <code python> | ||
+ | def init_i2c(scl, sda, width, height): | ||
+ | """ | ||
+ | 初始化i2c接口 | ||
+ | :param scl: i2c的时钟脚 | ||
+ | :param sda: i2c的数据脚 | ||
+ | :param width: oled屏幕的宽度像素 | ||
+ | :param height: oled屏幕的高度像素 | ||
+ | """ | ||
+ | |||
+ | def clear(): | ||
+ | """清除屏幕""" | ||
+ | |||
+ | def show(): | ||
+ | """屏幕刷新显示""" | ||
+ | |||
+ | def pixel(x, y): | ||
+ | """画点""" | ||
+ | |||
+ | def text(string, x_axis, y_axis, font_size): | ||
+ | """显示字符串.注意字符串必须是英文或者数字""" | ||
+ | |||
+ | def set_font(font, font_size): | ||
+ | """ | ||
+ | 设置中文字库.允许设置多个不同大小的字库 | ||
+ | 字库必须是字典,格式示例: | ||
+ | font = { | ||
+ | 0xe4bda0: | ||
+ | [0x08, 0x08, 0x08, 0x11, 0x11, 0x32, 0x34, 0x50, 0x91, 0x11, 0x12, 0x12, 0x14, 0x10, 0x10, 0x10, 0x80, 0x80, | ||
+ | 0x80, 0xFE, 0x02, 0x04, 0x20, 0x20, 0x28, 0x24, 0x24, 0x22, 0x22, 0x20, 0xA0, 0x40], # 你 | ||
+ | 0xe5a5bd: | ||
+ | [0x10, 0x10, 0x10, 0x10, 0xFC, 0x24, 0x24, 0x25, 0x24, 0x48, 0x28, 0x10, 0x28, 0x44, 0x84, 0x00, 0x00, 0xFC, | ||
+ | 0x04, 0x08, 0x10, 0x20, 0x20, 0xFE, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xA0, 0x40] # 好 | ||
+ | } | ||
+ | """ | ||
+ | |||
+ | def text_cn(string, x_axis, y_axis, font_size): | ||
+ | """显示中文字符.注意字符必须是utf-8编码""" | ||
+ | </code> | ||
+ | |||
+ | #### 显示英文字符 | ||
+ | <code python> | ||
+ | import ssd1306py as lcd | ||
+ | |||
+ | |||
+ | lcd.init_i2c(22, 21, 128, 64) | ||
+ | lcd.text('font8x8', 0, 0, 8) | ||
+ | lcd.text('font16x16', 0, 20, 16) | ||
+ | lcd.show() | ||
+ | |||
+ | </code> | ||
+ | |||
+ | <code python> | ||
+ | import ssd1306py as lcd | ||
+ | |||
+ | |||
+ | lcd.init_i2c(22, 21, 128, 64) | ||
+ | lcd.text('font32x32', 0, 0, 32) | ||
+ | lcd.show() | ||
+ | |||
+ | </code> | ||
+ | |||
+ | #### 显示汉字 | ||
+ | 可以使用在线转换工具查询:[[http://www.mytju.com/classcode/tools/encode_utf8.asp|在线转换工具]] | ||
+ | |||
+ | 比如以下示例,显示汉字“你好”。 | ||
+ | <code python> | ||
+ | import ssd1306py as lcd | ||
+ | |||
+ | lcd.init_i2c(22, 21, 128, 64) | ||
+ | |||
+ | font16 = { | ||
+ | 0xe4bda0: | ||
+ | [0x08, 0x08, 0x08, 0x11, 0x11, 0x32, 0x34, 0x50, 0x91, 0x11, 0x12, 0x12, 0x14, 0x10, 0x10, 0x10, 0x80, 0x80, | ||
+ | 0x80, 0xFE, 0x02, 0x04, 0x20, 0x20, 0x28, 0x24, 0x24, 0x22, 0x22, 0x20, 0xA0, 0x40], # 你 | ||
+ | 0xe5a5bd: | ||
+ | [0x10, 0x10, 0x10, 0x10, 0xFC, 0x24, 0x24, 0x25, 0x24, 0x48, 0x28, 0x10, 0x28, 0x44, 0x84, 0x00, 0x00, 0xFC, | ||
+ | 0x04, 0x08, 0x10, 0x20, 0x20, 0xFE, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xA0, 0x40] # 好 | ||
+ | } | ||
+ | |||
+ | font24 = { | ||
+ | 0xe4bda0: | ||
+ | [0x00, 0x01, 0x01, 0x03, 0x03, 0x02, 0x04, 0x04, 0x0E, 0x1C, 0x14, 0x24, 0x44, 0x04, 0x04, 0x04, 0x04, 0x04, | ||
+ | 0x04, 0x05, 0x04, 0x06, 0x04, 0x00, | ||
+ | 0x00, 0x00, 0x8C, 0x0C, 0x08, 0x18, 0x1F, 0x30, 0x21, 0x41, 0x41, 0x91, 0x19, 0x11, 0x31, 0x21, 0x41, 0x41, | ||
+ | 0x81, 0x01, 0x11, 0x0F, 0x02, 0x00, | ||
+ | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x10, 0x00, 0x00, 0x00, 0x20, 0x10, 0x18, 0x0C, 0x0C, 0x06, | ||
+ | 0x04, 0x00, 0x00, 0x00, 0x00, 0x00], # 你 | ||
+ | 0xe5a5bd: | ||
+ | [0x00, 0x00, 0x06, 0x06, 0x06, 0x04, 0x04, 0x7F, 0x0C, 0x0C, 0x08, 0x08, 0x08, 0x18, 0x10, 0x11, 0x0D, 0x03, | ||
+ | 0x02, 0x04, 0x18, 0x20, 0x40, 0x00, | ||
+ | 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0xC0, 0x40, 0x40, 0xC0, 0x80, 0xBF, 0x80, 0x80, 0x00, 0x00, 0x80, | ||
+ | 0xC0, 0x60, 0x00, 0x07, 0x01, 0x00, | ||
+ | 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x20, 0x40, 0x80, 0x80, 0x80, 0x84, 0xFE, 0x80, 0x80, 0x80, 0x80, 0x80, | ||
+ | 0x80, 0x80, 0x80, 0x80, 0x00, 0x00] # 好 | ||
+ | } | ||
+ | |||
+ | font32 = { | ||
+ | 0xe4bda0: | ||
+ | [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x07, 0x0D, 0x09, 0x11, 0x11, 0x21, | ||
+ | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||
+ | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x40, 0x70, 0x60, 0xE0, 0xC0, 0xC1, 0x81, 0x03, | ||
+ | 0x03, 0x86, 0x84, 0x8C, 0x88, 0x90, | ||
+ | 0x81, 0x83, 0x83, 0x83, 0x86, 0x86, 0x8C, 0x88, 0x90, 0x90, 0xA0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, | ||
+ | 0x00, 0x60, 0xE0, 0xC0, 0xC0, 0x80, | ||
+ | 0x80, 0xFF, 0x00, 0x10, 0x0C, 0x08, 0x08, 0x08, 0x88, 0x88, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, | ||
+ | 0x08, 0x08, 0xF8, 0x38, 0x10, 0x00, | ||
+ | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xFC, 0x18, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00, 0x80, | ||
+ | 0x40, 0x20, 0x30, 0x18, 0x1C, 0x0C, | ||
+ | 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], # 你 | ||
+ | 0xe5a5bd: | ||
+ | [0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x3F, 0x03, 0x03, 0x02, 0x06, 0x06, 0x04, 0x04, 0x0C, | ||
+ | 0x0C, 0x08, 0x08, 0x0E, 0x01, 0x00, | ||
+ | 0x00, 0x01, 0x03, 0x04, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x81, 0x80, 0x00, 0x08, 0xFC, | ||
+ | 0x08, 0x08, 0x18, 0x18, 0x18, 0x18, | ||
+ | 0x17, 0x30, 0x30, 0x30, 0x60, 0x60, 0xC0, 0xF0, 0xBC, 0x8C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
+ | 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, | ||
+ | 0x00, 0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xFF, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, | ||
+ | 0x06, 0x06, 0xFC, 0x1C, 0x08, 0x00, | ||
+ | 0x00, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x70, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xFC, 0x00, | ||
+ | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
+ | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] # 好 | ||
+ | } | ||
+ | |||
+ | lcd.init_i2c(22, 21, 128, 64) | ||
+ | lcd.set_font(font16, 16) | ||
+ | lcd.set_font(font24, 24) | ||
+ | lcd.set_font(font32, 32) | ||
+ | lcd.text_cn('你好', 0, 0, 16) | ||
+ | lcd.text_cn('你好', 40, 00, 24) | ||
+ | lcd.text_cn('你好', 0, 30, 32) | ||
+ | lcd.show() | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ### 7. 滚动屏幕的程序 | ||
+ | [[https://randomnerdtutorials.com/micropython-ssd1306-oled-scroll-shapes-esp32-esp8266/|滚动屏幕]] | ||
+ | <code python> | ||
+ | oled_width = 128 | ||
+ | oled_height = 64 | ||
+ | oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) | ||
+ | |||
+ | screen1_row1 = "Screen 1, row 1" | ||
+ | screen1_row2 = "Screen 1, row 2" | ||
+ | screen1_row3 = "Screen 1, row 3" | ||
+ | |||
+ | screen2_row1 = "Screen 2, row 1" | ||
+ | screen2_row2 = "Screen 2, row 2" | ||
+ | |||
+ | screen3_row1 = "Screen 3, row 1" | ||
+ | |||
+ | screen1 = [[0, 0 , screen1_row1], [0, 16, screen1_row2], [0, 32, screen1_row3]] | ||
+ | screen2 = [[0, 0 , screen2_row1], [0, 16, screen2_row2]] | ||
+ | screen3 = [[0, 40 , screen3_row1]] | ||
+ | |||
+ | # Scroll in screen horizontally from left to right | ||
+ | def scroll_in_screen(screen): | ||
+ | for i in range (0, oled_width+1, 4): | ||
+ | for line in screen: | ||
+ | oled.text(line[2], -oled_width+i, line[1]) | ||
+ | oled.show() | ||
+ | if i!= oled_width: | ||
+ | oled.fill(0) | ||
+ | |||
+ | # Scroll out screen horizontally from left to right | ||
+ | def scroll_out_screen(speed): | ||
+ | for i in range ((oled_width+1)/speed): | ||
+ | for j in range (oled_height): | ||
+ | oled.pixel(i, j, 0) | ||
+ | oled.scroll(speed,0) | ||
+ | oled.show() | ||
+ | |||
+ | # Continuous horizontal scroll | ||
+ | def scroll_screen_in_out(screen): | ||
+ | for i in range (0, (oled_width+1)*2, 1): | ||
+ | for line in screen: | ||
+ | oled.text(line[2], -oled_width+i, line[1]) | ||
+ | oled.show() | ||
+ | if i!= oled_width: | ||
+ | oled.fill(0) | ||
+ | |||
+ | # Scroll in screen vertically | ||
+ | def scroll_in_screen_v(screen): | ||
+ | for i in range (0, (oled_height+1), 1): | ||
+ | for line in screen: | ||
+ | oled.text(line[2], line[0], -oled_height+i+line[1]) | ||
+ | oled.show() | ||
+ | if i!= oled_height: | ||
+ | oled.fill(0) | ||
+ | |||
+ | # Scroll out screen vertically | ||
+ | def scroll_out_screen_v(speed): | ||
+ | for i in range ((oled_height+1)/speed): | ||
+ | for j in range (oled_width): | ||
+ | oled.pixel(j, i, 0) | ||
+ | oled.scroll(0,speed) | ||
+ | oled.show() | ||
+ | |||
+ | # Continous vertical scroll | ||
+ | def scroll_screen_in_out_v(screen): | ||
+ | for i in range (0, (oled_height*2+1), 1): | ||
+ | for line in screen: | ||
+ | oled.text(line[2], line[0], -oled_height+i+line[1]) | ||
+ | oled.show() | ||
+ | if i!= oled_height: | ||
+ | oled.fill(0) | ||
+ | |||
+ | while True: | ||
+ | |||
+ | # Scroll in, stop, scroll out (horizontal) | ||
+ | scroll_in_screen(screen1) | ||
+ | sleep(2) | ||
+ | scroll_out_screen(4) | ||
+ | |||
+ | scroll_in_screen(screen2) | ||
+ | sleep(2) | ||
+ | scroll_out_screen(4) | ||
+ | |||
+ | scroll_in_screen(screen3) | ||
+ | sleep(2) | ||
+ | scroll_out_screen(4) | ||
+ | |||
+ | # Continuous horizontal scroll | ||
+ | scroll_screen_in_out(screen1) | ||
+ | scroll_screen_in_out(screen2) | ||
+ | scroll_screen_in_out(screen3) | ||
+ | |||
+ | # Scroll in, stop, scroll out (vertical) | ||
+ | scroll_in_screen_v(screen1) | ||
+ | sleep(2) | ||
+ | scroll_out_screen_v(4) | ||
+ | |||
+ | scroll_in_screen_v(screen2) | ||
+ | sleep(2) | ||
+ | scroll_out_screen_v(4) | ||
+ | |||
+ | scroll_in_screen_v(screen3) | ||
+ | sleep(2) | ||
+ | scroll_out_screen_v(4) | ||
+ | |||
+ | # Continuous verticall scroll | ||
+ | scroll_screen_in_out_v(screen1) | ||
+ | scroll_screen_in_out_v(screen2) | ||
+ | scroll_screen_in_out_v(screen3) | ||
+ | </code> | ||
+ | |||
+ | ### 8. 绘图 | ||
+ | 使用[[https://github.com/adafruit/micropython-adafruit-gfx/blob/master/gfx.py|Adafruit GFX Arduino library to MicroPython]] | ||
+ | |||
+ | <code python> | ||
+ | # Port of Adafruit GFX Arduino library to MicroPython. | ||
+ | # Based on: https://github.com/adafruit/Adafruit-GFX-Library | ||
+ | # Author: Tony DiCola (original GFX author Phil Burgess) | ||
+ | # License: MIT License (https://opensource.org/licenses/MIT) | ||
+ | |||
+ | |||
+ | class GFX: | ||
+ | |||
+ | def __init__(self, width, height, pixel, hline=None, vline=None): | ||
+ | # Create an instance of the GFX drawing class. You must pass in the | ||
+ | # following parameters: | ||
+ | # - width = The width of the drawing area in pixels. | ||
+ | # - height = The height of the drawing area in pixels. | ||
+ | # - pixel = A function to call when a pixel is drawn on the display. | ||
+ | # This function should take at least an x and y position | ||
+ | # and then any number of optional color or other parameters. | ||
+ | # You can also provide the following optional keyword argument to | ||
+ | # improve the performance of drawing: | ||
+ | # - hline = A function to quickly draw a horizontal line on the display. | ||
+ | # This should take at least an x, y, and width parameter and | ||
+ | # any number of optional color or other parameters. | ||
+ | # - vline = A function to quickly draw a vertical line on the display. | ||
+ | # This should take at least an x, y, and height paraemter and | ||
+ | # any number of optional color or other parameters. | ||
+ | self.width = width | ||
+ | self.height = height | ||
+ | self._pixel = pixel | ||
+ | # Default to slow horizontal & vertical line implementations if no | ||
+ | # faster versions are provided. | ||
+ | if hline is None: | ||
+ | self.hline = self._slow_hline | ||
+ | else: | ||
+ | self.hline = hline | ||
+ | if vline is None: | ||
+ | self.vline = self._slow_vline | ||
+ | else: | ||
+ | self.vline = vline | ||
+ | |||
+ | def _slow_hline(self, x0, y0, width, *args, **kwargs): | ||
+ | # Slow implementation of a horizontal line using pixel drawing. | ||
+ | # This is used as the default horizontal line if no faster override | ||
+ | # is provided. | ||
+ | if y0 < 0 or y0 > self.height or x0 < -width or x0 > self.width: | ||
+ | return | ||
+ | for i in range(width): | ||
+ | self._pixel(x0+i, y0, *args, **kwargs) | ||
+ | |||
+ | def _slow_vline(self, x0, y0, height, *args, **kwargs): | ||
+ | # Slow implementation of a vertical line using pixel drawing. | ||
+ | # This is used as the default vertical line if no faster override | ||
+ | # is provided. | ||
+ | if y0 < -height or y0 > self.height or x0 < 0 or x0 > self.width: | ||
+ | return | ||
+ | for i in range(height): | ||
+ | self._pixel(x0, y0+i, *args, **kwargs) | ||
+ | |||
+ | def rect(self, x0, y0, width, height, *args, **kwargs): | ||
+ | # Rectangle drawing function. Will draw a single pixel wide rectangle | ||
+ | # starting in the upper left x0, y0 position and width, height pixels in | ||
+ | # size. | ||
+ | if y0 < -height or y0 > self.height or x0 < -width or x0 > self.width: | ||
+ | return | ||
+ | self.hline(x0, y0, width, *args, **kwargs) | ||
+ | self.hline(x0, y0+height-1, width, *args, **kwargs) | ||
+ | self.vline(x0, y0, height, *args, **kwargs) | ||
+ | self.vline(x0+width-1, y0, height, *args, **kwargs) | ||
+ | |||
+ | def fill_rect(self, x0, y0, width, height, *args, **kwargs): | ||
+ | # Filled rectangle drawing function. Will draw a single pixel wide | ||
+ | # rectangle starting in the upper left x0, y0 position and width, height | ||
+ | # pixels in size. | ||
+ | if y0 < -height or y0 > self.height or x0 < -width or x0 > self.width: | ||
+ | return | ||
+ | for i in range(x0, x0+width): | ||
+ | self.vline(i, y0, height, *args, **kwargs) | ||
+ | |||
+ | def line(self, x0, y0, x1, y1, *args, **kwargs): | ||
+ | # Line drawing function. Will draw a single pixel wide line starting at | ||
+ | # x0, y0 and ending at x1, y1. | ||
+ | steep = abs(y1 - y0) > abs(x1 - x0) | ||
+ | if steep: | ||
+ | x0, y0 = y0, x0 | ||
+ | x1, y1 = y1, x1 | ||
+ | if x0 > x1: | ||
+ | x0, x1 = x1, x0 | ||
+ | y0, y1 = y1, y0 | ||
+ | dx = x1 - x0 | ||
+ | dy = abs(y1 - y0) | ||
+ | err = dx // 2 | ||
+ | ystep = 0 | ||
+ | if y0 < y1: | ||
+ | ystep = 1 | ||
+ | else: | ||
+ | ystep = -1 | ||
+ | while x0 <= x1: | ||
+ | if steep: | ||
+ | self._pixel(y0, x0, *args, **kwargs) | ||
+ | else: | ||
+ | self._pixel(x0, y0, *args, **kwargs) | ||
+ | err -= dy | ||
+ | if err < 0: | ||
+ | y0 += ystep | ||
+ | err += dx | ||
+ | x0 += 1 | ||
+ | |||
+ | def circle(self, x0, y0, radius, *args, **kwargs): | ||
+ | # Circle drawing function. Will draw a single pixel wide circle with | ||
+ | # center at x0, y0 and the specified radius. | ||
+ | f = 1 - radius | ||
+ | ddF_x = 1 | ||
+ | ddF_y = -2 * radius | ||
+ | x = 0 | ||
+ | y = radius | ||
+ | self._pixel(x0, y0 + radius, *args, **kwargs) | ||
+ | self._pixel(x0, y0 - radius, *args, **kwargs) | ||
+ | self._pixel(x0 + radius, y0, *args, **kwargs) | ||
+ | self._pixel(x0 - radius, y0, *args, **kwargs) | ||
+ | while x < y: | ||
+ | if f >= 0: | ||
+ | y -= 1 | ||
+ | ddF_y += 2 | ||
+ | f += ddF_y | ||
+ | x += 1 | ||
+ | ddF_x += 2 | ||
+ | f += ddF_x | ||
+ | self._pixel(x0 + x, y0 + y, *args, **kwargs) | ||
+ | self._pixel(x0 - x, y0 + y, *args, **kwargs) | ||
+ | self._pixel(x0 + x, y0 - y, *args, **kwargs) | ||
+ | self._pixel(x0 - x, y0 - y, *args, **kwargs) | ||
+ | self._pixel(x0 + y, y0 + x, *args, **kwargs) | ||
+ | self._pixel(x0 - y, y0 + x, *args, **kwargs) | ||
+ | self._pixel(x0 + y, y0 - x, *args, **kwargs) | ||
+ | self._pixel(x0 - y, y0 - x, *args, **kwargs) | ||
+ | |||
+ | def fill_circle(self, x0, y0, radius, *args, **kwargs): | ||
+ | # Filled circle drawing function. Will draw a filled circule with | ||
+ | # center at x0, y0 and the specified radius. | ||
+ | self.vline(x0, y0 - radius, 2*radius + 1, *args, **kwargs) | ||
+ | f = 1 - radius | ||
+ | ddF_x = 1 | ||
+ | ddF_y = -2 * radius | ||
+ | x = 0 | ||
+ | y = radius | ||
+ | while x < y: | ||
+ | if f >= 0: | ||
+ | y -= 1 | ||
+ | ddF_y += 2 | ||
+ | f += ddF_y | ||
+ | x += 1 | ||
+ | ddF_x += 2 | ||
+ | f += ddF_x | ||
+ | self.vline(x0 + x, y0 - y, 2*y + 1, *args, **kwargs) | ||
+ | self.vline(x0 + y, y0 - x, 2*x + 1, *args, **kwargs) | ||
+ | self.vline(x0 - x, y0 - y, 2*y + 1, *args, **kwargs) | ||
+ | self.vline(x0 - y, y0 - x, 2*x + 1, *args, **kwargs) | ||
+ | |||
+ | def triangle(self, x0, y0, x1, y1, x2, y2, *args, **kwargs): | ||
+ | # Triangle drawing function. Will draw a single pixel wide triangle | ||
+ | # around the points (x0, y0), (x1, y1), and (x2, y2). | ||
+ | self.line(x0, y0, x1, y1, *args, **kwargs) | ||
+ | self.line(x1, y1, x2, y2, *args, **kwargs) | ||
+ | self.line(x2, y2, x0, y0, *args, **kwargs) | ||
+ | |||
+ | def fill_triangle(self, x0, y0, x1, y1, x2, y2, *args, **kwargs): | ||
+ | # Filled triangle drawing function. Will draw a filled triangle around | ||
+ | # the points (x0, y0), (x1, y1), and (x2, y2). | ||
+ | if y0 > y1: | ||
+ | y0, y1 = y1, y0 | ||
+ | x0, x1 = x1, x0 | ||
+ | if y1 > y2: | ||
+ | y2, y1 = y1, y2 | ||
+ | x2, x1 = x1, x2 | ||
+ | if y0 > y1: | ||
+ | y0, y1 = y1, y0 | ||
+ | x0, x1 = x1, x0 | ||
+ | a = 0 | ||
+ | b = 0 | ||
+ | y = 0 | ||
+ | last = 0 | ||
+ | if y0 == y2: | ||
+ | a = x0 | ||
+ | b = x0 | ||
+ | if x1 < a: | ||
+ | a = x1 | ||
+ | elif x1 > b: | ||
+ | b = x1 | ||
+ | if x2 < a: | ||
+ | a = x2 | ||
+ | elif x2 > b: | ||
+ | b = x2 | ||
+ | self.hline(a, y0, b-a+1, *args, **kwargs) | ||
+ | return | ||
+ | dx01 = x1 - x0 | ||
+ | dy01 = y1 - y0 | ||
+ | dx02 = x2 - x0 | ||
+ | dy02 = y2 - y0 | ||
+ | dx12 = x2 - x1 | ||
+ | dy12 = y2 - y1 | ||
+ | if dy01 == 0: | ||
+ | dy01 = 1 | ||
+ | if dy02 == 0: | ||
+ | dy02 = 1 | ||
+ | if dy12 == 0: | ||
+ | dy12 = 1 | ||
+ | sa = 0 | ||
+ | sb = 0 | ||
+ | if y1 == y2: | ||
+ | last = y1 | ||
+ | else: | ||
+ | last = y1-1 | ||
+ | for y in range(y0, last+1): | ||
+ | a = x0 + sa // dy01 | ||
+ | b = x0 + sb // dy02 | ||
+ | sa += dx01 | ||
+ | sb += dx02 | ||
+ | if a > b: | ||
+ | a, b = b, a | ||
+ | self.hline(a, y, b-a+1, *args, **kwargs) | ||
+ | sa = dx12 * (y - y1) | ||
+ | sb = dx02 * (y - y0) | ||
+ | while y <= y2: | ||
+ | a = x1 + sa // dy12 | ||
+ | b = x0 + sb // dy02 | ||
+ | sa += dx12 | ||
+ | sb += dx02 | ||
+ | if a > b: | ||
+ | a, b = b, a | ||
+ | self.hline(a, y, b-a+1, *args, **kwargs) | ||
+ | y += 1 | ||
+ | </code> | ||
+ | |||
+ | |||
+ | 绘图示例: | ||
+ | <code python> | ||
+ | oled_width = 128 | ||
+ | oled_height = 64 | ||
+ | oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) | ||
+ | |||
+ | graphics = gfx.GFX(oled_width, oled_height, oled.pixel) | ||
+ | |||
+ | while True: | ||
+ | |||
+ | graphics.line(0, 0, 127, 20, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.rect(10, 10, 50, 30, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.fill_rect(10, 10, 50, 30, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | |||
+ | graphics.circle(64, 32, 10, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.fill_circle(64, 32, 10, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.triangle(10,10,55,20,5,40,1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.fill_triangle(10,10,55,20,5,40,1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
</code> | </code> |