【换取逻辑分析仪】+TTP229触摸键盘在MSPM0G3507下的奇怪表现
之前测试一个从项目的时候,打算在MSPM0G3507下使用TTP229触摸键盘。
1.输入按键数目选择
TTP229 具有 8 键输入模式和 16 键输入模式。两者是通过 TP2(KYSEL)是否连接高阻值电阻到VSS 所决定。默认为 TP2(KYSEL)不连接电阻到 VSS 选定为 8 键输入模式,16 键输入模式是连接高阻值电阻到 VSS。
2. 输出模式
TTP229 具有 8 端口直接输出模式和两种串行输出模式。16 键输入模式下只能使用串行输出方式。8 键输入模式下可使用两种输出方式,为 8 端口直接输出和串行输出方式。8 端口直接输出方式只能应用在 8 键直接输出模式下。两种串行输出方式包括 I2C 和 2-线串行通讯方式。此两种方式共用 SCL 作为时钟输入端口。这两种模式通过 SLSERT 选择,同一时间只能选择一种通讯方式。SLSERT 悬空(默认)或连接到 VDD 将设置为 2-线串行通讯方式,当 SLSERT 链接到VSS 时,设置为 I2C 通讯方式。
2.1 在 8 端口直接输出模式下,TTP229 具有两种输出类型,CMOS 类型输出和 OD(漏极开路)类型输出。这两者通过 TP0(OPDEN)选择。默认为 CMOS 类型,即 TP0(OPDEN)不连接高阻值电阻到 VSS。当 TP0(OPDEN) 连接高阻值电阻到 VSS 时,选择为 OD 类型输出。
2.2 当选用 8 端口直接 COMS 输出模式,输出有效电平可以通过 TP1(SAHL) 端口设置为高电平有效或低电平有效。默认 TP1(SAHL) 端口不连接高阻值电阻到 VSS,输出设置为高电平有效。当 TP1(SAHL) 端口连接高阻值电阻到 VSS 时,输出设置为低电平有效。
2.3 在 8 端口直接 OD 输出模式下,可通过 TP1(SAHL) 端口选择为 OD(漏极开路)或 OC(集极开路) 输出方式。若 TP1(SAHL) 端口连接高阻值电阻到 VSS,即选为 OC 输出模式。若不连接高阻值电阻则选用默认的 OD 输出模式。OD 模式下其平常为悬浮状态, 输出为低电平有效,OC 模式下其平常为悬浮状态, 输出为高电平有效。OD 和 OC 输出模式的结构如下图。
备注:芯片输出端口内部具有二极管保护电路,因此当选用 OD 或 OC 输出模式时,为避免系统内部漏电流, 请不要与不同电压的系统直接连接.
2.4 2-线串行输出通讯方式可由 SLSERT 端口是否悬空或连接到 VDD 选定。在此模式下,SDO端口为数据输出端口,SCL 是时钟输入端口,两者皆可由 TP1(SAHL) 端口选择为高电平有效还是低电平有效。默认为 TP1(SAHL) 端口不连接高阻值电阻到 VSS 设置为低电平有效。若连接高阻值电阻到 VSS,则设置为高电平有效。
2-线串行输出方式它支持连续接受其它系统送给的数据,也可以让其他设备等待 TTP229 通过SDO 端口送出的数据信号(DV),然后再送出时钟信号到 TTP229 的 SCL 端口并从 SDO 端口取得按键数据。
TTP229 的 2-线串行通讯方式对 SCL 端口设有时间的限制。如果 SCL 端口超过 2ms 信号没有变化,系统将会自行回到待机模式。
2-线串行通讯方式时序如下图所示:
D0~D15 对应于 TP0~TP15 上数据。
2.4.11 当TP1=0,TP2=0:设置为16键模式,高电平有效
图2.4.1:16键输入,高电平有效时序
2.4.2. 当TP1=1,TP2=0:设置为16键模式,低电平有效
图2.4.2:16键输入,低电平有效时序
键盘处理部分在MSPM0G3507工程中的程序代码如下:
/******************************************************************** * 名称 : TTP229B() * 功能 : 扫描TTP229电容键盘(16按键)函数 * 输入 : 无 * 输出 : 按键编号 ***********************************************************************/ unsigned int TTP229B(void) { unsigned char key=0; unsigned char i; unsigned int temp=0x0000; // 设置PB12为输出模式 DL_GPIO_initDigitalOutput(GPIO_LEDS_Key3_IOMUX); // PB12 输出0 DL_GPIO_clearPins(GPIOB, DL_GPIO_PIN_12 ); // 使能输出 DL_GPIO_enableOutput(GPIOB, DL_GPIO_PIN_12); delay_us(100); // 输出为1 DL_GPIO_setPins(GPIOB, DL_GPIO_PIN_12 ); delay_us(20); //DL_GPIO_disableOutput(GPIOB, DL_GPIO_PIN_12); // 变更为输入模式 DL_GPIO_initDigitalInputFeatures(GPIO_LEDS_Key3_IOMUX, DL_GPIO_INVERSION_DISABLE, DL_GPIO_RESISTOR_PULL_UP, DL_GPIO_HYSTERESIS_DISABLE, DL_GPIO_WAKEUP_DISABLE); //DL_GPIO_initDigitalInput(GPIO_LEDS_Key3_IOMUX); for(i=0;i<16;i++) { // 输出SCL=0 DL_GPIO_clearPins(GPIOB, DL_GPIO_PIN_17); delay_us(100); // 输出SCL=1 DL_GPIO_setPins(GPIOB, DL_GPIO_PIN_17); delay_us(100); // 读入Key3(PB12) if(DL_GPIO_readPins(GPIOB, DL_GPIO_PIN_12) ==0) { temp|=(1<<i); } } // 转换键盘值为0-15 for (i=0;i<16;i++) { if ((temp & (1<<i)) > 0) { key=i+1; } } // 延迟 delay_ms(10); return key; }
这个程序的处理过程是在其它51单片机以及STM32单片机上经过验证的,但在MSPM0G3507上测试,没有达到预期结果,任何按键都没有产生输出,即使调节SDA的输入端是否接上拉电阻,对于结果也没有任何影响。下面是示波器测试的SCL和SDA事实时波形(一直按住第15个按键)。可以看到,在读取数据的过程中,SDA没有任何变化。
作为对比,在STM32单片机下的测试波形(一直按住第15个按键):
一直按住第2个按键:
可以看到,在通过接口访问获得数据时,对应哪个按钮被按下,在相应的SCL时序中对应按钮的SDA位会有一个负脉冲。
作为代码对比,STM32下TTP229的处理代码如下:
// 使SDA=0 void CLR_TTP229_SDA(void){ // 使SDA对应的GPIO引脚为输出 OUT_TTP229_SDA(0); } void SET_TTP229_SDA(void){ // 使SDA对应的GPIO引脚为输出 OUT_TTP229_SDA(1); } // 使SDA对应的GPIO引脚为输出 // 使SDA=val void OUT_TTP229_SDA(uint8_t val){ GPIO_InitTypeDef GPIO_InitStruct; //TTP229_SDA_CLK_ENABLE(); //使能GPIO的时钟 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Pin = TTP229_SDA; HAL_GPIO_Init(PORT_TTP229_SDA, &GPIO_InitStruct); if (val) { HAL_GPIO_WritePin(PORT_TTP229_SDA, TTP229_SDA, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(PORT_TTP229_SDA, TTP229_SDA, GPIO_PIN_RESET); } } // 使SDA对应的GPIO引脚为输入 uint8_t READ_TTP229_SDA(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Pin = TTP229_SDA; HAL_GPIO_Init(PORT_TTP229_SDA, &GPIO_InitStruct); // 取得GPIO电平 return HAL_GPIO_ReadPin(PORT_TTP229_SDA, TTP229_SDA); } /******************************************************************** * 名称 : ttp_GetKeyCode() * 功能 : 扫描TTP229电容键盘(16按键)函数 * 输入 : 无 * 输出 : 按键编号 ***********************************************************************/ uint8_t ttp_GetKeyCode(void) { uint8_t key=0; uint8_t i; uint8_t temp=0x0000; CLR_TTP229_SDA(); ttp29_delay(200); SET_TTP229_SDA(); ttp29_delay(200); for(i=0;i<16;i++) { CLR_TTP229_SCL(); ttp29_delay(200); SET_TTP229_SCL(); ttp29_delay(200); if(READ_TTP229_SDA()==RESET) { temp|=(1<<i); } } for (i=0;i<16;i++) { if ((temp & (1<<i)) > 0) { key=i+1; } } HAL_Delay(50); return key; }
在处理逻辑上完全一样。如果说有区别的话,仅仅是在脉冲周期上有变化。
后面围绕这个问题,我会继续使用其他开发板,使用相同逻辑,以及调整接口脉冲的周期,来做进一步测试,以期找到原因和解决办法。