ข้ามไปยังเนื้อหา
Display Engineer
การแก้ปัญหา

GT911 ทัชไม่ทำงาน? วิธีแก้ที่อยู่ I2C, จังหวะรีเซ็ต, คอนฟิก และพิกัด

เช็กลิสต์ทีละขั้นสำหรับชิปคอนโทรลเลอร์ทัชแบบ capacitive GT911 ที่ไม่ถูกตรวจพบ ไม่มีสัญญาณทัช หรือรายงานพิกัดผิด: กำลังไฟและการสแกน I2C, ลำดับเลือกที่อยู่ผ่าน INT/RST, รีจิสเตอร์สถานะ 0x814E, ขอบของอินเทอร์รัพท์ และวิธีแก้ความละเอียดและแกนพิกัดสำหรับ Linux, ESP-IDF และ ESPHome

DEDisplay Engineer Applications Team · วิศวกรแอปพลิเคชันด้านจออัปเดต 19 ต.ค. 2569

เริ่มจากจุดนี้: จับคู่อาการ

อาการ

สาเหตุที่เป็นไปได้มากที่สุด

ไปที่

ไม่พบอะไรเลยที่ 0x5D หรือ 0x14 จากการสแกน I2C

คอนโทรลเลอร์ไม่มีไฟเลี้ยง ขาด pull-up หรือชิปถูกค้างอยู่ในสถานะรีเซ็ต

ขั้นตอนที่ 1

พบที่ 0x14 แต่ไดรเวอร์คาดหวัง 0x5D (หรือกลับกัน) หรือที่อยู่เปลี่ยนไปในแต่ละครั้งที่บูต

ระดับลอจิกขา INT ระหว่างรีเซ็ต

ขั้นตอนที่ 2

ตรวจพบอุปกรณ์ อ่าน product ID ได้ถูกต้อง แต่ไม่มีสัญญาณทัชเข้ามา

รีจิสเตอร์สถานะไม่ถูกเคลียร์ ขอบของอินเทอร์รัพท์ตั้งผิด หรือ INT ไม่ได้เดินสาย

ขั้นตอนที่ 3

มีสัญญาณทัชเข้ามาแต่ตำแหน่งผิด กลับด้าน หรือหมุน 90 องศา

ความละเอียดในคอนฟิกของ GT911 ไม่ตรงกับพาเนล หรือต้องสลับแกน

ขั้นตอนที่ 4

กำลังจะเขียนคอนฟิกบล็อกใหม่

อ่านส่วนนี้ก่อน

ขั้นตอนที่ 5

ทำตามขั้นตอนตามลำดับ ที่อยู่รีจิสเตอร์และจังหวะเวลาด้านล่างอ้างอิงจากไดรเวอร์ goodix ของ Linux, คอมโพเนนต์ esp_lcd_touch_gt911 ของ Espressif และเอกสารของ ESPHome; ลิงก์อยู่ในหมวด Sources

1. ตรวจสอบว่า GT911 มีไฟเลี้ยงและตอบสนองบน I2C

กำลังไฟและ pull-up

device-tree binding ของ Linux สำหรับคอนโทรลเลอร์ Goodix ระบุแหล่งจ่ายไฟ 2 สาย: AVDD28 (อนาล็อก) และ VDDIO (รางไฟของลอจิก I/O) บนโมดูลหรือ FPC ทั้งสองสายมักจ่ายจากคอนเนกเตอร์ของโฮสต์ ดังนั้นให้วัดไฟที่คอนเนกเตอร์ก่อนสงสัยที่เฟิร์มแวร์ นอกจากนี้ SDA และ SCL ยังต้องมีตัวต้านทาน pull-up อยู่ที่ใดที่หนึ่งบนบัส โดยโมดูลจอจำนวนมากไม่ได้มีมาให้

สแกนบัส

รันสเก็ตช์สแกน I2C หรือ i2cdetect GT911 จะตอบสนองที่ที่อยู่แบบ 7-bit ใดที่หนึ่งจากสองค่านี้:

