# SPI_ILI9341 #### 組員: A1105129 吳祥毅 M1115114 楊皓翔 #### 指導老師:林宏益 --- ### 一、實驗目的 SPI是一種微控制器常用的通訊界面,常用於顯示屏幕和感測器,本次實驗使用Raspberry Pi和ILI9341搭配實踐顯示和觸控功能。 ### 二、實驗原理 * SPI是一種一主多從的介面,MISO、MOSI作為雙向資料傳輸,SCLK作為同步時鐘線,SS作為選擇從屬裝置(每個從屬裝置都有一條獨立的SS線,且只有SS線是獨立的)。 * SPI支持全雙工通訊,資料可以同時在兩個方向上傳輸。 * 在多從機的情況下,需要更多的引腳,不如I2C那樣節省線路。 * ILI9341是一種低功耗TFT LCD,具320x240像素解析度,支持觸控功能。 ### 三、實驗材料 1. 樹莓派(Raspberry Pi 1) 2. UART模組 3. ILI9341 ### 四、實驗步驟 **1. 背景色更換** ```python= from PIL import Image, ImageDraw, ImageFont import RPi.GPIO as GPIO import spidev from time import sleep from lib_tft24T import TFT24T # Raspberry Pi配置 DC = 24 RST = 25 LED = 18 PEN = 17 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) spi = spidev.SpiDev() TFT = TFT24T(spi, GPIO, landscape=True) TFT.initLCD(DC, RST, LED) TFT.backlite(True) TFT.initTOUCH(pen=PEN, ce=1, spi_speed=100000) draw = TFT.draw() colors = ["red", "green", "blue", "yellow", "purple"] color_index = 0 draw.rectangle((0, 0, 240, 320), fill=colors[color_index]) TFT.display() while True: if TFT.penDown(): color_index = (color_index + 1) % len(colors) draw.rectangle((0, 0, 240, 320), fill=colors[color_index]) TFT.display() sleep(0.3) sleep(0.1) ``` **2. 圈圈叉叉** ```python= import RPi.GPIO as GPIO import spidev from time import sleep from lib_tft24T import TFT24T DC = 24 RST = 25 LED = 18 PEN = 17 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) spi = spidev.SpiDev() TFT = TFT24T(spi, GPIO, landscape=True) TFT.initLCD(DC, RST, LED) TFT.backlite(True) TFT.initTOUCH(pen=PEN, ce=1, spi_speed=100000) draw = TFT.draw() board = [" "] * 9 current_player = "X" def draw_board(): draw.rectangle((0, 0, 240, 240), fill="black") for i in range(3): for j in range(3): x = j * 80 y = i * 80 draw.rectangle((x, y, x + 80, y + 80), outline="white", width=2) if board[i * 3 + j] == "X": draw.line((x + 10, y + 10, x + 70, y + 70), fill="red", width=5) draw.line((x + 70, y + 10, x + 10, y + 70), fill="red", width=5) elif board[i * 3 + j] == "O": draw.ellipse((x + 10, y + 10, x + 70, y + 70), outline="blue", > TFT.display() draw_board() def check_win(player): for i in range(3): if (board[i * 3] == board[i * 3 + 1] == board[i * 3 + 2] == player or board[i] == board[i + 3] == board[i + 6] == player): return True return (board[0] == board[4] == board[8] == player or board[2] == board[4] == board[6] == player) def get_cell(pos): x, y = pos if x >= 240 or y >= 240: return None cell_index = int(x // 80) + (int(y // 80) * 3) if 0 <= cell_index < 9: return cell_index else: return None while True: if TFT.penDown(): pos = TFT.penPosition() if pos != [0, 0]: cell = get_cell(pos) if cell is not None and board[cell] == " ": board[cell] = current_player if check_win(current_player): print(f"Player {current_player} wins!") break current_player = "O" if current_player == "X" else "X" draw_board() sleep(0.1) ``` **3. PIN腳選擇** **BCM pin numbers** +5 -> +5 GND > GND CE -> CE0 RESET -> GPIO25 D/C -> GPIO24 SDO/MOSI -> MOSI SCK -> SCLK LED -> GPIO18 SDI/MISO -> n/c t_CLK -> SCLK t_CS -> CE1 t_DIN/MOSI -> MOSI t_DO/MISO -> MISO t_IRQ -> GPIO17 >**解釋** D/C用於指示樹莓派發送的數據是控制命令還是顯示數據,而SDO/MOSI線用於實際傳輸這些數據。 ### 五、實驗結果 **1. 更換背景色** ![3659_0](https://hackmd.io/_uploads/B1k0cjp7T.jpg) ![3660_0](https://hackmd.io/_uploads/HkECqjpmp.jpg) >**結論** > >使用lib_tft24T操作硬體、spidev用於SPI通訊,定義一個顏色陣列,如果偵測到觸摸,顏色的index增加,從而改變顏色。 --- **2. 圈圈叉叉** ![3658_0](https://hackmd.io/_uploads/r1vxso6Xp.jpg) >**結論** >先初始化繪製九宮格, >(1)定義draw_board的函式繪製 O 和 X 。 >(2)定義check_win檢查是否有同列、同行和對角是否連線判斷勝利。 >(3)定義get_cell檢查點擊位置是否在九宮格內。 --- ### 六、實驗討論&心得 在實驗中,我們學習到SPI的通訊方式,並且使用TFT LCD實踐整個專案流程,對SPI的硬體操作建立了基礎,由於顯示端MISO不用傳回資料給樹梅派所以可以空下,讓觸控端的MISO使用即可。 ### 七、參考文獻 :::danger 參考文獻 : * [ILI9341] https://github.com/pcbcrew-org/pcbcrew-raspi-spilcd :::