python - How can I connect an LCD to an Up Squared Board using spidev? - Stack Overflow

admin2025-04-20  0

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 /
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[i]) - 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][i], 1)

        self.lcd_set_page(y_pos + 1, x_pos)
        for i in range(8, 16):
            self.lcd_transfer_data(ASCII168[char][i], 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

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745084872a284080.html

最新回复(0)