ที่อยู่แบบ 7-bit

ไบต์ write / read แบบ 8-bit (ตามที่บางดาต้าชีตระบุ)

0x5D

0xBA / 0xBB

0x14

0x28 / 0x29

คู่ค่าแบบ 8-bit มาจากคอมเมนต์ในโค้ดรีเซ็ตของไดรเวอร์ Linux หากเอกสารของผู้ขายระบุ "address 0xBA" นั่นคืออุปกรณ์ตัวเดียวกับ 0x5D แบบ 7-bit; ให้ใส่ 0x5D ใน Arduino, ESP-IDF และ Linux

อ่าน product ID

รีจิสเตอร์บน GT911 ใช้ที่อยู่แบบ 16-bit ไดรเวอร์ Linux อ่าน 6 ไบต์จาก 0x8140: 4 ไบต์แรกคือ product ID เป็นข้อความ ASCII และ 2 ไบต์สุดท้ายคือเวอร์ชันเฟิร์มแวร์ (little-endian) GT911 จะรายงานสตริง 911 หากได้ 911 แปลว่าบัส ไฟเลี้ยง และที่อยู่ทำงานถูกต้องทั้งหมด และปัญหาอยู่ในขั้นตอนถัดไปของลิสต์นี้

หากไม่มีอะไรตอบสนองที่ทั้งสองที่อยู่ ให้ตรวจสอบว่าขา reset ไม่ได้ถูกค้างอยู่ที่ระดับ low บนโมดูลจำนวนมาก RST เป็นอินพุตของ GT911 และต้องถูกขับเป็น high โดยโฮสต์ (หรือ pull-up บนบอร์ด) ก่อนคอนโทรลเลอร์จะเริ่มทำงาน

2. จัดลำดับรีเซ็ตและการเลือกที่อยู่ให้ถูกต้อง

GT911 เลือกที่อยู่ I2C จากระดับลอจิกบนขา INT ในช่วงเวลาที่รีเซ็ตถูกปล่อย ตามคำของ device-tree binding ของ Linux ขา INT "is sampled by the device on reset deassertion to select the I2C client address"

ระดับลอจิกขา INT เมื่อ RST เป็น high

ที่อยู่ I2C

ต่ำ

0x5D

สูง

0x14

ลำดับขั้นตอนที่ไดรเวอร์ Linux ใช้

  1. จ่ายสัญญาณ RST เป็นระดับต่ำ แล้วรอมากกว่า 10 ms (ไดรเวอร์รอ 20 ms)
  2. จ่ายสัญญาณ INT ไปที่ระดับของที่อยู่ที่ต้องการ: สูงสำหรับ 0x14, ต่ำสำหรับ 0x5D
  3. รอมากกว่า 100 µs
  4. จ่ายสัญญาณ RST เป็นระดับสูง แล้วรอมากกว่า 5 ms (ไดรเวอร์รอ 6–10 ms)
  5. จ่ายสัญญาณ INT เป็นระดับต่ำนาน 50 ms จากนั้นสลับ INT เป็นโหมดอินพุต

หาก INT ลอย (floating) ระหว่างขั้นตอนที่ 4 ที่อยู่อาจต่างกันไปในแต่ละครั้งที่จ่ายไฟ นั่นคือสาเหตุคลาสสิกของรายงานปัญหา "แฟลชแล้วใช้งานได้ แต่ cold boot แล้วใช้งานไม่ได้"

ESP-IDF: esp_lcd_touch_gt911

คอมโพเนนต์ของ Espressif กำหนด ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS เป็น 0x5D และ ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP เป็น 0x14 โดยจะรันลำดับขั้นตอนเลือกที่อยู่ก็ต่อเมื่อครบทั้งสามเงื่อนไขนี้:

  • rst_gpio_num เป็น GPIO จริง (ไม่ใช่ GPIO_NUM_NC),
  • int_gpio_num เป็น GPIO จริง,
  • driver_data ชี้ไปที่ esp_lcd_touch_io_gt911_config_t ที่มี dev_addr เป็นที่อยู่ที่คุณต้องการ

