mybag1 发表于 2017-1-24 22:46:34

[TPYBoard-Micropython之会python就能做硬件 2] 利用micropython控制NOKIA 5110屏

转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi

欢迎加入讨论群 64770604
一、本次实验所需器材
1、TPYboard V102板一块

2、DS3231模块   一块

3、NOKIA 5110 LCD 屏 一块

4、杜邦线:若干

===感谢某宝“萝卜城”提供的TPYboard V102豪华版套餐===

二、Nokia 5110 LCD屏使用方法
1、什么是Nokia 5110 LCD?

      Nokia 5110 LCD是NOKIA 公司生产的可用于其5110、6150,6100 等系列移动电话的液晶显示模块,国内厂家也生产有类似的兼容产品。该产品除应用于移动电话外,也可广泛应用于各类便携式设备的显示系统。与其它类型的产品相比,该模块具有以下特点:
●84x48 的点阵LCD,可以显示4 行汉字,
●采用串行接口与主处理器进行通信,接口信号线数量大幅度减少,包括电源和地在内的信号线仅有9 条。支持多种串行通信协议(如AVR 单片机的SPI、MCS51 的串口模式0等),传输速率高达4Mbps,可全速写入显示数据,无等待时间。
●可通过导电胶连接模块与印制版
●LCD 控制器/驱动器芯片已绑定到LCD 晶片上,模块的体积很小。
●采用低电压供电,正常显示时的工作电流在200μA 以下,且具有掉电模式。

2、Nokia 5110 LCD 引脚说明

    Nokia 5110 LCD共有8个引脚,不同的板子可能标注的英文略有不同,具体含义如下:


3、Tpyboard V102连接5110的方法

    这里使用的是SPI连接方法,如果你对什么是SPI连接还不是很清楚,你可以百度一下,这样有利于你从原理上搞明白为什么这么连接。具体针脚对应如下:(由于tpyboard v102有两个spi接口,这里我们选用x1对应接口)


4、5110 LCD字模的获取

(1)英文及数据的显示

   本节提供了font.py文件,已经将英文、数字及符号的字模做好,可以直接调用。具体下载见文章最后的下载地址。

(2)汉字取模

   汉字取模需要用到字模提取工具,该工具在文章后面的下载地址中可以下载。这里以“欢”为例具体说明使用方法如下:

第一步,打开工具:


第二步,点击新建图像,宽度与高度均为16,点击确定。如图:


第三步,在文字输入区写入要取模的汉字“欢”,按下ctrl+enter。


第四步,点左边菜单里的取模方式,点c51格式,于是得到:

0x04,0x24,0x44,0x84,0x64,0x9C,0x40,0x30,0x0F,0xC8,0x08,0x08,0x28,0x18,0x00,0x00,
0x10,0x08,0x06,0x01,0x82,0x4C,0x20,0x18,0x06,0x01,0x06,0x18,0x20,0x40,0x80,0x00,


第五步,对应填写到chinese.py文件中(该文件可从文章后面的网址下载),如下:
class CN_UTF8:
    """docstring for CN_UTF8"""
    #key:values
    #key: 使用汉字的UTF-8码
    #values: 16*16
    #    8*16 上半部分
    #    8*16 下半部分
    UTF8_CHINESE = {
      0xe6aca2:[
                  ,
                  
                ],#欢
      0xe8bf8e:[
                  ,
                  
                ],#迎
      0xe4bdbf:[
                  ,
                  
                ],#使
      0xe794a8:[
                  ,
                  
                ],#用
      0xe78eb0:[
                  ,
                  
                ],#现
      0xe59ca8:[
                  ,
                  
                ],#在
      0xe697b6:[
                  ,
                  
                ],#时
      0xe997b4:[
                  ,
                  
                ], #间   
      0xe68891:[
                  ,
                  
                ], #我
      0xe8909d:[
                  ,
                  
                ], #萝
      0xe58d9c:[
                  ,
                  
                ], #卜
      0xe699ba:[
                  ,
                  
                ], #智
      0xe883bd:[
                  ,
                  
                ],#能
      0xe682a8:[
                  ,
                  
                ],#您
      0xe5bd93:[
                  ,
                  
                ],#当
      0xE5898D:[
                  ,
                  
                ]#前
   
               
         

    }
    #key 汉字的UTF-8码
    #isBottom 确定这次是获取 某个字的 上半部分(0) 还是下半部分(1)
    def get_chinese_utf8(self, key,isBottom = 0):
      values = self.UTF8_CHINESE
      return values

