2020年10月10日 星期六

SPI串列通訊實作Part2 – MAX7219 7段LED顯示

SPI串列通訊實作Part2 – MAX7219 7LED顯示

電路圖

 

程式列表

  • max7219_8digit.py

 

# Reference:

#   Micropython driver for the max7219 with 8 x 7segment display

#   https://github.com/pdwerryhouse/max7219_8digit

 

CHAR_MAP = {

  ' ': 0x00, '0': 0x7e, '1': 0x30, '2': 0x6d,

  '3': 0x79, '4': 0x33, '5': 0x5b, '6': 0x5f,

  '7': 0x70, '8': 0x7f, '9': 0x7b, 'a': 0x77,

  'b': 0x1f, 'c': 0x4e, 'd': 0x3d, 'e': 0x4f,

  'f': 0x47, 'g': 0x7b, 'h': 0x37, 'i': 0x30,

  'j': 0x3c, 'k': 0x57, 'l': 0x0e, 'm': 0x54,

  'n': 0x15, 'o': 0x1d, 'p': 0x67, 'q': 0x73,

  'r': 0x05, 's': 0x5b, 't': 0x0f, 'u': 0x1c,

  'v': 0x3e, 'w': 0x2a, 'x': 0x37, 'y': 0x3b,

  'z': 0x6d, 'A': 0x77, 'B': 0x1f, 'C': 0x4e,

  'D': 0x3d, 'E': 0x4f, 'F': 0x47, 'G': 0x7b,

  'H': 0x37, 'I': 0x30, 'J': 0x3c, 'K': 0x57,

  'L': 0x0e, 'M': 0x54, 'N': 0x15, 'O': 0x1d,

  'P': 0x67, 'Q': 0x73, 'R': 0x05, 'S': 0x5b,

  'T': 0x0f, 'U': 0x1c, 'V': 0x3e, 'W': 0x2a,

  'X': 0x37, 'Y': 0x3b, 'Z': 0x6d, ' ': 0x00,

  '-': 0x01, '\xb0': 0x63, '.': 0x80

}

 

REG_NO_OP       = const(0x00)

REG_DIGIT_BASE  = const(0x01)

REG_DIGIT0      = const(0x01)

REG_DIGIT1      = const(0x02)

REG_DIGIT2      = const(0x03)

REG_DIGIT3      = const(0x04)

REG_DIGIT4      = const(0x05)

REG_DIGIT5      = const(0x06)

REG_DIGIT6      = const(0x07)

REG_DIGIT7      = const(0x08)

REG_DECODE_MODE = const(0x09)   #Decode-Mode Register

  # 0x00: No decode for digits 7¡V0

  # 0x01: Code B decode for digit 0,No decode for digits 7¡V1

  # 0x0F: Code B decode for digits 3¡V0, No decode for digits 7¡V4

  # 0xFF: Code B decode for digits 7¡V0,

REG_INTENSITY   = const(0x0A)   #Intensity Register Format

  #       MAX7219 MAX7221

  # 0x00:  1/16    1/32

  # 0x01:  3/32    2/16

  # 0x02:  5/32    3/16

  # 0x03:  7/32    4/16

  # 0x04:  9/32    5/16

  # 0x05: 11/32    6/16

  # 0x06: 13/32    7/16

  # 0x07: 15/32    8/16

  # 0x08: 17/32    9/16

  # 0x09: 19/32   10/16

  # 0x0A: 21/32   11/16

  # 0x0B: 23/32   12/16

  # 0x0C: 25/32   13/16

  # 0x0D: 27/32   14/16

  # 0x0E: 29/32   15/16

  # 0x0F: 15/16   31/32

REG_SCAN_LIMIT  = const(0x0B)   #Scan-Limit Register Format

  # 0x00: Display digits 0 X X X X X X X

  # 0x01: Display digits 0 1 X X X X X X

  # 0x02: Display digits 0 1 2 X X X X X

  # 0x03: Display digits 0 1 2 3 X X X X

  # 0x04: Display digits 0 1 2 3 4 X X X

  # 0x05: Display digits 0 1 2 3 4 5 X X

  # 0x06: Display digits 0 1 2 3 4 5 6 X

  # 0x07: Display digits 0 1 2 3 4 5 6 7