มิฉะนั้นจะบันทึกล็อกว่า I2C address initialization procedure skipped - using default GT9xx setup แล้วทำรีเซ็ตแบบปกติ ในกรณีนี้ ที่อยู่จะเป็นไปตามที่การเดินสายของบอร์ดกำหนด และที่อยู่ I2C ของ panel-IO ที่คุณระบุต้องตรงกับผลการสแกน ค่าเริ่มต้น I2C clock ของคอมโพเนนต์ใน ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG() คือ 100 kHz

บอร์ดที่โฮสต์ไม่ได้ควบคุมขา INT

หาก INT ไม่ได้ต่อกับโฮสต์ โฮสต์จะเลือกที่อยู่ไม่ได้ จึงต้องสแกนทั้งสองที่อยู่แล้วใช้ที่อยู่ที่ตอบสนอง ยกตัวอย่างเช่น Sunton ESP32-8048S043C ขาอินเทอร์รัปต์ของ GT911 ไม่ได้เดินสายต่อกับ GPIO โดยค่าเริ่มต้น (ดูหน้าบอร์ดของเรา) หน้า GT911 ของ ESPHome ระบุว่าเมื่อ INT ต่อผ่าน IO expander ขานี้ยังคงถูกใช้ตั้งค่าที่อยู่ตอนบูต แต่การสัมผัสจะถูกอ่านแบบ polling แทนที่จะเป็นแบบ interrupt-driven

3. ตรวจพบชิปแต่ไม่มีอีเวนต์การสัมผัส

อ่านและเคลียร์สถานะเรจิสเตอร์

ข้อมูลการสัมผัสเริ่มต้นที่ 0x814E ไบต์แรกเป็นสถานะไบต์:

  • บิต 7 (0x80): บัฟเฟอร์พร้อม ข้อมูลใหม่จะใช้ได้ก็ต่อเมื่อบิตนี้ถูกเซ็ตเท่านั้น
  • บิต 0–3: จำนวนจุดสัมผัส ไดรเวอร์ Linux จะปฏิเสธค่าที่มากกว่าค่าสูงสุดที่ตั้งค่าไว้
  • บิต 4: มีการกดคีย์ (ปุ่ม)

จุดสัมผัสแต่ละจุดถัดจากนั้นมีขนาด 8 ไบต์: track ID ตามด้วย X, Y และ size เป็นค่า 16 บิตแบบ little-endian

หลังจากอ่านแล้ว ทั้งไดรเวอร์ Linux และ esp_lcd_touch_gt911 จะเขียนค่า 0 ลงที่ 0x814E หากคุณเขียนไดรเวอร์เอง ควรทำเช่นเดียวกัน การละเว้นการเขียนนี้เป็นสาเหตุที่พบบ่อยที่ทำให้ไดรเวอร์ที่เขียนเองเห็นเฉพาะการสัมผัสแรก

จับคู่ขอบสัญญาณอินเทอร์รัปต์ให้ตรงกัน

ประเภททริกเกอร์อยู่ในคอนฟิกูเรชันของ GT911 เอง: บิต 0–1 ของไบต์คอนฟิกที่ 0x804D (ออฟเซ็ต 6 จากจุดเริ่มต้นคอนฟิกที่ 0x8047) ไดรเวอร์ Linux แมปค่านี้ดังนี้:

ค่า

ประเภทอินเทอร์รัปต์

0

ขอบขึ้น (Rising edge)

1

ขอบลง (Falling edge)

2

ระดับต่ำ

3

ระดับสูง

ตั้งค่า GPIO interrupt ให้ตรงกัน ใน esp_lcd_touch_gt911 การกำหนด levels.interrupt = 1 จะเลือกขอบขาขึ้น (rising-edge) และ 0 จะเป็นขอบขาลง (falling edge)