三、显示“萝卜智能”的小实例
    按照上面连接后,将tpyboard v102插入电脑usb,在TPFLASH内建立以下文件(可从文章后地址下载):

#font.py
class FONT6_8:
    """docstring for FONT6_8"""
    FONTTYPE6_8 = [
       # 20
      , # 21 !
      , # 22 "
      , # 23 #
      , # 24 $
      , # 25 %
      , # 26 &
      , # 27 '
      , # 28 (
      , # 29 )
      , # 2a *
      , # 2b +
      , # 2c ,
      , # 2d -
      , # 2e .
      , # 2f /
      , # 30 0
      , # 31 1
      , # 32 2
      , # 33 3
      , # 34 4
      , # 35 5
      , # 36 6
      , # 37 7
      , # 38 8
      , # 39 9
      , # 3a :
      , # 3b ;
      , # 3c <
      , # 3d =
      , # 3e >
      , # 3f ?
      , # 40 @
      , # 41 A
      , # 42 B
      , # 43 C
      , # 44 D
      , # 45 E
      , # 46 F
      , # 47 G
      , # 48 H
      , # 49 I
      , # 4a J
      , # 4b K
      , # 4c L
      , # 4d M
      , # 4e N
      , # 4f O
      , # 50 P
      , # 51 Q
      , # 52 R
      , # 53 S
      , # 54 T
      , # 55 U
      , # 56 V
      , # 57 W
      , # 58 X
      , # 59 Y
      , # 5a Z
      , # 5b [
      , # 5c \
      , # 5d ]
      , # 5e ^
      , # 5f _
      , # 60 `
      , # 61 a
      , # 62 b
      , # 63 c
      , # 64 d
      , # 65 e
      , # 66 f
      , # 67 g
      , # 68 h
      , # 69 i
      , # 6a j
      , # 6b k
      , # 6c l
      , # 6d m
      , # 6e n
      , # 6f o
      , # 70 p
      , # 71 q
      , # 72 r
      , # 73 s
      , # 74 t
      , # 75 u
      , # 76 v
      , # 77 w
      , # 78 x
      , # 79 y
      , # 7a z
      , # 7b [
      , # 7c |
      , # 7d ]
      , # 7e ~
      , # 7f (delete)
    ]
   

    def get_font6_8(self, data):
      return self.FONTTYPE6_8 - 0x20]

#chinese.py

//转载请注明:@小五义http://www.cnblogs.com/xiaowuyiQQ群:64770604
class CN_UTF8:
    """docstring for CN_UTF8"""
    #key:values
    #key: 使用汉字的UTF-8码
    #values: 16*16
    #    8*16 上半部分
    #    8*16 下半部分
    UTF8_CHINESE = {
      0xe6aca2:[
                  ,
                  
                ],#欢
      0xe8bf8e:[
                  ,
                  
                ],#迎
      0xe4bdbf:[
                  ,
                  
                ],#使
      0xe794a8:[
                  ,
                  
                ],#用
      0xe78eb0:[
                  ,
                  
                ],#现
      0xe59ca8:[
                  ,
                  
                ],#在
      0xe697b6:[
                  ,
                  
                ],#时
      0xe997b4:[
                  ,
                  
                ], #间   
      0xe68891:[
                  ,
                  
                ], #我
      0xe8909d:[
                  ,
                  
                ], #萝
      0xe58d9c:[
                  ,
                  
                ], #卜
      0xe699ba:[
                  ,
                  
                ], #智
      0xe883bd:[
                  ,
                  
                ],#能
      0xe682a8:[
                  ,
                  
                ],#您
      0xe5bd93:[
                  ,
                  
                ],#当
      0xE5898D:[
                  ,
                  
                ]#前
   
               
         

    }
    #key 汉字的UTF-8码
    #isBottom 确定这次是获取 某个字的 上半部分(0) 还是下半部分(1)
    def get_chinese_utf8(self, key,isBottom = 0):
      values = self.UTF8_CHINESE
      return values

#upcd8544.py

//转载请注明:@小五义http://www.cnblogs.com/xiaowuyiQQ群:64770604
# -*- coding: utf-8 -*-
"""
MicroPython PCD8544 driver
(for Nokia 5110 displays)
"""

