[Python] How can I connect an LCD to an Up Squared Board using spidev?

Discussão em 'Python' iniciado por Stack, Março 3, 2025.

  1. Stack

    Stack Membro Participativo

    Original Board: Raspberry Pi 4 model B New Board: Up Squared 7100 LCD: NHD-PCB12832A1Zrev2

    import RPi.GPIO as GPIO
    from ascii_values import ASCII168
    import icon_manager

    # Mapping based on BCM (Broadcom) pinout from https://pinout.xyz/
    LCD_CS = 8
    LCD_RST = 22
    LCD_A0 = 23
    LCD_CLK = 11
    LCD_SI = 10


    class LCD:
    _instance = None

    def __new__(cls, *args, **kwargs):
    """Ensure only one instance of the LCD class exists."""
    if cls._instance is None:
    cls._instance = super(LCD, cls).__new__(cls)
    cls._instance._initialize_lcd()
    return cls._instance

    def __del__(self):
    GPIO.cleanup()

    def _initialize_lcd(self):
    self.io_init()
    self.lcd_init()
    GPIO.setwarnings(False)

    def cleanup(self):
    GPIO.cleanup()

    def io_init(self):
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(LCD_CS, GPIO.OUT)
    GPIO.setup(LCD_RST, GPIO.OUT)
    GPIO.setup(LCD_A0, GPIO.OUT)
    GPIO.setup(LCD_CLK, GPIO.OUT)
    GPIO.setup(LCD_SI, GPIO.OUT)

    def lcd_init(self):
    GPIo_Output(LCD_CS, True)
    GPIo_Output(LCD_RST, False)
    GPIo_Output(LCD_RST, True)
    self.lcd_transfer_data(0xe2, 0) # Internal reset

    self.lcd_transfer_data(0xa2, 0) # Sets the LCD drive voltage bias ratio
    ##A2: 1/9 bias
    ##A3: 1/7 bias (ST7565V)

    self.lcd_transfer_data(0xa0, 0) # Sets the display RAM address SEG output correspondence
    ##A0: normal
    ##A1: reverse

    self.lcd_transfer_data(0xc8, 0) # Select COM output scan direction
    ##C0~C7: normal direction
    ##C8~CF: reverse direction

    self.lcd_transfer_data(0xa4, 0) # Display all points ON/OFF
    ##A4: normal display
    ##A5: all points ON

    self.lcd_transfer_data(0xa6, 0) # Sets the LCD display normal/inverted
    ##A6: normal
    ##A7: inverted

    self.lcd_transfer_data(0x2F, 0) # Select internal power supply operating mode
    ##28~2F: Operating mode

    self.lcd_transfer_data(0x40, 0) # Display start line set
    ##40~7F: Display start address

    self.lcd_transfer_data(0x20, 0) # V5 voltage regulator internal resistor ratio set (contrast)
    ##20~27: small~large

    self.lcd_transfer_data(0x81, 0) # Electronic volume mode set
    ##81: Set the V5 output voltage

    self.lcd_transfer_data(0x30, 0) # Electronic volume register set
    ##00~3F: electronic volume register

    self.lcd_transfer_data(0b10101111, 0) # Display ON/OFF
    ## 0b10101111: ON
    ## 0b10101110: OFF
    self.lcd_clear()

    def display_icon(self, x_pos, y_pos, icon, negative=False):
    icon_matrix = icon_manager.format_icon(icon, negative)

    if not isinstance(icon_matrix, list) or not all(isinstance(i, int) for i in icon_matrix):
    raise TypeError("icon_matrix must be a list of integers")

    quadrant_offsets = [
    (0, 0, 0, 8), # Quadrant 1: Top-left
    (1, 0, 8, 16), # Quadrant 2: Bottom-left
    (0, 8, 16, 24), # Quadrant 3: Top-right
    (1, 8, 24, 32), # Quadrant 4: Bottom-right
    ]

    for y_offset, x_offset, start_idx, end_idx in quadrant_offsets:
    self.lcd_set_page(y_pos + y_offset, x_pos + x_offset)
    # Transfer the entire quadrant data at once
    data = icon_matrix[start_idx:end_idx]
    self.lcd_transfer_data_bulk(data)

    def lcd_ascii168_string(self, x_pos, y_pos, string):
    string_len = len(string)
    for i in range(0, string_len):
    self.lcd_ascii168(x_pos + i * 8, y_pos, ord(string) - 32)

    def lcd_ascii168(self, x_pos, y_pos, char):
    self.lcd_set_page(y_pos, x_pos)

    for i in range(0, 8):
    self.lcd_transfer_data(ASCII168[char], 1)

    self.lcd_set_page(y_pos + 1, x_pos)
    for i in range(8, 16):
    self.lcd_transfer_data(ASCII168[char], 1)

    def lcd_clear(self):
    GPIo_Output(LCD_CS, False)
    for i in range(0, 8):
    self.lcd_set_page(i, 0)
    for j in range(0, 128):
    self.lcd_transfer_data(0x00, 1)
    GPIo_Output(LCD_CS, True)

    def lcd_set_page(self, page, column):
    lsb = column & 0x0f
    msb = column & 0xf0
    msb >>= 4
    msb |= 0x10
    page |= 0xb0
    self.lcd_transfer_data(page, 0)
    self.lcd_transfer_data(msb, 0)
    self.lcd_transfer_data(lsb, 0)

    def lcd_transfer_data(self, value, A0):
    GPIo_Output(LCD_CS, False)
    GPIo_Output(LCD_CLK, True)
    if (A0):
    GPIo_Output(LCD_A0, True)
    else:
    GPIo_Output(LCD_A0, False)
    self.lcd_byte(value)
    GPIo_Output(LCD_CS, True)

    def lcd_transfer_data_bulk(self, data_list):
    """Transfers a list of data in bulk, minimizing GPIO operations."""
    GPIo_Output(LCD_CS, False)
    GPIo_Output(LCD_CLK, True)

    for data in data_list:
    GPIo_Output(LCD_A0, True) # Data mode
    self.lcd_byte(data)

    GPIo_Output(LCD_CS, True)

    def lcd_byte(self, bits):
    tmp = bits
    for i in range(0, 8):
    GPIo_Output(LCD_CLK, False)
    if (tmp & 0x80):
    GPIo_Output(LCD_SI, True)
    else:
    GPIo_Output(LCD_SI, False)
    tmp = (tmp << 1)
    GPIo_Output(LCD_CLK, True)



    I am able to send data to display on the LCD using the RPi.GPIO package; however, I want to run the code on an up squared board and the RPi.GPIO package does not work on a non-raspberry pi.

    I am using an UP Squared 7100 that has the same 40 pin header as a Raspberry Pi. I am trying to connect to the LCD using the spidev package

    Continue reading...

Compartilhe esta Página