ไม่มีขา INT? ใช้การ Poll แทน

การ Poll ใช้งานได้ดีสำหรับงาน HMI ESPHome จะ Poll ทุก 50 ms ตามค่าเริ่มต้น (update_interval) เมื่อไม่ได้ตั้งค่า interrupt_pin ส่วนไดรเวอร์ Linux เมื่อมี interrupt จะรอบิต ready นานสูงสุด 20 ms ก่อนยอมแพ้ต่อหนึ่งเฟรม

4. จุดสัมผัสอยู่ผิดตำแหน่ง

ตรวจสอบค่าความละเอียดที่เก็บไว้ใน GT911

GT911 รายงานค่าพิกัดตามความละเอียดที่เขียนไว้ในคอนฟิกูเรชันของมันเอง ไม่ใช่ตามความละเอียดของจอแสดงผลของคุณ ตามไดรเวอร์ Linux ค่า X maximum คือค่า 16 บิตแบบ little-endian ที่ 0x8048 และ Y maximum อยู่ที่ 0x804A ให้อ่านค่าทั้งสองออกมา ถ้าคอนโทรลเลอร์ถูกตั้งค่าไว้ที่ 1024×600 แต่พาเนลของคุณเป็น 800×480 จุดสัมผัสจะไปอยู่ทางขวาและด้านล่างของนิ้ว และตำแหน่งขอบสุดจะหลุดออกนอกจอ วิธีแก้คือทำการสเกลค่า (หรือตั้งลิมิตของไดรเวอร์ให้ตรงกับค่าของคอนโทรลเลอร์)

แต่ละสแตกได้ค่าลิมิตมาจากที่ใด:

สแตก

แหล่งที่มาของความละเอียด

สลับและกลับด้าน (swap และ mirror)

Linux goodix

อ่านจากคอนฟิกของ GT911 หากคอนฟิกไม่มีค่าจะ fallback ไปที่ 4095 × 4095

Device-tree touchscreen-swapped-x-y, touchscreen-inverted-x, touchscreen-inverted-y, touchscreen-size-x/y

ESP-IDF esp_lcd_touch_gt911

ค่า x_max / y_max ที่คุณกำหนดใน esp_lcd_touch_config_t (ไดรเวอร์ไม่ได้อ่านความละเอียดจากชิป)

flags.swap_xy, flags.mirror_x, flags.mirror_y

ESPHome gt911

Touchscreen calibration (x_min, x_max, y_min, y_max)

transform: swap_xy / mirror_x / mirror_y

คาลิเบรตจากค่า raw

หน้าเอกสาร touchscreen ของ ESPHome แนะนำให้ log ค่า touch.x_raw และ touch.y_raw ใน lambda ของ on_touch แล้วแตะมุมทั้งสี่ที่ริมพิกเซลสุดหลาย ๆ ครั้ง จากนั้นนำค่า raw ต่ำสุดและสูงสุดที่ได้มาใส่เป็นค่า calibration วิธีเดียวกันนี้ใช้ได้กับทุกแพลตฟอร์ม: พิมพ์ค่า raw X และ Y ออกมา แตะมุมทั้งสี่ แล้ว map ช่วงค่าเข้ากับหน้าจอ

แก้การวางแนวตามลำดับนี้: ก่อนอื่นให้แกน X และ Y อยู่ถูกด้าน (swap_xy) จากนั้นค่อยกลับแกนที่วิ่งสวนทาง (mirror_x / mirror_y) จุด (0, 0) เชิงตรรกะของจอต้องอยู่ที่มุมซ้ายบน

5. การเขียนคอนฟิก GT911 ใหม่: ทางเลือกสุดท้าย

บล็อกคอนฟิกูเรชันเริ่มต้นที่ 0x8047 สำหรับ GT911 ไดรเวอร์ Linux ถือว่าบล็อกนี้มีขนาด 186 ไบต์:

  • ไบต์ 0 (0x8047): เวอร์ชันของคอนฟิก
  • ไบต์ 1–4: ความละเอียด X และ Y (ดูขั้นตอนที่ 4)
  • ไบต์ 5 (0x804C): จำนวนจุดสัมผัสสูงสุด, 4 บิตล่าง
  • ไบต์ 6 (0x804D): ชนิดการทริกเกอร์ interrupt, 2 บิตล่าง
  • ไบต์ 184 (0x80FF): checksum, ค่า two's complement 8 บิตของผลรวมไบต์ 0–183
  • ไบต์ 185 (0x8100): config_fresh ซึ่งต้องเป็น 1

ตัวไดรเวอร์ Linux เองจะเขียนคอนฟิกก็ต่อเมื่อมี GPIO ทั้ง INT และ RST และพบไฟล์เฟิร์มแวร์ (ชื่อค่าเริ่มต้น goodix_911_cfg.bin หรือชื่อที่ระบุในพรอเพอร์ตี goodix,config-name) ถ้าไม่มีไฟล์นั้น มันจะใช้คอนฟิกที่เก็บไว้แล้วในชิป

ก่อนเขียนอะไรลงไป ให้อ่านค่าทั้ง 186 ไบต์ออกมาและเก็บสำรองไว้ แก้ความละเอียดและการวางแนวในซอฟต์แวร์ให้มากที่สุดเท่าที่จะทำได้ บล็อกคอนฟิกที่ทำมาสำหรับพาเนลสัมผัสรุ่นอื่นอาจทำให้การสัมผัสบนพาเนลของคุณใช้งานไม่ได้ ดังนั้นถ้าจำเป็นต้องเปลี่ยนจริง ๆ ให้ขอไฟล์มาจากผู้ขายพาเนล

การเลือกโมดูลแบบ capacitive-touch

ถ้าคุณกำลังเลือกจอ CTP สำหรับงานออกแบบใหม่ ให้ถามผู้ขายสามข้อก่อนสั่งซื้อ samples: ใช้ตัวคอนโทรลเลอร์สัมผัสรุ่นใด, ส่งมอบพร้อม I2C address ใด และขา INT กับ RST เดินมาถึงคอนเนกเตอร์หรือไม่ ส่งขนาด, อินเทอร์เฟซ และโปรเซสเซอร์ของตัว host มาทาง Ask an Engineer แล้วเราจะแนบคำตอบทั้งสามข้อนี้มาพร้อมโมดูลที่เราแนะนำให้

คำถามที่พบบ่อย

I2C address ของ GT911 คืออะไร?

ใช้ได้ทั้ง 0x5D หรือ 0x14 (แบบ 7-bit) เมื่อสิ้นสุดสถานะ reset ตัวควบคุมจะอ่านระดับลอจิกที่ขา INT ทันที: ถ้า INT เป็น Low จะเลือก 0x5D ถ้า INT เป็น High จะเลือก 0x14 ส่วนดาต้าชีตที่ระบุ 0xBA/0xBB หรือ 0x28/0x29 นั้นคือที่อยู่เดียวกันในรูปแบบไบต์ write/read แบบ 8-bit

ทำไม GT911 ของฉันถึงเปลี่ยน address หลังจากรีบูต?

ขา INT ลอยอยู่หรือถูกขับโดยอย่างอื่นขณะสิ้นสุดสถานะ reset ทำให้ตัวควบคุมอ่านค่าระดับที่ต่างกันในแต่ละครั้ง วิธีแก้คือจูงขา INT ให้เป็น Low (สำหรับ 0x5D) หรือ High (สำหรับ 0x14) ก่อนปล่อย RST รอมากกว่า 5 ms คงสถานะ INT เป็น Low ไว้ 50 ms แล้วจึงตั้งเป็นอินพุต ถ้าฝั่ง host ควบคุมขา INT ไม่ได้ ให้สแกนหาทั้งสองที่อยู่