__author__   = "Markus Birth"
__copyright__= "Copyright 2015, Markus Birth"
__credits__    = ["Markus Birth"]
__license__    = "MIT"
__version__    = "1.0"
__maintainer__ = "Markus Birth"
__email__      = "[email protected]"
__status__   = "Production"

# Datasheet: https://www.sparkfun.com/datasheets/LCD/Monochrome/Nokia5110.pdf
# Inspiration from:
#   - https://github.com/inaugurator/upyd5110
#   - https://github.com/rm-hull/pcd8544/blob/master/src/lcd.py
#
# PINOUT
# WiPy/pyBoard      display   function
#
# 3V3 or any Pin => VCC       3.3V logic voltage (0=off, 1=on)
# MOSI         => DIN       data flow (Master out, Slave in)
# SCK            => CLK       SPI clock
# any Pin      => RST       Reset pin (0=reset, 1=normal)
# any Pin      => CE      Chip Enable (0=listen for input, 1=ignore input)
# any Pin      => DC      Data/Command (0=commands, 1=data)
# any Pin      => LIGHT   Light (0=on, 1=off)
# GND            => GND
#
# pyBoard "Y" side
# SPI    = pyb.SPI(1)
# RST    = pyb.Pin('Y4')
# CE   = pyb.Pin('Y5')
# DC   = pyb.Pin('Y3')
# LIGHT= pyb.Pin('Y2')
# PWR    = pyb.Pin('Y1')
#
# pyBoard "X" side
# SPI    = pyb.SPI(2)
# RST    = pyb.Pin('X4')
# CE   = pyb.Pin('X5')
# DC   = pyb.Pin('X3')
# LIGHT= pyb.Pin('X2')
# PWR    = pyb.Pin('X1')
#
# WiPy (on Exp board, SD and User-LED jumper have to be removed!)
# SPI    = machine.SPI(0)   # GP14 (CLK) + GP16 (MOSI->DIN), User-LED jumper removed!
# RST    = machine.Pin('GP24')
# CE   = machine.Pin('GP12')
# DC   = machine.Pin('GP22')
# LIGHT= machine.Pin('GP23')
# PWR    = directly from 3V3 pin of the WiPy

try:
    import pyb as machine
except:
    # WiPy
    import machine
   
import sys
import struct
import time
import font
import chinese

