4608|0

19

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

TI - MCU - MSP430使用指南14 -> I2C通信(eUSCI) [复制链接]


此内容由EEWORLD论坛网友骑IC看MCU原创,如需转载或用于商业用途需征得作者同意并注明出处

 

说到MSP430 MCUI2C资源,那么首先就得先看一下USCI

如果你了解过多款MSP430 MCU你会发现,内部资源里有USCIeUSCI,那么他们什么意思呢?

USCI (Universal Serial Communication Interface),即通用串行通信接口,eUSCI中的e则是enhanced的意思,即增强型,那么有什么区别呢?

一些主要的区别如下表所示,F2xx这一列代表USCIFR57xx代表eUSCI

更多详细区别,请查看TI官方文档:

查看详情

其实你会发现 区别不是很大,仅仅是寄存器的名字变了一点,在使用起来很是相似,因此本次使用eUSCI进行讲解。

eUSCI又分两种:AB,有什么区别呢:

  • A:支持UARTSPI
  • B:支持I2CSPI

也就是说两种都支持SPI,但A仅支持UARTSPIB仅支持I2CSPI。想过为什么吗?

(这段内容比较深,也不一定是全部都是正确的:我认为毕竟eUSCI就是数字逻辑电路嘛,TI设计成这种格式去给客户机会去选用SPII2C/UART,相对于单独设计I2CSPIUART内核来说,第一节省电路,可以降低功耗和成本,第二减少引脚数量。那为什么都支持SPI嘛,因为SPI协议简单嘛,没有I2C那种起始位,停止位,也没有UART那种固定的波特率,SPI自己有自己的时钟,所以内部电路集成方面与UARTI2C有一定的公共成分,而UARTI2C差别较大,结合起来没什么性价比吧,所以出现了A版本和B版本。这些仅是我的猜测。。。em……

好啦,那么正式进入我们今天的主题  à I2C协议。

首先,第一部分肯定要讲清楚什么是I2C协议,这类资料网上一大堆一大堆,也可以很容易的搜索到资料来参考,我就简单的过一下吧。

I2C(Inter-Integrated Circuit) Philips公司发明的一种用于片级连接的总线方式,有什么好处呢:

  • 简单,就两根线SDASCL
  • 总线方式,可以挂接多个设备。
  • 通信速度有低速,普通,高速等模式,目前最快好像可以实现3.4Mbps速度。

其实还有挺多优点的,不然也不可能经历那么多年I2C依旧很主流。首先我想稍微解释一下挂接设备数量问题:

这个可以挂接多个设备主要是由于I2C的开漏特性决定的,即0有效,外部需要上拉电阻,开漏和推挽的资料网上也很多,可以自己查来看看。那么能挂接多少设备呢?这个本质上是由总线上的容性决定的,我们都知道,电容越大,充电时间越长,那么信号上升速度越满,当慢到不能满足I2C要求是,那么则不能挂接了,挂接设备相当于并联电容嘛,电容就变大了,然后就。。。,就。。。。

I2C协议如下:

https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1579184850371&di=a94ab1ed5c4327249bf96aae9aaac1e9&imgtype=0&src=http%3A%2F%2Fyzhtml01.book118.com%2F2016%2F11%2F25%2F18%2F45147305%2F5.files%2Ffile0003.jpeg

简单吧,就两根线嘛,首先呢,起始位。如果你是个Master,需要发信号给Slave,那么肯定要给个起始位嘛,告诉Slave你开始发数据了,如上图:SCL=1SDA01标志着起始位,然后呢,肯定是要写地址了,从设备地址,总线上挂接了很多Slave,你要发送给谁呢? 那么就写谁的地址,I2C地址是7位的(别抬杠,知道有10位地址模式,不过原理相同的),然后呢,下一位是R/W,你是读Slave里的数据呢,还是写数据到Slave呢?需要吧? 后面就是数据了,当然,当你写完一个数据后,Slave会给你个回应那个,then你接着写,Slave再回应,就这样最后Master发送一个STOP位(SCL=1SDA由低变高),好啦,那么一包数据通信即结束了。

PS:讲解一个小知识:你细看I2C协议你会发现:SDA数据线上只能再SCL=0的时候改变,SCL=1时需要保持状态,为什么呢? 简单嘛,请看STARTSTOP信号,你就知道了。

好啦,I2C协议讲解完了,那么正式进入正题:MSP430 I2C如何使用:

先上一张I2C模块的内部结构图:

一堆一堆的寄存器,标志位对吧,最终出来两根线SDASCL是吧。就是这样的嘛,内部的模块不就是一些逻辑电路加一些Memory嘛,迷糊没事的,后面看看寄存器就知道了:

那么就开始讲解如何使用吧,也就是寄存器内容啦:

看一下有哪些寄存器:

  • UCBxCTLW0

 

UCA1010位地址选择,1时为10位地址模式,0时为7位地址模式。

UCLSA10Slave10位地址选择,也就是说你作为Master时需要通信的Slave是否是10位地址的模式。

UCMM:多Master选择,因为正常I2C时钟是由Master控制的,因此如果存在多Master时,需要释放SCL的,故设计了这一位用来应对多Master模式。

UCMSTMasterSlave选择,决定MSP430用作I2C中的Master还是Slave

UCMODEx:模式选择:SPI或者I2C,同时SPI还分为三线和四线模式。

UCSSELx:时钟源选择,建议选SMCLK吧,频率高一点,精度也就高一点。

UCTXACK:回应地址正确,这个是再Slave或者多Master模式下,开启地址掩码功能后,只对比除去掩码的剩下地址,如果一致的话,需要发送个地址确认位(UCSWACK=1时需要手动设置发送,UCSWACK=0时会自动发送),这个就是那个地址确认位。

UCTR:发送还是接受,数据给Slave时是发送,读的时候则是接受或者作为Slave也是接受。

UCTXNACK:发送ACK信号,在Slave模式下使用。

UCTXSTP:生成STOP信号,在Master模式下使用。

UCTXSTT:生成起始信号,在Master模式下使用。

UCSWRST:软件复位使能,默认是1,即不能写一些寄存器设置I2C参数,有些寄存器想进行操作时需要复位这一位。

  • UCBxCTLW1

              UCETXINT:这一位仅在Slave模式下有用,决定着什么时候会置位UCTXIFG0(这一位置位标志着有能力去发送数据了),当这一位是1时,收到Master发送过来的START信号就会置位,当这一位是0时,则等到接收到Master发送的地址与自己的地址匹配时,才会置位UCTXIFG0(注意这种情况下地址1-3都要disable)。

              UCCLTOI2C总线时钟超时,也就是可能总线上卡死了,这一位用来设置这个时间,也可以关闭此项功能。如果设置了时间,在超时之后会触发UCCLTOIFG中断,用户可以在中断里重新初始化I2C

              UCSTPNACK:这一位是指在MCU作为Master接受数据时,在收到Slave的最后一个字节数据后可以发送一个响应给Slave,不过这并不符合I2C协议,因此只用在一些特定场合,正常的I2C协议,请忽略。

UCSWACK:看UCBxCTLW0中的UCTXACK描述,这一位和地址掩码有关系。

              UCASTPx:自动生成STOP设置,这一位只用在Master模式下,在设置自动生成STOP信号后,发送完设置长度的数据后,I2C内核直接自动发送停止位,这样会简化用户操作。注意:你可能会遇到一个情况:设置自动STOP后,会设置一个发送数据的长度,而这个数据长度寄存器,也就是UCTBCNTx,这个是8位的,也就是最大值就是255了,因此,如果I2C一次性需要传递的数据包超过了255字节,那么有两种方案解决:不要开启STOP,选择手动设置STOP信号,或者启动DMA模块,这两张方式都可以。手动STOP简单一点,DMA速度快一点。

              UCGLITx:错误检测位,这一位可以检测信号线上的毛刺噪声,建议直接默认就好啦。

  • UCBxBRW

               这个寄存器是控制I2C波特率的,目前MSP430I2C模块支持快速的400Kbps(资料中说的严谨,起始可以更快的)。那么如何计算波特率的呢?看下面框图:

就是对时钟进行分频后,就直接传输给SCL线上了,因此很容易计算,在选择时钟源之后,时钟源的频率除以这一位,就是SCL的时钟频率。

  • UCBxSTATW

UCBCNTx:只读寄存器,用来获取I2C总线上接受或者发送的数据量。

UCSCLLOW:用来查看SCL状态,可以确定是否有其他设备将此总线时钟拉低了。

UCGC:只读寄存器,标志着是否接收到了通用的Call 地址。

UCBBUSY:只读寄存器,用来查看总线上是否繁忙,一般情况下,为了保证数据发送的严谨性,在数据发送前都要查询这一位来决定是否可以发送数据的。

 

  • UCBxTBCNT

UCTBCNTx:在上面自动生成STOP信号时提过,这一位用来设置I2C一包数据发送的数量。

  • UCBxRXBUF

I2C数据接受缓冲区,在收到I2C接受中断后(当然是在使能中断后啦),接收到的数据会存放在这个缓冲区里,需要读取出来,读取后会自动清除接收中断。

 

  • UCBxTXBUF

              I2C数据发送缓冲区,也就是如果你想通过I2C协议发送一个数据,那么你只需要把这个数据写入这个寄存器中即可,当数据移入移位寄存器后,开始发送,发送完成后则会触发发中断,代表着当前寄存器的值已经空了,数据已经发送完成,可以写入下一个数据进行发送了。

  • UCBxI2COA0

              I2Cgeneral call是一个什么呢? 就类似于广播模式嘛,地址就是0,更多详细资料,请查看I2C官网:https://www.i2c-bus.org/addressing/PS:推荐大家有问题多去官网查看,官方发布的肯定没什么问题,理解起来不会有误区)

               UCOAEN:使能自己的I2C地址。

               I2COAx:自己的I2C地址0

  • UCBxI2COA1

参考UCBxI2COA0

               UCOAEN:使能自己的I2C地址。

               I2COAx:自己的I2C地址1

 

  • UCBxI2COA2

参考UCBxI2COA0

               UCOAEN:使能自己的I2C地址。

               I2COAx:自己的I2C地址2

 

  • UCBxI2COA3

参考UCBxI2COA0

               UCOAEN:使能自己的I2C地址。

               I2COAx:自己的I2C地址3

总的来说,就是MSP430I2C模块可以设置4Slave地址,可以产生不同的I2C中断。

  • UCBxADDRX

              ADDRXx:只读寄存器,接收到数据对方的地址。

  • UCBxADDMASK

               ADDMASKx:地址掩码,可以选择性的接受对象固定地址的设备发送来的数据。

  • UCBxI2CSA

              I2CSAxSlave设备的地址,注意,这个只用在MCU作为Master模式下,这一位用来设置你要发送的Slave设备他的地址。

  • UCBxIE

               各种各样的中断使能位,这个和IFG中断标志位是匹配的,也就是使能相应的中断后,产生中断的情况下后,会置位相应的中断标志位,然后产生中断。具体每个中断时什么用,请看IFG寄存器的描述。

  • UCBxIFG

              中断标志位寄存器,看起来好多吧,最常用的就是UCTXIFG0UCRXIF0了,当然一些NACKSTTSTP也会用到,具体内容看下面这四张图:分别表示在Slave模式下T/RMasterT/R,什么时候会将这些标志位置位(7bit地址模式,10bit模式的类似,请直接擦看官方的user guide

 

这四张图解释的很清楚,在I2C数据包那一块会触发什么中断,这样用户可以很灵活的使用这些中断标志位和中断入口。

  • UCBxIV

中断向量表,可以和中断标志位匹配。

好啦,寄存器内容讲解完成后,接下来就是如何使用的环节了,直接上程序吧(MS430FR2355):

其实寄存器很多,但是真正常用的寄存器很少,其他的直接默认就行了,因此不用担心看完了记不住,不重要的,看下下面程序,哪些不懂得地方直接回去找就好啦,User guide就像一个字典,你不需要去背,需要的是在遇到问题是,如何去查找就行。

  • Master模式+Slave模式:(单个地址,Slave在接收到Master数据后,发送从0开始的递增数据)两个程序可以下载到两个MCU中,实现两个MCUI2C通信验证。

Maser 程序:

#include <msp430.h>

volatile unsigned char RXData;

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;

    // Configure GPIO
    P1OUT &= ~BIT0;                         // Clear P1.0 output latch
    P1DIR |= BIT0;                          // For LED
    P1SEL0 |= BIT2 | BIT3;                  // I2C pins

    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    // Configure USCI_B0 for I2C mode
    UCB0CTLW0 |= UCSWRST;                   // Software reset enabled
    UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C mode, Master mode, sync
    UCB0CTLW1 |= UCASTP_2;                  // Automatic stop generated
                                            // after UCB0TBCNT is reached
    UCB0BRW = 0x0008;                       // baudrate = SMCLK / 8
    UCB0TBCNT = 0x0005;                     // number of bytes to be received
    UCB0I2CSA = 0x0048;                     // Slave address
    UCB0CTL1 &= ~UCSWRST;
    UCB0IE |= UCRXIE | UCNACKIE | UCBCNTIE;

    while (1)
    {
        __delay_cycles(2000);
        while (UCB0CTL1 & UCTXSTP);         // Ensure stop condition got sent
        UCB0CTL1 |= UCTXSTT;                // I2C start condition

        __bis_SR_register(LPM0_bits|GIE);   // Enter LPM0 w/ interrupt
    }
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCB0IV, 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
      UCB0CTL1 |= UCTXSTT;                  // I2C start condition
      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 14: TXIFG3
    case USCI_I2C_UCRXIFG2: break;          // Vector 16: RXIFG2
    case USCI_I2C_UCTXIFG2: break;          // Vector 18: TXIFG2
    case USCI_I2C_UCRXIFG1: break;          // Vector 20: RXIFG1
    case USCI_I2C_UCTXIFG1: break;          // Vector 22: TXIFG1
    case USCI_I2C_UCRXIFG0:                 // Vector 24: RXIFG0
      RXData = UCB0RXBUF;                   // Get RX data
      __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
      break;
    case USCI_I2C_UCTXIFG0: break;          // Vector 26: TXIFG0
    case USCI_I2C_UCBCNTIFG:                // Vector 28: BCNTIFG
      P1OUT ^= BIT0;                        // Toggle LED on P1.0
      break;
    case USCI_I2C_UCCLTOIFG: break;         // Vector 30: clock low timeout
    case USCI_I2C_UCBIT9IFG: break;         // Vector 32: 9th bit
    default: break;
  }
}