REG_SHUTDOWN    = const(0x0C)   #Shutdown Register Format

  # 0x00  Shutdown Mode

  # 0x01  Normal Operation

REG_DISPLAY_TEST  = const(0x0F)   #Display-Test Register Format

  # 0x00  Normal Operation

  # 0x01  Display Test Mode

 

NUM_DIGITS      = 8

 

class Display7seg:

  def __init__(self, spi, intensity=7):

    self.spi = spi

    self.buffer = bytearray(NUM_DIGITS)

    self.intensity = intensity

    self.init()

 

  def init(self):

    for command, data in (

      (REG_DECODE_MODE, 0),

      (REG_INTENSITY, self.intensity),

      (REG_SCAN_LIMIT, 7),

      (REG_DISPLAY_TEST, 0),

      (REG_SHUTDOWN, 1),

    ):

      self.set_register(command, data)

 

  def set_register(self, register, value):

    self.spi.write(bytearray([value, register]))

 

  def write_to_buffer(self, s):

    l = len(s)

    if l < NUM_DIGITS:

      s = "%-8s" % s

    for i in range(0,NUM_DIGITS):

      self.buffer[7-i] = self.decode_char(s[i])

 

  def decode_char(self, c):

    d = CHAR_MAP.get(c)

    return d if d != None else ' '

 

  def write_number(self, value, zeroPad=False, leftJustify=False):

    # Take number, format it, look up characters then pass to buffer.

 

    if len(str(value)) > NUM_DIGITS:

      raise OverflowError('{0} too large for display'.format(value))

 

    size = NUM_DIGITS

    formatStr = '%'

 

    if zeroPad:

      formatStr += '0'

 

    if leftJustify:

      size *= -1

 

    formatStr = '{fmt}{size}i'.format(fmt=formatStr, size=size)

    position = REG_DIGIT7

    strValue = formatStr % value

 

    # look up each digit's character

    # then send to buffer

    for char in strValue:

      self.buffer[position - 1] = self.letter(char)

      position -= 1

 

  def letter(self, char):

    # Look up character on digits table & return

    value = CHAR_MAP.get(str(char))

    return value

 

  def intensity(self, i):

    self.send(self.intensity, i)

 

  def show(self):

    for y in range(0,NUM_DIGITS):

      self.set_register(REG_DIGIT_BASE + y, self.buffer[y])

 

  • max7219_8digit_Test.py

from machine import KEY  #獲取按鍵KEY

from machine import SPI, PIN

import max7219_8digit

import utime

 

# Connections:

# 腳位定義  SPI0  SPI1     MAX7219

# 3V3                      VCC

# GND                      GND

# MOSI       P15  P26  ->  DIN

# CS         P16  P23  ->  CS

# CLK        P13  P24  ->  CLK

# MISO       P14  P25  ->  DOUT

 

spi_1  = None

spi_1 =SPI(1, mode=SPI.MASTER, baudrate=5000000, polarity=1, phase=0) #For Hardware SPI bus

         #baudrate is the SCK clock rate.

         #polarity can be 0 or 1, and is the level the idle clock line sits at.

         #phase can be 0 or 1 to sample data on the first or second clock edge respectively.

         #bits is the width in bits of each transfer. Only 8 is guaranteed to be supported by all hardware.

         #firstbit can be SPI.MSB or SPI.LSB.

 

# Start Function

if __name__ == '__main__':

  key_c = KEY(KEY.KEYC)    #創建按鍵C

 

  display = max7219_8digit.Display7seg(spi_1)

  display.write_to_buffer('EPYTHON')

  display.show()

  utime.sleep_ms(1000)

 

  for NUM in range(0,50000):

    display.write_number(NUM)

    display.show()

 

    if key_c.value() == 0:      #如果按鍵C被按下

      break

    utime.sleep_ms(100)

 

spi_1 .deinit()