class PCD8544:
    ADDRESSING_HORIZ = 0x00
    ADDRESSING_VERT= 0x02
    INSTR_BASIC = 0x00
    INSTR_EXT   = 0x01
    POWER_UP   = 0x00
    POWER_DOWN = 0x04
    DISPLAY_BLANK   = 0x08
    DISPLAY_ALL   = 0x09
    DISPLAY_NORMAL= 0x0c
    DISPLAY_INVERSE = 0x0d
    TEMP_COEFF_0 = 0x04
    TEMP_COEFF_1 = 0x05
    TEMP_COEFF_2 = 0x06
    TEMP_COEFF_3 = 0x07
    BIAS_1_4= 0x17   # 1/4th
    BIAS_1_5= 0x16   # 1/5th
    BIAS_1_6= 0x15   # 1/6th
    BIAS_1_7= 0x14   # 1/7th
    BIAS_1_8= 0x13   # 1/8th
    BIAS_1_9= 0x12   # 1/9th
    BIAS_1_10 = 0x11   # 1/10th
    BIAS_1_11 = 0x10   # 1/11th

    def __init__(self, spi, rst, ce, dc, light, pwr=None):
      self.width= 84
      self.height = 48
      self.power      = self.POWER_DOWN
      self.addressing = self.ADDRESSING_HORIZ
      self.instr      = self.INSTR_BASIC
      self.display_mode = self.DISPLAY_BLANK
      self.temp_coeff = self.TEMP_COEFF_0
      self.bias       = self.BIAS_1_11
      self.voltage    = 3060

      # init the SPI bus and pins
      spi.init(spi.MASTER, baudrate=328125, bits=8, polarity=0, phase=1, firstbit=spi.MSB)
      if "OUT_PP" in dir(rst):
            # pyBoard style
            rst.init(rst.OUT_PP, rst.PULL_NONE)# Reset line
            ce.init(ce.OUT_PP, ce.PULL_NONE)   # Chip Enable
            dc.init(dc.OUT_PP, dc.PULL_NONE)   # Data(1) / Command(0) mode
            light.init(light.OUT_PP, light.PULL_NONE)
            if pwr:
                pwr.init(pwr.OUT_PP, pwr.PULL_NONE)
      else:
            # WiPy style
            rst.init(rst.OUT, None)
            ce.init(ce.OUT, None)
            dc.init(dc.OUT, None)
            light.init(light.OUT, None)
            if pwr:
                pwr.init(pwr.OUT, None)

      self.spi   = spi
      self.rst   = rst
      self.ce    = ce
      self.dc    = dc
      self.light = light
      self.pwr   = pwr

      self.light_off()
      self.power_on()
      self.ce.value(1)# set chip to disable (don't listen to input)
      self.reset()
      self.set_contrast(0xbf)
      self.clear()
      self.lcd_font = font.FONT6_8()
      self.chinese = chinese.CN_UTF8()


    def _set_function(self):
      """ Write current power/addressing/instructionset values to lcd. """
      value = 0x20 | self.power | self.addressing | self.instr
      self.command()

    def set_power(self, power, set=True):
      """ Sets the power mode of the LCD controller """
      assert power in , "Power must be POWER_UP or POWER_DOWN."
      self.power = power
      if set:
            self._set_function()

    def set_adressing(self, addr, set=True):
      """ Sets the adressing mode """
      assert addr in , "Addressing must be ADDRESSING_HORIZ or ADDRESSING_VERT."
      self.addressing = addr
      if set:
            self._set_function()

    def set_instr(self, instr, set=True):
      """ Sets instruction set (basic/extended) """
      assert instr in , "Instr must be INSTR_BASIC or INSTR_EXT."
      self.instr = instr
      if set:
            self._set_function()

    def set_display(self, display_mode):
      """ Sets display mode (blank, black, normal, inverse) """
      assert display_mode in , "Mode must be one of DISPLAY_BLANK, DISPLAY_ALL, DISPLAY_NORMAL or DISPLAY_INVERSE."
      assert self.instr == self.INSTR_BASIC, "Please switch to basic instruction set first."
      self.display_mode = display_mode
      self.command()

    def set_temp_coeff(self, temp_coeff):
      """ Sets temperature coefficient (0-3) """
      assert 4 <= temp_coeff < 8, "Temperature coefficient must be one of TEMP_COEFF_0..TEMP_COEFF_3."
      assert self.instr == self.INSTR_EXT, "Please switch to extended instruction set first."
      self.temp_coeff = temp_coeff
      self.command()

    def set_bias(self, bias):
      """ Sets the LCD bias. """
      assert 0x10 <= bias <= 0x17, "Bias must be one of BIAS_1_4..BIAS_1_11."
      assert self.instr == self.INSTR_EXT, "Please switch to extended instruction set first."
      self.bias = bias
      self.command()

    def set_voltage(self, millivolts):
      """ Sets the voltage of the LCD charge pump in millivolts. """
      assert 3060 <= millivolts <= 10680, "Voltage must be between 3,060 and 10,680 mV."
      assert self.instr == self.INSTR_EXT, "Please switch to extended instruction set first."
      self.voltage = millivolts
      basevoltage = millivolts - 3060
      incrementor = basevoltage // 60
      code = 0x80 & incrementor
      self.command()

    def set_contrast(self, value):
      """ set LCD voltage, i.e. contrast """
      assert 0x80 <= value <= 0xff, "contrast value must be between 0x80 and 0xff"
      self.command()
      # 0x21 - enter extended instruction set (H=1)
      # 0x06 - set temperature coefficient 2
      # 0x14 - set BIAS system to n=3 (recomm. mux rate 1:40/1:34)
      # value - (80-ff) - set Vop (80 = 3.00V, ff = 10.68V), 8b seems to work (0x3b/d70: 3.00+(70*0.06)=7.2V)
      # 0x20 - back to basic instruction set
      # 0x0c - normal display mode

    def position(self, x, y):
      """ set cursor to bank y, column x """
      assert 0 <= x < self.width, "x must be between 0 and 83"
      assert 0 <= y < self.height // 8, "y must be between 0 and 5"
      assert self.instr == self.INSTR_BASIC, "Please switch to basic instruction set first."
      self.command()

    def clear(self):
      """ clear screen """
      self.position(0, 0)
      self.data( * (self.height * self.width // 8))
      self.position(0, 0)

    def sleep_ms(self, mseconds):
      try:
            time.sleep_ms(mseconds)
      except AttributeError:
            machine.delay(mseconds)

    def sleep_us(self, useconds):
      try:
            time.sleep_us(useconds)
      except AttributeError:
            machine.udelay(useconds)

    def power_on(self):
      if self.pwr:
            self.pwr.value(1)
      self.reset()

    def reset(self):
      """ issue reset impulse to reset the display """
      self.rst.value(0)# RST on
      self.sleep_us(100) # reset impulse has to be >100 ns and <100 ms
      self.rst.value(1)# RST off
      # Defaults after reset:
      self.power      = self.POWER_DOWN
      self.addressing = self.ADDRESSING_HORIZ
      self.instr      = self.INSTR_BASIC
      self.display_mode = self.DISPLAY_BLANK
      self.temp_coeff = self.TEMP_COEFF_0
      self.bias       = self.BIAS_1_11
      self.voltage    = 3060

    def power_off(self):
      self.clear()
      self.command()
      # 0x20 - basic instruction set
      # 0x08 - set display to blank (doesn't delete contents)
      self.sleep_ms(10)
      if self.pwr:
            self.pwr.value(0) # turn off power

    def command(self, arr):
      """ send bytes in command mode """
      self.bitmap(arr, 0)

    def data(self, arr):
      """ send bytes in data mode """
      self.bitmap(arr, 1)

    def bitmap(self, arr, dc):
      self.dc.value(dc)
      buf = struct.pack('B'*len(arr), *arr)
      self.ce.value(0) # set chip to listening/enable
      try:
            self.spi.send(buf)
      except AttributeError:
            self.spi.write(buf)
      self.ce.value(1) # set chip to disable

    def light_on(self):
      self.light.value(0)# pull to GND

    def light_off(self):
      self.light.value(1)# set to HIGH

    def lcd_write_string(self, string, x, y):
      self.position(x,y)
      for i in string:
            self.data(self.lcd_font.get_font6_8(i))
   
    def lcd_write_chineses(str,x,y,space = 9):
      # i,j=0,0
      # lsLen = len(str)
      # while (j<lsLen)
            # self.lcd_write_chinese(str,x+(i*space),y)
            # i+=1
            # j+=1
      return 0
   
    def lcd_write_chinese(self,data,x,y):
      #获取 字 的UTF8码
      code = 0x00 #赋初值
      data_code = data.encode("UTF-8")
      code |= data_code<<16
      code |= data_code<<8
      code |= data_code
      #获取 字 的UTF8码 END
      self.position(x,y)
      self.data(self.chinese.get_chinese_utf8(code,0))
      self.position(x,y+1)
      self.data(self.chinese.get_chinese_utf8(code,1))

#boot.py

//转载请注明:@小五义http://www.cnblogs.com/xiaowuyiQQ群:64770604
# boot.py -- run on boot-up
# can run arbitrary Python, but best to keep it minimal

import machine
import pyb
#pyb.main('main.py') # main script to run after this one
#pyb.usb_mode('CDC+MSC') # act as a serial and a storage device
#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse

#main.py
# main.py -- put your code here!
import pyb
import upcd8544
from machine import SPI,Pin

def main():
    lcd_5110.lcd_write_chinese('萝',14,0)
    lcd_5110.lcd_write_chinese('卜',30,0)
    lcd_5110.lcd_write_chinese('智',46,0)
    lcd_5110.lcd_write_chinese('能',62,0)


    pyb.delay(1000)

if __name__ == '__main__':

    SPI = pyb.SPI(1) #DIN=>X8-MOSI/CLK=>X6-SCK

    RST    = pyb.Pin('X1')
    CE   = pyb.Pin('X2')
    DC   = pyb.Pin('X3')
    LIGHT= pyb.Pin('X4')
    lcd_5110 = upcd8544.PCD8544(SPI, RST, CE, DC, LIGHT)
    while(1):
   main()

实现效果如图:


以上提到的程序原代码及工具下载地址:https://pan.baidu.com/s/1eRZZd1C

独行者 发表于 2017-1-25 09:22:01

楼主辛苦谢谢分享!
页: [1]
查看完整版本: [TPYBoard-Micropython之会python就能做硬件 2] 利用micropython控制NOKIA 5110屏