Slave程序:

#include <msp430.h>

volatile unsigned char TXData;

int main(void)
{
  WDTCTL = WDTPW | WDTHOLD;

  // Configure GPIO
  P1SEL0 |= BIT2 | BIT3;                    // I2C pins

  // Disable the GPIO power-on default high-impedance mode to activate
  // previously configured port settings
  PM5CTL0 &= ~LOCKLPM5;

  // Configure USCI_B0 for I2C mode
  UCB0CTLW0 = UCSWRST;                      // Software reset enabled
  UCB0CTLW0 |= UCMODE_3 | UCSYNC;           // I2C mode, sync mode
  UCB0I2COA0 = 0x48 | UCOAEN;               // own address is 0x48 + enable
  UCB0CTLW0 &= ~UCSWRST;                    // clear reset register
  UCB0IE |= UCTXIE0 | UCSTPIE;              // transmit,stop interrupt enable

    __bis_SR_register(LPM0_bits | GIE);     // Enter LPM0 w/ interrupts
    __no_operation();
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
  {
    case USCI_NONE: break;                  // Vector 0: No interrupts
    case USCI_I2C_UCALIFG: break;           // Vector 2: ALIFG
    case USCI_I2C_UCNACKIFG: break;         // Vector 4: NACKIFG
    case USCI_I2C_UCSTTIFG: break;          // Vector 6: STTIFG
    case USCI_I2C_UCSTPIFG:                 // Vector 8: STPIFG
      TXData = 0;
      UCB0IFG &= ~UCSTPIFG;                 // Clear stop condition int flag
      break;
    case USCI_I2C_UCRXIFG3: break;          // Vector 10: RXIFG3
    case USCI_I2C_UCTXIFG3: break;          // Vector 14: TXIFG3
    case USCI_I2C_UCRXIFG2: break;          // Vector 16: RXIFG2
    case USCI_I2C_UCTXIFG2: break;          // Vector 18: TXIFG2
    case USCI_I2C_UCRXIFG1: break;          // Vector 20: RXIFG1
    case USCI_I2C_UCTXIFG1: break;          // Vector 22: TXIFG1
    case USCI_I2C_UCRXIFG0: break;          // Vector 24: RXIFG0
    case USCI_I2C_UCTXIFG0:
       UCB0TXBUF = TXData++;
       break;                               // Vector 26: TXIFG0
    case USCI_I2C_UCBCNTIFG: break;         // Vector 28: BCNTIFG
    case USCI_I2C_UCCLTOIFG: break;         // Vector 30: clock low timeout
    case USCI_I2C_UCBIT9IFG: break;         // Vector 32: 9th bit
    default: break;
  }
}
  • Master模式+Slave模式:(单个地址,Slave在接收到Master数据后,接收到的数据)两个程序可以下载到两个MCU中,实现两个MCUI2C通信验证。这个程序里一个Slave可以设置四个地址,产生四个中断,这个也是MSP430 I2C模块的特点。