ทำไม GT911 ของฉันได้แค่การสัมผัสเดียว?

หลังอ่านข้อมูลทัชที่ 0x814E แล้วต้องเขียนค่า 0 กลับไปที่ 0x814E ดรายเวอร์ goodix ของ Linux และ esp_lcd_touch_gt911 ของ Espressif ต่างทำแบบนี้หลังทุกครั้งที่อ่าน ถ้าดรายเวอร์ข้ามขั้นตอนนี้ไป มักจะไม่เห็นการแตะใหม่อีกเลย

ทำไมพิกัดสัมผัสของ GT911 ถึงถูกสเกลหรือเลื่อนตำแหน่ง?

GT911 รายงานพิกัดตามความละเอียดที่เก็บไว้ในคอนฟิกของตัวเอง (X ที่ 0x8048, Y ที่ 0x804A) ถ้าค่านี้ต่างจากพาเนลของคุณ ให้สเกลค่าที่ได้ หรือตั้ง x_max/y_max ของดรายเวอร์ให้ตรงกับความละเอียดของตัวควบคุม จากนั้นใช้ swap_xy และ mirror_x/mirror_y ปรับทิศทาง

GT911 ใช้งานได้หรือไม่หากไม่มีขา INT?

ได้ครับ ให้เปลี่ยนจากการใช้ขา interrupt มาเป็นการอ่านสถานะจากรีจิสเตอร์ 0x814E แทน เมื่อไม่ได้ตั้งค่า interrupt_pin ESPHome จะทำการ polling ทุก 50 ms เป็นค่าเริ่มต้น และเนื่องจากไม่มีขา INT โฮสต์จึงไม่สามารถเลือกที่อยู่ของอุปกรณ์ได้ ให้ใช้ที่อยู่ใดก็ได้จาก 0x5D หรือ 0x14 ที่ตอบสนอง

ควรเขียนคอนฟิกูเรชันของ GT911 ใหม่หรือไม่?

ทำเฉพาะเมื่อทางเลือกอื่นหมดแล้วเท่านั้น ให้อ่านและสำรองบล็อกข้อมูล 186 ไบต์เดิมจาก 0x8047 ไว้ก่อน และถ้าจำเป็นต้องเขียนคอนฟิกจริง ๆ ให้ใช้ไฟล์คอนฟิกจากผู้ขายทัชแพเนล โดยเลือกแก้ความละเอียดและทิศทางในซอฟต์แวร์ก่อนเสมอ บล็อกนี้ปิดท้ายด้วย checksum แบบ 8-bit ที่ 0x80FF และไบต์ config_fresh ที่ 0x8100 ซึ่งต้องมีค่าเป็น 1

แหล่งที่มา

  1. Linux kernel: drivers/input/touchscreen/goodix.c
  2. Linux kernel: drivers/input/touchscreen/goodix.h (ที่อยู่รีจิสเตอร์)
  3. Linux kernel: Goodix touchscreen device-tree binding (goodix.yaml)
  4. Espressif ESP-BSP: ซอร์สโค้ดดรายเวอร์ esp_lcd_touch_gt911
  5. Espressif ESP-BSP: เฮดเดอร์ esp_lcd_touch_gt911 (ที่อยู่ I2C)
  6. ESPHome: GT911 touchscreen
  7. ESPHome: Touchscreen components (transform, calibration)

ไม่แน่ใจว่าจอแบบใดเหมาะกับงานออกแบบของคุณ?

ส่งขนาด อินเทอร์เฟซ และโปรเซสเซอร์โฮสต์มาให้เรา วิศวกรจอจะตอบกลับภายใน 12 ชั่วโมงพร้อมตัวเลือก 2–3 รายการ datasheet และโค้ดเริ่มต้น ตัวอย่างเริ่มที่ 1 ชิ้น