背景
最近参加公司一个电池测试仪的项目,负责电容屏驱动开发,电容屏的触控IC是汇顶科技的GT911
,电容屏的总线接口是I2C
。
因为项目沟通方面的失误,本应接到主控芯片的电容屏,被连到了MSP430
这款负责供电管理的MCU,领导说等PCB改版太慢了,让我就在MSP430上开发驱动,于是电容屏接入系统的方式就变成了这样:
本来写一份驱动就行,现在得MSP430和主机各写一部分,而且两边还要加一些SPI
总线处理。
MSP430的I2C驱动调试
首先要打通MSP430跟电容屏之间的I2C通信。
I2C控制器的初始化
分配I2C控制器对应的GPIO管脚
需要配置PxSEL0和PxSEL1寄存器,二者的相同位置的一对bit可以确定一个GPIO管脚是复用成4种功能的哪一种,我们根据datasheet选择合适的值,就能将其配置成I2C的SCL,同理SDA要用另外一对bit
配置I2C工作模式和波特率
这需要I2C控制器在复位状态下才能进行,因此需要先设置UCBxCTLW0的UCSWRST位,配置完毕后再清零相应bit位。
工作模式需要先设置UCBxCTLW0的UCMODE_3位,表示该USCI_B模块工作在I2C模式下,再设置UCMST位,表示I2C扮演Master角色。
波特率需要先设置UCBxCTLW0的UCSSEL__SMCLK位,表示时钟源选择SMCLK,再将UCB1BRW寄存器的值配成20,表示将SMCLK(我的是8M)分频20倍,就得到了400K,是GT911能支持的最高时钟频率。
配置I2C接收完成、发送完成、收发NACK中断
因为承载I2C功能的是USCI_B模块,因此中断向量要这样写
#pragma vector = USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
{
switch(__even_in_range(UCB1IV, USCI_I2C_UCBIT9IFG))
{
case USCI_NONE: break; // Vector 0: No interrupts
case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG
// NACK中断的处理
UCB1CTLW0 |= UCTXSTP; // pull up SCL
break;
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3
case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2
case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2
case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1
case USCI_I2C_UCTXIFG1: