树莓派 python 驱动 lcd tft spi 2.8寸 ili9341 240x320

树莓派 python 驱动 lcd tft spi 2.8寸 ili9341 240x320

1. 驱动效果

娃开车图
在这里插入图片描述

2. 屏幕及接线

屏幕我某宝直接购买的,价钱31.5
在这里插入图片描述
接线图:
在这里插入图片描述

3. python驱动代码

写的不严谨,但是能驱动,作为入门吧。详见注释
代码中,需要先解析图片的每个像素,再spi写入屏幕芯片。解析图片耗时挺长的,见日志输出:

pi@raspberrypi:~ $ python3 ili9341Driver.py
setWindow donw
picReadTimeConsuming = 6.100s , SpiTimeConsuming = 0.128s

具体代码见下:

# coding : UTF-8
import time #用于计算spi刷新整个屏幕所用时长
import RPi.GPIO as GPIO #用于操作引脚
import spidev #树莓派与屏幕的交互协议为SPI,说明见:https://github.com/doceme/py-spidev
from PIL import Image, ImageFont, ImageDraw #用于创建画布,或者读取具体路径下的图片。给图片添加文字。
screenWidth = 320 #屏幕长度
screenHeight = 240 #屏幕宽度
PinDC = 18 #GPIO.BOARD引脚模式,第18号引脚
PinReset = 22  #GPIO.BOARD引脚模式,第22号引脚
PinLED=12 #GPIO.BOARD引脚模式,第12号引脚

def LCDReset(): #重置电平时序
    GPIO.output(PinReset, 1)
    time.sleep(.2)
    GPIO.output(PinReset, 0)
    time.sleep(.2)
    GPIO.output(PinReset, 1)
    time.sleep(.2)
    
def sendCommand(command, *bytes): #发送指令(DC为低电平)和数据(DC为高电平)
    GPIO.output(PinDC, 0)
    spi.writebytes([command])
    if len(bytes) > 0:
        GPIO.output(PinDC, 1)
        spi.writebytes(list(bytes))
        
def sendManyBytes(bytes): #发送屏幕数据
    GPIO.output(PinDC, 1)
    spi.writebytes(bytes)
    
def init(): #屏幕初始化
    GPIO.output(PinLED, 1) #LED.high();
    LCDReset()
    sendCommand(0xEF,0x03,0x80,0x02);
    sendCommand(0xCF,0x00,0XC1,0X30);
    sendCommand(0xED,0x64,0x03,0X12,0X81);
    sendCommand(0xE8,0x85,0x00,0x78);
    sendCommand(0xCB,0x39,0x2C,0x00,0x34,0x02);
    sendCommand(0xF7,0x20);
    sendCommand(0xEA,0x00,0x00);
    sendCommand(0xC0,0x23);   # Power control --VRH[5:0]
    sendCommand(0xC1,0x10);   # Power control # SAP[2:0];BT[3:0]
    sendCommand(0xC5,0x3e,0x28);   # VCM control
    sendCommand(0xC7,0x86);    # VCM control2
    sendCommand(0x36,0x48);    #  Memory Access Control
    sendCommand(0x3A,0x55);
    sendCommand(0xB1,0x00,0x18);
    sendCommand(0xB6,0x08,0x82,0x27);    #  Display Function Control
    sendCommand(0xF2,0x00);             #  3Gamma Function Disable
    sendCommand(0x26,0x01);    # Gamma curve selected
    sendCommand(0xE0,0x0F,0x31,0x2B,0x0C,0x0E,0x08,0x4E,0xF1,0x37,0x07,0x10,0x03,0x0E,0x09,0x00);    # Set Gamma
    sendCommand(0xE1,0x00,0x0E,0x14,0x03,0x11,0x07,0x31,0xC1,0x48,0x08,0x0F,0x0C,0x31,0x36,0x0F);    # Set Gamma
    sendCommand(0x11);   # Exit Sleep
    sendCommand(0x29);    # Display on
    
def setWindow():
    sendCommand(0x2A);       # Column addr set
    x0 = 0;
    bytes = []
    bytes.append(x0 >> 8)
    bytes.append(x0)
    sendManyBytes(bytes);              # XSTART
    x1 = screenHeight - 1;
    bytes = []
    bytes.append(x1 >> 8)
    bytes.append(x1)
    sendManyBytes(bytes);       # XEND
    sendCommand(0x2B);      # Row addr set
    bytes = []
    bytes.append(0 >> 8)
    bytes.append(0)
    sendManyBytes(bytes);           # YSTART
    y1 =  screenWidth - 1;
    bytes = []
    bytes.append(y1 >> 8)
    bytes.append(y1)
    sendManyBytes(bytes);       # YEND
    sendCommand(0x2C);
    print('setWindow donw')
    