Maser 程序:

#include <msp430.h>

unsigned char TXData[]= {0xA1,0xB1,0xC1,0xD1};        // Pointer to TX data
unsigned char SlaveAddress[]= {0x0A,0x0B,0x0C,0x0D};
unsigned char TXByteCtr;
unsigned char SlaveFlag = 0;

int main(void)
{

    WDTCTL = WDTPW | WDTHOLD;                         // Stop watchdog timer

    // Configure Pins for I2C
    P1SEL0 |= BIT2 | BIT3;                            // I2C pins

    // Disable the GPIO power-on default high-impedance mode
    // to activate previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;


    // Configure USCI_B0 for I2C mode
    UCB0CTLW0 |= UCSWRST;                             // put eUSCI_B in reset state
    UCB0CTLW0 |= UCMODE_3 | UCMST;                    // I2C master mode, SMCLK
    UCB0BRW = 0x8;                                    // baudrate = SMCLK / 8
    UCB0CTLW0 &=~ UCSWRST;                            // clear reset register
    UCB0IE |= UCTXIE0 | UCNACKIE;                     // transmit and NACK interrupt enable

    SlaveFlag =0;

    while(1)
    {
    __delay_cycles(1000);                             // Delay between transmissions
    UCB0I2CSA = SlaveAddress[SlaveFlag];              // configure slave address
    TXByteCtr = 1;                                    // Load TX byte counter
    while (UCB0CTLW0 & UCTXSTP);                      // Ensure stop condition got sent
    UCB0CTLW0 |= UCTR | UCTXSTT;                      // I2C TX, start condition
    __bis_SR_register(LPM0_bits | GIE);               // Enter LPM0 w/ interrupts
                                                      // Remain in LPM0 until all data
                                                      // is TX'd
    // Change Slave address
    SlaveFlag++;
    if (SlaveFlag>3)                                  // Roll over slave address
      {
        SlaveFlag =0;
      }
    }
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCB0IV,USCI_I2C_UCBIT9IFG))
  {
        case USCI_NONE: break;                        // Vector 0: No interrupts break;
        case USCI_I2C_UCALIFG: break;
        case USCI_I2C_UCNACKIFG:
            UCB0CTL1 |= UCTXSTT;                      //resend start if NACK
          break;                                      // Vector 4: NACKIFG break;
        case USCI_I2C_UCSTTIFG: break;                // Vector 6: STTIFG break;
        case USCI_I2C_UCSTPIFG: break;                // Vector 8: STPIFG break;
        case USCI_I2C_UCRXIFG3: break;                // Vector 10: RXIFG3 break;
        case USCI_I2C_UCTXIFG3: break;                // Vector 14: TXIFG3 break;
        case USCI_I2C_UCRXIFG2: break;                // Vector 16: RXIFG2 break;
        case USCI_I2C_UCTXIFG2: break;                // Vector 18: TXIFG2 break;
        case USCI_I2C_UCRXIFG1: break;                // Vector 20: RXIFG1 break;
        case USCI_I2C_UCTXIFG1: break;                // Vector 22: TXIFG1 break;
        case USCI_I2C_UCRXIFG0: break;                // Vector 24: RXIFG0 break;
        case USCI_I2C_UCTXIFG0:
        if (TXByteCtr)                                // Check TX byte counter
           {
            UCB0TXBUF = TXData[SlaveFlag];            // Load TX buffer
            TXByteCtr--;                              // Decrement TX byte counter
           }
        else
           {
            UCB0CTLW0 |= UCTXSTP;                     // I2C stop condition
            UCB0IFG &= ~UCTXIFG;                      // Clear USCI_B0 TX int flag
            __bic_SR_register_on_exit(LPM0_bits);     // Exit LPM0
           }
          break;                                      // Vector 26: TXIFG0 break;
        case USCI_I2C_UCBCNTIFG: break;               // Vector 28: BCNTIFG
        case USCI_I2C_UCCLTOIFG: break;               // Vector 30: clock low timeout
        case USCI_I2C_UCBIT9IFG: break;               // Vector 32: 9th bit
        default: break;
  }
}

