This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TCA8418:TCA8418连接

Guru**** 2387080 points
Other Parts Discussed in Thread: TCA8418
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1226766/tca8418-tca8418-interfacing

器件型号:TCA8418

您好!
我很久以前问过这个问题,并以某种方式解决了问题,但我失去了解决方案,因为窗户问题,我回来了相同的问题。
我正在使用从 GitHub 下载的给定代码。 并在代码中添加链接。
它对我工作正常、但最后6个键、它显示双输出、如串行监视器数据中所示。

/*
 * TCA8418 Driver
 * This code is adapted from the phishman's driver for arduino, github.com/.../TCA8418
 * The difference is that it is written to be easily ported to another microcontroller
 * Author: Henry Troutman
 */

/*
 * Keyboard PCB Hookup Guide:
 * 1 -> 3.3V
 * 2 -> GND
 * 3 -> SDA
 * 4 -> SCL
 * 5 -> INT_PIN
 * 6 -> RTC_INT (ds3231)
 */

// Arduino I2C Library
#include <Wire.h>

// keyboard Constants
#define KEYBOARD_ADDRESS 0x34
#define KEYBOARD_INT_PIN 1
#define KEYBOARD_STATE_REGISTER 0x04
#define KEYBOARD_FLAG_REGISTER 0x02
#define KEYBOARD_KEY_DOWN 0x80
#define KEYBOARD_KEY_MASK 0x7F




// configuration commands (configures the 3x9 matrix as inputs with pullups, interrupts ...
// For more information look at the code in the repo linked above
const uint8_t KEYBOARD_CONFIG_COMMANDS[] = {0x1D,0x07,0x1E,0xFF,0x1F,0x01,0x01,0xB9,0x02,0x09}; 



// Define our functions before use
void keyboard_configure(void);
void keyboard_clearFlag(void);
uint8_t keyboard_getState(void);

// keyInt allows our event to ultimately be handled in the loop
volatile bool keyInt = false;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  keyboard_configure();
  pinMode(KEYBOARD_INT_PIN,INPUT); // There is an external pullup on the pin

  // Set up a falling edge pin interrupt on pin 1  
  attachInterrupt(digitalPinToInterrupt(KEYBOARD_INT_PIN), keyboard_ISR, FALLING); 
}

void loop() {
  if(keyInt)
  {
    uint8_t key_code = keyboard_getState(); // Get first keycode from FIFO
    if(key_code & KEYBOARD_KEY_DOWN) 
    {
      // This is where we can write to a screen or handle control keys
      Serial.print(key_code&KEYBOARD_KEY_MASK); // print the keycode
      Serial.print(",");
    }
      keyInt = false;
      keyboard_clearFlag();
    delay(100); 
  }
}

void keyboard_configure(void){
  for(uint8_t i = 0;i < 9;i+=2){
    Wire.beginTransmission(KEYBOARD_ADDRESS);
    Wire.write(KEYBOARD_CONFIG_COMMANDS[i]);
    Wire.write(KEYBOARD_CONFIG_COMMANDS[i+1]);
    Wire.endTransmission(); 
  }
}
uint8_t keyboard_getState(void){
  uint8_t key;
  Wire.beginTransmission(KEYBOARD_ADDRESS);
  Wire.write(KEYBOARD_STATE_REGISTER);
  Wire.endTransmission(); 
  Wire.requestFrom(KEYBOARD_ADDRESS, 1);    // request 1 bytes from slave device 0x34
  while (Wire.available()) 
  { // slave may send less than requested
    key = Wire.read(); // receive a byte as character
  }
  return key;
}
void keyboard_clearFlag(void){
  Wire.beginTransmission(KEYBOARD_ADDRESS);
  Wire.write(KEYBOARD_FLAG_REGISTER);
  Wire.write(0x0F);
  Wire.endTransmission(); 
}
void keyboard_ISR(void){
  keyInt = true;
}

/*
I2C Command Summary

Setup board (3x9 keypad)
write to Register, value
            0x1D, 0x07
            0x1E, 0xFF
            0x1F, 0x01
            0x01, 0xB9
            0x02, 0x09

To get keys
read 1 byte from 0x04

To clear interrupt flag
write to register,value
            0x02, 0x0F
 
 */

如果您能帮助我、我有两个请求。

  1. 为 SW1到 SW9分配与 SW10到 SW18顺序相同的数字。 例如、SW1应为1、而不是 SW1为21。 SW10至 SW18的序列是完美的。
  2. 从 SW19到 SW27分配一个唯一数字、而不是双数字




串行监视器数据

21至29对于 SW1至 SW9按下
11至19对于 SW11至 SW18、按下

在给我一个唯一的 ID 之前、我是可以接受的。

当我按下 SW19时、问题就开始了、然后它会生成一对输出、即1、2
SW20 2、3
SW21 3、4等

我需要知道最后9个开关的操作错误。
我使用3X9键盘矩阵。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ali、

    我正在尝试理解您的问题。 您所说的是、当您按 SW1到 SW10时、将收到21到30的数字。 当您按下开关 SW11到 SW20时、您将读取数字11到20。 您所指的数字是否在下面的数据表的关键事件表中列出?  

    如果是这种情况、您能否仔细检查以确保您的接线正确?  

    对于最后9个 SW21至 SW29开关、您会收到一个配对号。 这是否意味着每次按键时只能读取两个键事件? 或者、您是否阅读了单个开关的按压和释放两个关键事件?  

    对于您的请求...

    Unknown 说:
    按照相同的顺序为 SW1到 SW9分配号码、就像为 SW10到 SW18分配号码一样。 例如、SW1应为1、而不是 SW1为21。 SW10到 SW18的序列是完美的。

    请仔细检查开关与 IC 的连接。 这似乎连接可能会以某种方式反向、尤其是当您为开关1读取十进制数21时。  

    此致、

    泰勒

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    感谢您的答复。

    我正在尝试理解您的问题。 您所说的是、当您按 SW1到 SW10时、将收到21到30的数字。 当您按下开关 SW11到 SW20时、您将读取数字11到20。 您所指的数字是否在下面的数据表的关键事件表中列出?  

    我不知道它,但我解释的代码。

    1. 检查是否发生中断
    2. 从 I2C 读取1个字节
    3. if ( 从 I2C 接收到的字节  和 0x80 )
    4. 打印(  从 I2C 接收到的字节  0x7f)
    5. 清除中断标志

    这是我在串行监视器上打印的内容、得到的结果与不同的开关按压相对应。

    连接正常、没有问题。

    忽略网标名称,因为我通过正确位置的电线连接键盘,即 ROW1到 IC 的 ROW0,等等。

    唯一的问题是最后一行。 我有两种类型的键盘3X9和3X10。 每当我读取最后一行中的数据时、无论每一行中的按钮如何、它都以成对形式提供输出。

    我以前解决过这个问题、但没找到解决方案。 我在寄存器读取或类似的东西中犯了一些错误。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、 

    您还有其他问题吗?
     我测试了一个新代码、以检查在按下每个开关时它给我的行和列。  
    这是我发现的值、SW1 = R2 C0
    SW10 = R1 C0
    SW19 = R0 C0

    01:47:25.821 -> PRESS	R: 2	C: 0
    01:47:26.075 -> RELEASE	R: 2	C: 0
    01:47:31.278 -> PRESS	R: 2	C: 1
    01:47:31.483 -> RELEASE	R: 2	C: 1
    01:47:34.045 -> PRESS	R: 2	C: 2
    01:47:34.236 -> RELEASE	R: 2	C: 2
    01:47:36.686 -> PRESS	R: 2	C: 3
    01:47:36.892 -> RELEASE	R: 2	C: 3
    01:47:38.786 -> PRESS	R: 2	C: 4
    01:47:38.992 -> RELEASE	R: 2	C: 4
    01:47:40.884 -> PRESS	R: 2	C: 5
    01:47:41.153 -> RELEASE	R: 2	C: 5
    01:47:43.029 -> PRESS	R: 2	C: 6
    01:47:43.236 -> RELEASE	R: 2	C: 6
    01:47:45.607 -> PRESS	R: 2	C: 7
    01:47:45.845 -> RELEASE	R: 2	C: 7
    01:47:48.530 -> PRESS	R: 2	C: 8
    01:47:48.706 -> RELEASE	R: 2	C: 8
    01:47:50.551 -> PRESS	R: 1	C: 0
    01:47:50.709 -> RELEASE	R: 1	C: 0
    01:47:55.231 -> PRESS	R: 1	C: 1
    01:47:55.454 -> RELEASE	R: 1	C: 1
    01:48:03.847 -> PRESS	R: 1	C: 1
    01:48:04.022 -> RELEASE	R: 1	C: 1
    01:48:05.996 -> PRESS	R: 1	C: 2
    01:48:06.219 -> RELEASE	R: 1	C: 2
    01:48:08.767 -> PRESS	R: 1	C: 3
    01:48:09.022 -> RELEASE	R: 1	C: 3
    01:48:10.469 -> PRESS	R: 1	C: 4
    01:48:10.645 -> RELEASE	R: 1	C: 4
    01:48:12.300 -> PRESS	R: 1	C: 5
    01:48:12.476 -> RELEASE	R: 1	C: 5
    01:48:17.376 -> PRESS	R: 1	C: 6
    01:48:17.599 -> RELEASE	R: 1	C: 6
    01:48:19.797 -> PRESS	R: 1	C: 7
    01:48:20.002 -> RELEASE	R: 1	C: 7
    01:48:22.133 -> PRESS	R: 1	C: 8
    01:48:22.371 -> RELEASE	R: 1	C: 8
    01:48:26.241 -> PRESS	R: 0	C: 0
    01:48:26.241 -> PRESS	R: 0	C: 1
    01:48:26.479 -> RELEASE	R: 0	C: 0
    01:48:26.479 -> RELEASE	R: 0	C: 1
    01:48:35.222 -> PRESS	R: 0	C: 1
    01:48:35.222 -> PRESS	R: 0	C: 2
    01:48:35.411 -> RELEASE	R: 0	C: 1
    01:48:35.411 -> RELEASE	R: 0	C: 2
    01:48:42.304 -> PRESS	R: 0	C: 2
    01:48:42.304 -> PRESS	R: 0	C: 3
    01:48:42.558 -> RELEASE	R: 0	C: 2
    01:48:42.558 -> RELEASE	R: 0	C: 3
    01:48:47.590 -> PRESS	R: 0	C: 3
    01:48:47.590 -> PRESS	R: 0	C: 4
    01:48:47.827 -> RELEASE	R: 0	C: 3
    01:48:47.827 -> RELEASE	R: 0	C: 4
    01:48:49.704 -> PRESS	R: 0	C: 4
    01:48:49.704 -> PRESS	R: 0	C: 5
    01:48:49.927 -> RELEASE	R: 0	C: 4
    01:48:49.927 -> RELEASE	R: 0	C: 5
    01:48:51.930 -> PRESS	R: 0	C: 5
    01:48:51.930 -> PRESS	R: 0	C: 6
    01:48:52.198 -> RELEASE	R: 0	C: 5
    01:48:52.198 -> RELEASE	R: 0	C: 6
    01:48:54.334 -> PRESS	R: 0	C: 6
    01:48:54.334 -> PRESS	R: 0	C: 7
    01:48:54.571 -> RELEASE	R: 0	C: 6
    01:48:54.571 -> RELEASE	R: 0	C: 7
    01:48:56.211 -> PRESS	R: 0	C: 7
    01:48:56.211 -> PRESS	R: 0	C: 8
    01:48:56.481 -> RELEASE	R: 0	C: 7
    01:48:56.481 -> RELEASE	R: 0	C: 8
    01:49:05.302 -> PRESS	R: 0	C: 8
    01:49:05.540 -> RELEASE	R: 0	C: 8

    这是串行监视器的输出。 我不介意编号顺序是否不同、这可能是由于键盘布线造成的。
    我唯一担心的是、最后一行 允许单次按下和释放每个按钮两次。

    你知道为什么会这样吗?
    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ali、

    是否可以打印出所有寄存器? 我具体想查看寄存器0x29、0x2A、0x2B、但完整的寄存器读出将非常有帮助、因为该问题最初是通过软件解决的、与硬件无关。

    如果可能、请打印0x00 - 0x2E 的寄存器读数。  

    此致、

    泰勒

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    PLZ、请参阅所附文档以了解所请求的数据。 我还发布了代码供您参考。 我玩了很多,我使用的所有注册,但没有获得任何成功谢谢

    #include <Wire.h>
    
    #define KEYBOARD_ADDRESS 0x34
    #define KEYBOARD_INT_PIN 1
    #define KEYBOARD_EVENT_REGISTER 0x04
    #define KEYBOARD_FLAG_REGISTER 0x02
    #define KEYBOARD_KEY_DOWN 0x80
    #define KEYBOARD_KEY_MASK 0x7F
    
    // configuration commands
    const uint8_t KEYBOARD_CONFIG_COMMANDS[] = {
      0x1D, 0x07,
      0x1E, 0xFF,
      0x1F, 0x01,
      0x01, 0x11,
      0x02, 0xFF
    };
    
    volatile bool keyInt = false;
    
    void setup() {
      Serial.begin(9600);
      Wire.begin();
      keyboard_configure();
      pinMode(KEYBOARD_INT_PIN, INPUT);
    
      attachInterrupt(digitalPinToInterrupt(KEYBOARD_INT_PIN), keyboard_ISR, FALLING);
    }
    
    void loop() {
      if (keyInt) {
        printRegisterReadouts();
        keyboard_clearFlag();
        keyInt = false;
      }
    }
    
    void printRegisterReadouts() {
      for (uint8_t reg = 0x01; reg <= 0x2E; reg++) {
        uint8_t value = readRegister(reg);
        Serial.print("Register 0x");
        Serial.print(reg, HEX);
        Serial.print(": ");
        Serial.println(value, HEX);
      }
      Serial.println();
    }
    
    void keyboard_configure() {
      for (uint8_t i = 0; i < sizeof(KEYBOARD_CONFIG_COMMANDS); i += 2) {
        Wire.beginTransmission(KEYBOARD_ADDRESS);
        Wire.write(KEYBOARD_CONFIG_COMMANDS[i]);
        Wire.write(KEYBOARD_CONFIG_COMMANDS[i + 1]);
        Wire.endTransmission();
      }
    }
    
    uint8_t readRegister(uint8_t reg) {
      Wire.beginTransmission(KEYBOARD_ADDRESS);
      Wire.write(reg);
      Wire.endTransmission();
      Wire.requestFrom(KEYBOARD_ADDRESS, 1);
      if (Wire.available()) {
        return Wire.read();
      }
      return 0;
    }
    
    void keyboard_clearFlag() {
      Wire.beginTransmission(KEYBOARD_ADDRESS);
      Wire.write(KEYBOARD_FLAG_REGISTER);
      Wire.write(0xFF);
      Wire.endTransmission();
    }
    
    void keyboard_ISR() {
      keyInt = true;
    }
    

    e2e.ti.com/.../Serial-Data.xlsx

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    如果您有任何其他更新或需要任何其他更新、请告诉我。 如果我们能够尽快解决这一问题、那将是很好的选择。
    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ali、

    我现在实际上在研究这个问题。 请允许我尽快回复您。

    此致、

    泰勒

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ali、

    寄存器0x03分别显示了按键工作与不工作的值1和2。 这告诉我、按正确的按键后、FIFO 中仅存储一个事件、用于单次按压或释放。 按下不良按钮时、会存储两个事件、用于单次按下或释放操作。  

    我还注意到、在串行监视器读数中、当 R = 1或2、并且 C = 1/2/3/4/5/6/7/8时、没有问题。 该问题仅在行= 0时发生、仅当行= 0时才存在双按压/释放事件。 我们是否确定第0行的电气连接良好? 由于信号是非单调的、代码是否有可能寄存器化两个下降沿和两次按键按压/释放操作?  否则、这似乎是索引问题或类似问题。  

    keyboard_configure()函数似乎正确。 uint8_t 循环至 I = 0/2/4/6/8、并正确写入每个寄存器0x1D、0x1E、0x1F、0x01、0x02。 我不认为这个函数是问题所在。  

    我也没有看到 readRegister (uint8_t reg)函数有任何问题。  

    这使我认为,该问题有某种程度的处理 keyboard_clearFlag()函数,因为我发现在循环中 printRegisterReadouts()没有错误。  在 keyboard_clearFlag ()函数的代码中,您可以将写入0xFF 更改为0x1F 以确保不会弄乱始终为0的前三个位吗? 不确定这是否会起作用、但只是想更改此值、以便写入寄存器中的正确位。 我认为这不一定是问题。  

    似乎您使用正确的地址0x34开始传输。 然后、你通过写入0xFF (全1)来写入0x02以清除中断。 将其更改为0x1F、以查看是否发生了任何不同的情况。 发送后将发送一个停止位、正确无误。 在循环函数中、可以在"if"语句后添加一小段延迟。 延迟(10)应该没有问题。 去抖问题似乎有点像、但您的寄存器0x29、0x2A、0x2B 都为0x00、因此启用了50us 去抖。 可能50us 的时间不够。  

    我查看了您提供的 Excel 文档中的寄存器读数。 在我看来、没有什么是重大问题。  

    请查看我在此处所述的任何内容是否有助于解决该问题。 如果没有、我认为下一步是查看工作按键与非工作按键之间的范围捕获。 我目前在您的代码中看不到任何其他与软件相关的问题。  

    此致、

    泰勒

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    感谢您的详细解释。 我发现了问题。 实际上、这不是软件问题。 是硬件问题。 我做了两个版本的键盘。 去年、我做过测试、准备了最终代码的旧版、然后我要求供应商为我提供更多的键盘、他们在新库存中明显犯了错误。 我刚刚用一个旧的键盘测试,它工作正常,但当我尝试相同的代码相同的 PCB 板,新的键盘,然后它产生了这个问题。

    再次感谢您的全力帮助。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    我发现了这个问题、但不确定如何纠正。 也许你可以建议一些东西。
    键盘上有背光。
    一旦我将它的两根电线与板连接、然后它开始在单次按压时发出两个按键、但如果我断开它的电缆、它就开始正常工作。 我正在做测试,发现它工作正常,然后我连接电缆,它开始工作相同.
    此问题不会出现在其他18个按键上。 仅最后一行导致问题
    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ali、

    在不知道系统中如何连接的完整详细信息的情况下、我不确定如何解决此问题。 听起来背光照明是键盘的一个附加功能、从为 LED 供电到为键盘数字提供背光、可能会给电源带来噪音。  

    是否可以在 TCA8418的电源中添加去耦电容器? 0.1uF 10V 电容器在此处应该可以正常工作。 如果电容器尽可能靠近电源引脚放置、将会更有益处。  

    为了减慢开关的上升沿/下降沿、在行和 COL 引脚上添加滤波器电容以及靠近开关引脚的电容也可能是明智之举。 开关上可能存在噪声耦合、导致 TCA8418识别双开关按压操作。  

    此致、

    泰勒

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    我在电源处添加了电容器、但它没有多大帮助。 我引入了50ms 的去抖延迟、它开始提供单个值。 现在我的问题是、如何配置寄存器以在 TCA8418中引入此延迟、这样我就不必每次在程序中都担心它。
    是否有任何其他与硬件相关的建议,因为我将很快制造新的板.
    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ali、

    TCA8418只能自行实现50us 去抖延迟。  

    该时序无法在 TCA8418中更改。 唯一的选择是通过软件增加延迟、或通过外部 RC 元件减少振铃、降低整体数据速率。 任何旨在降低边沿转换的压摆率的变化都会有所帮助。  

    此致、

    泰勒

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、谢谢
    在这种情况下、我将添加软件

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ali、

    这听起来不错。

    如果您还有其他问题、敬请告知。

    此致、

    泰勒