def drawImg16BitColor(img320x240): #入参为320x240像素的image对象
    init()
    setWindow();
    bytes = []
    i = 0;
    GPIO.output(PinDC, 1)
    picReadStartTime = time.time()
    for x in range(0, screenWidth):
        for y in range(screenHeight - 1, -1, -1):
            colorValue = img320x240.getpixel((x, y))
            red = colorValue[0]
            green = colorValue[1]
            blue = colorValue[2]
            red = red >> 3;  # st7735s的红色占5位
            green = green >> 2;  # st7735s的绿色占6位
            blue = blue >> 3;  # st7735s的蓝色占5位
            highBit = 0 | (red << 3) | (green >> 3);  # 每个像素写入个字节,highBit高字节,lowBit低字节
            lowBit = 0 | (green << 5) | blue;
            bytes.append(highBit)
            bytes.append(lowBit)
    picReadTimeConsuming = time.time() - picReadStartTime #解析图像像素时长
    
    startTime = time.time()
    # screenWidth*screenHeight*2 每个像素写入2个字节。
    #以下for循环是为了控制每次传入的数组长度,防止这个报错,:OverflowError: Argument list size exceeds 4096 bytes.
    for j in range(2000, screenWidth * screenHeight * 2, 2000):  
        sendManyBytes(bytes[i:j])
        i = i + 2000
    sendManyBytes(bytes[i:screenWidth * screenHeight * 2])
    SpiTimeConsuming = time.time() - startTime #Spi写入像素数据时长
    print("picReadTimeConsuming = %.3fs , SpiTimeConsuming = %.3fs" % (picReadTimeConsuming, SpiTimeConsuming))

GPIO.setmode(GPIO.BOARD) #设置GPIO.BOARD引脚模式
GPIO.setwarnings(False)
GPIO.setup(PinDC, GPIO.OUT)
GPIO.setup(PinReset, GPIO.OUT)
GPIO.setup(PinLED, GPIO.OUT)
spi = spidev.SpiDev() #https://github.com/doceme/py-spidev
spi.open(0, 0) 
spi.max_speed_hz = 24000000 #通信时钟最大频率
spi.mode = 0x00 #SPI的模式,9341为模式spi0

image = Image.new('RGB', (screenWidth, screenHeight)) #可以使用代码新建画布

draw = ImageDraw.Draw(image)
setFont = ImageFont.truetype("/usr/share/fonts/myfont/MSYHBD.TTF", 32) #字体地址,请参考我这篇内容:https://blog.csdn.net/chenqide163/article/details/106933858
draw.text((35, 0), "离思", font=setFont, fill="#FFA500", direction=None)
setFont = ImageFont.truetype("/usr/share/fonts/myfont/MSYHBD.TTF", 16)
draw.text((105, 15), "元稹", font=setFont, fill="#00FFFF", direction=None)
setFont = ImageFont.truetype("/usr/share/fonts/myfont/MSYHBD.TTF", 20)
draw.text((0, 35), "曾经沧海难为水,", font=setFont, fill="#FFFF00", direction=None)
draw.text((0, 60), "除却巫山不是云。", font=setFont, fill="#FFFF00", direction=None)
draw.text((0, 85), "取次花丛懒回顾,", font=setFont, fill="#FFFF00", direction=None)
draw.text((0, 110), "半缘修道半缘君。", font=setFont, fill="#FFFF00", direction=None)
#也可以从地址读取图片文件,并缩放为320x240
image = Image.open('/home/pi/test.jpg');
image = image.convert('RGBA'); 
image = image.resize((screenWidth, screenHeight))  #也可以从地址读取图片文件,并缩放为160x128

drawImg16BitColor(image)
  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
连接LCD TFT SPI 2.8寸 ILI9341 240x320接口的步骤如下: 1. 将LCD TFT SPI 2.8寸 ILI9341 240x320接口的VCC引脚连接到msp430g2553的VCC引脚,GND引脚连接到msp430g2553的GND引脚,CS引脚连接到msp430g2553的P1.4引脚,DC引脚连接到msp430g2553的P1.3引脚,SDI引脚连接到msp430g2553的P1.7引脚,SCK引脚连接到msp430g2553的P1.5引脚,并且在LCD TFT SPI 2.8寸 ILI9341 240x320接口中设置引脚的电平。 2. 编写msp430g2553的代码,将LCD TFT SPI 2.8寸 ILI9341 240x320接口的初始化命令和显示命令通过SPI总线发送到LCD TFT SPI 2.8寸 ILI9341 240x320接口上,以控制LCD TFT SPI 2.8寸 ILI9341 240x320接口上的显示内容。 3. 在代码中实现LCD TFT SPI 2.8寸 ILI9341 240x320接口上的显示功能,包括清屏、绘制图形和文字等功能。 下面是一个示例代码,其中包含了注释,可以帮助你理解代码的作用: ``` #include <msp430.h> #include <stdint.h> #define CS BIT4 #define DC BIT3 void spi_init(void) { P1SEL |= BIT5 + BIT6 + BIT7; // 选择SPI引脚 P1SEL2 |= BIT5 + BIT6 + BIT7; UCB0CTL1 |= UCSWRST; // 禁用SPI UCB0CTL0 = UCCKPH + UCMSB + UCMST + UCSYNC; // 设置SPI模式 UCB0CTL1 = UCSSEL_2 + UCSWRST; // 选择时钟源 UCB0BR0 = 2; // 设置时钟分频 UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // 启用SPI } void write_command(uint8_t command) { P1OUT &= ~DC; // DC引脚拉低表示发送的是命令 P1OUT &= ~CS; // 使能芯片 UCB0TXBUF = command; // 发送命令 while (UCB0STAT & UCBUSY); // 等待发送完成 P1OUT |= CS; // 禁用芯片 } void write_data(uint8_t data) { P1OUT |= DC; // DC引脚拉高表示发送的是数据 P1OUT &= ~CS; // 使能芯片 UCB0TXBUF = data; // 发送数据 while (UCB0STAT & UCBUSY); // 等待发送完成 P1OUT |= CS; // 禁用芯片 } void write_data16(uint16_t data) { write_data(data >> 8); // 先发送高8位数据 write_data(data & 0xFF); // 再发送低8位数据 } void ili9341_init(void) { write_command(0x01); // 软复位 __delay_cycles(500000); write_command(0x11); // 退出睡眠模式 __delay_cycles(500000); write_command(0x3A); // 设置像素格式 write_data(0x55); write_command(0xC2); // 设置电源控制 write_data(0x0D); write_data(0x00); write_data(0x0E); write_data(0x08); write_command(0xC5); // 设置VCOM控制 write_data(0x3E); write_data(0x28); write_command(0xE0); // 设置Gamma校正 write_data(0x1F); write_data(0x1A); write_data(0x18); write_data(0x0A); write_data(0x0F); write_data(0x06); write_data(0x45); write_data(0x87); write_data(0x32); write_data(0x0A); write_data(0x07); write_data(0x02); write_data(0x07); write_data(0x05); write_data(0x00); write_command(0xE1); // 设置Gamma校正 write_data(0x00); write_data(0x25); write_data(0x27); write_data(0x05); write_data(0x10); write_data(0x09); write_data(0x3A); write_data(0x78); write_data(0x4D); write_data(0x05); write_data(0x18); write_data(0x0D); write_data(0x38); write_data(0x3A); write_data(0x1F); write_command(0xB1); // 设置像素时钟频率 write_data(0x00); write_data(0x10); write_command(0xB6); // 设置显示功能 write_data(0x0A); write_data(0xA2); write_command(0xF2); // 设置像素频率 write_data(0x00); write_command(0x26); // 设置Gamma校正 write_data(0x01); write_command(0x36); // 设置扫描方向 write_data(0x08); write_command(0x29); // 打开LCD显示 } void lcd_draw_pixel(uint16_t x, uint16_t y, uint16_t color) { write_command(0x2A); // 设置列地址 write_data16(x); write_data16(x); write_command(0x2B); // 设置行地址 write_data16(y); write_data16(y); write_command(0x2C); // 写入像素数据 write_data16(color); } void lcd_clear(uint16_t color) { uint16_t x, y; for (y = 0; y < 320; y++) { for (x = 0; x < 240; x++) { lcd_draw_pixel(x, y, color); } } } int main(void) { WDTCTL = WDTPW + WDTHOLD; // 禁用看门狗 P1DIR |= CS + DC; // 设置引脚方向为输出 P1OUT |= CS; // 禁用芯片 spi_init(); // 初始化SPI总线 ili9341_init(); // 初始化LCD TFT SPI 2.8寸 ILI9341 240x320接口 lcd_clear(0xFFFF); // 清屏,并且设置背景颜色为白色 while (1) { // 此处添加你的代码,实现其他功能 } } ``` 注释可以帮助你理解代码的作用,更好地编写代码,理解代码运行的过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值