Slave程序:

#include <msp430.h>

unsigned char RXData0=0;
unsigned char RXData1=0;
unsigned char RXData2=0;
unsigned char RXData3=0;

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;                             // Stop watchdog timer

    // Configure Pins for I2C
    P1SEL0 |= BIT2 | BIT3;                                // I2C pins

    // Disable the GPIO power-on default high-impedance mode
    // to activate previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    // Configure USCI_B0 for I2C mode
    UCB0CTLW0 |= UCSWRST;                                 //Software reset enabled
    UCB0CTLW0 |= UCMODE_3;                                //I2C slave mode, SMCLK
    UCB0I2COA0 = 0x0A | UCOAEN;                           //SLAVE0 own address is 0x0A| enable
    UCB0I2COA1 = 0x0B | UCOAEN;                           //SLAVE1 own address is 0x0B| enable
    UCB0I2COA2 = 0x0C | UCOAEN;                           //SLAVE2 own address is 0x0C| enable
    UCB0I2COA3 = 0x0D | UCOAEN;                           //SLAVE3 own address is 0x0D| enable
    UCB0CTLW0 &=~UCSWRST;                                 //clear reset register
    UCB0IE |=  UCRXIE0 | UCRXIE1| UCRXIE2 | UCRXIE3;      //receive interrupt enable

    __bis_SR_register(LPM0_bits | GIE);                   // Enter LPM0 w/ interrupts
    __no_operation();
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
   switch(__even_in_range(UCB0IV,USCI_I2C_UCBIT9IFG))
    {
      case USCI_NONE: break;                            // Vector 0: No interrupts break;
      case USCI_I2C_UCALIFG: break;                     // Vector 2: ALIFG break;
      case USCI_I2C_UCNACKIFG: break;                   // Vector 4: NACKIFG break;
      case USCI_I2C_UCSTTIFG: break;                    // Vector 6: STTIFG break;
      case USCI_I2C_UCSTPIFG: break;                    // Vector 8: STPIFG break;
      case USCI_I2C_UCRXIFG3:                           // SLAVE3
        RXData3 = UCB0RXBUF;
        break;                                          // Vector 10: RXIFG3 break;
      case USCI_I2C_UCTXIFG3: break;                    // Vector 14: TXIFG3 break;
      case USCI_I2C_UCRXIFG2:                           // SLAVE2
        RXData2 = UCB0RXBUF;
        break;                                          // Vector 16: RXIFG2 break;
      case USCI_I2C_UCTXIFG2: break;                    // Vector 18: TXIFG2 break;
      case USCI_I2C_UCRXIFG1:                           // SLAVE1
        RXData1 = UCB0RXBUF;
        break;                                          // Vector 20: RXIFG1 break;
      case USCI_I2C_UCTXIFG1: break;                    // Vector 22: TXIFG1 break;
      case USCI_I2C_UCRXIFG0:                           // SLAVE0
        RXData0 = UCB0RXBUF;                            // Get RX data
        break;                                          // Vector 24: RXIFG0 break;
      case USCI_I2C_UCTXIFG0: break;                    // Vector 26: TXIFG0 break;
      case USCI_I2C_UCBCNTIFG: break;                   // Vector 28: BCNTIFG break;
      case USCI_I2C_UCCLTOIFG: break;                   // Vector 30: clock low timeout break;
      case USCI_I2C_UCBIT9IFG: break;                   // Vector 32: 9th bit break;
      default: break;
    }
}

最后,I2C通信仅仅是规定了协议格式 START STOP等,其实在和外设通信过程中,会在I2C基础上叠加一个特殊的东西,比如你去读EEPROM,那么I2C的数据段需要包括你想读的EEPROM地址,等数据,这个要看每个使用I2C协议的芯片的规定。

最后最后,如果你不想捣鼓这些I2C的东西,你就喜欢UART,那么看下面这个Application Note

Uart to I2c:   查看详情

 

 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表