MSP430硬件I2C使用方法——以BH1710和AT24C02为例

2021-06-16来源: eefocus关键字:MSP430  硬件I2C  BH1710  AT24C02

硬件的I2C控制器终于调出来了,这些天一直在钻死胡同,其实最好的参考资料还是TI官方提供的。代码参考了MSP430的User’s Guide和Application Note,下面提供IAR工程并做简要解释:

采用的芯片:MSP430F1611(USART0 Master方式)

设备地址:BH1710(写地址0x46,读地址0x47),AT24C02(写地址0xA0,读地址0xA1)


接口电路:


 

一般情况下,大家在调试I2C设备时会首先考虑采用IO口模拟I2C总线的方法,这样的方法思路简单,只需要给出正确的时序即可。但是这样也有意想不到的问题,比如时序的严格性:同样的时序,在BH1710上就能跑通而AT24C02上就时好时坏,读数据正确而写数据有问题,且十有八九都无法写入。也就是说,不同器件对于时序的要求是有差别的,这样即使编写了通用的模拟程序,也会偶尔出些莫名其妙的问题。


于是我开始鼓捣硬件的I2C,MSP430x15x、MSP430x16x系列的USART带有I2C模式,结构如下:

可以看出,I2C可以通过I2CSSELx位选择时钟输入方式,在完成初始化设置后,通过I2CDRW(Byte方式下用I2CDRB表示)来读写数据,下面是一个I2C初始化过程:

初始化过程的大致顺序为将USART设置为I2C模式,配置I2C工作方式、地址、时钟源和分频,启动I2C控制器。这里需要注意的是,I2CSA中填入的是7位地址,即如果设备的写入地址为0xA0,需要令I2CSA = (0xA0 >> 1),即0x50。


SCL的频率则由I2CPSC、I2CSCLH、I2CSCLL共同决定。I2CPSC为预分频,I2CPSC=0时为一分频,I2CPSC=1时为二分频,最高只支持4分频。I2CSCLH和I2CSCLL分别表示SCL高电平和低电平的持续时间,实际时间TH= (I2CPSC +1) x (I2CSCLH + 2),需要什么频率可以自己算,同时也可以为函数增加一个freq参数,在初始化的时候设置频率。请注意根据手册上的说明,I2CIN输入的时钟源频率至少要等于10*SCL* I2CPSC分频数,至于不这么干会怎样,大家可以试试呀。


void I2C_Init(unsigned char slaveAddress)

{

  I2C_PORT_SEL |= SDA_PIN + SCL_PIN;        //设置引脚,用作USART接口

  I2C_PORT_DIR &= ~(SDA_PIN + SCL_PIN);

 

  U0CTL |= I2C+SYNC;                        //USART0配置为I2C模式

  U0CTL &= ~I2CEN;                          //配置I2C前先关闭I2C控制器

                                            //这里采用默认配置,7位地址,无DMA,无反馈

  I2CTCTL = I2CTRX+I2CSSEL_2;               //byte模式,repeat模式,I2C时钟源为SMCLK

  I2CSA = slaveAddress;                     //设置从设备地址

 

  I2COA = 0xAA;                             //本机地址,这个目前用不到

 

  I2CPSC = 0x01;                            //I2C时钟 = SMCLK/2 = 2MHz

  I2CSCLH = 0x18;                           //SCL高电平周期 = 20*I2C clock

  I2CSCLL = 0x18;                           //SCL低电平周期  = 20*I2C clock

                                            //I2C_SCL频率 = 2MHz/20 =100KHz

  U0CTL |= I2CEN;                           //开启I2C控制器

 

  if (I2CDCTL&I2CBUSY)                      //检查I2C模块是否空闲,这里应该是检测时钟正确性吧?

  {                                        

    I2C_PORT_SEL &= ~SCL_PIN;               //将SCL设置为IO输出模式并手动置0

    I2C_PORT_OUT &= ~SCL_PIN;              

    I2C_PORT_DIR |= SCL_PIN;               

    I2C_PORT_SEL |= SDA_PIN + SCL_PIN;      //重新设置引脚为I2C模式

  };

}

 

发送数据以BH1710写入指令函数为例,向I2C从设备写入1字节数据,格式及代码如下:

Start

SlaveAddress

W

ACK

Data

ACK

Stop

 

void BH_WriteCmd(unsigned char Cmd)

{

  while (I2CDCTL&I2CBUSY);        

                                        

  I2CBufferArray[0] = Cmd;

  PtrTransmit = 0;                        

 

  I2C_WriteMod();

  I2CNDAT = 1;                            

                                          

  I2CTCTL |= I2CSTT;                      

                                         

  __bis_SR_register(LPM0_bits + GIE);      

  I2CTCTL |= I2CSTP;                       

  while(I2CTCTL & I2CSTP);               

}


其中I2CNDAT用于指定发送数据的字节数,I2CSTT位设定开始发送, I2CSTP位设定发送结束。在这里,发送函数只是将数据填入缓存中,实际的发送过程在__interrupt void ISR_I2C(void) 中断函数中完成,而在等待发送中断的过程中,系统进入LPM0休眠,整个过程为阻塞式。

 

读取函数与发送函数类似,依然已BH1710为例:

unsigned int BH_Resualt(void)

{

  unsigned char byteHight,byteLow;

  while (I2CDCTL&I2CBUSY);                  //等待I2C模块空闲

 

  I2C_ReadMod();

  I2CNDAT = 2;                              //读取2字节

  I2CTCTL |= I2CSTT;                        //发送Start开始接收

 

  __bis_SR_register(LPM0_bits + GIE);       //进入休眠等待

  byteHight = I2CBuffer;  //高位数据

  __bis_SR_register(LPM0_bits + GIE);

  byteLow = I2CBuffer;    //低位数据

 

  I2CTCTL |= I2CSTP;                        //发送Stop结束接收

  while(I2CTCTL & I2CSTP);                  //等待Stop发送完毕

 

  return ((((unsigned int)byteHight)<<8)+byteLow);//合成数据

}


需要注意的是,BH1710一次返回两个字节数据,需令I2CNDAT = 2,同时在读完一次缓存后再读取下一个。


对于AT24C02,读取方式有任意地址和当前地址读取的差别,可以参见工程代码。


最后是中断函数:

#pragma vector=USART0TX_VECTOR

__interrupt void ISR_I2C(void)

{

  switch (__even_in_range(I2CIV, I2CIV_STT))

  {

     case I2CIV_RXRDY:   //接收就绪 (RXRDYIFG)

      I2CBuffer = I2CDRB;                   //读取数据,跳出休眠

      __bic_SR_register_on_exit(LPM0_bits);

      break;

    case I2CIV_TXRDY:   //发送就绪 (TXRDYIFG)

      while(!(I2CDCTL & I2CTXUDF));         //等待上一个数据发送完毕

      I2CDRB = I2CBufferArray[PtrTransmit]; //发送Buff中的数据

      PtrTransmit--;

      if (PtrTransmit < 0)                  //PtrTransmit为发送数据个数的自减计数器,减完表示发送结束

      {

        I2CIE &= ~TXRDYIE;                  //最后清标志位

        I2CIFG &= ~TXRDYIFG;               

        __bic_SR_register_on_exit(LPM0_bits);

      }

      break;

  }

}


I2C的中断变量就是串口发送中断USART0TX_VECTOR,这里只用到了RXRDY 和TXRDY,其他的中断标志位判断已包含在工程文件里,需要时可添加相应代码。这里的接收缓存I2CBuffer只能存储一个字节数据,接收多个字节时需要多次接收,有大量数据接收需要的童鞋可以改成数组的形式,操作方法同I2CBufferArray[]。

[1] [2]
关键字:MSP430  硬件I2C  BH1710  AT24C02 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic538743.html

上一篇:采用MSP430设计的12位心电(ECG)放大器
下一篇:MSP430户外运动环境监测仪

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

MSP-EXP430G2 LaunchPad学习笔记:MSP430G2231存储器组织
摘要:本文以MSP430G2231为例,整理了其存储器组织各个部分的内容,包括特殊功能寄存器、外围模块、RAM、FLASH、中断向量表。 PS:本文系学习MSP430的整理笔记,为了是将Contiki移植到LaunchPad。一、存储器组织[1]1.1 小模式从0x0000到0xFFFF分别是:特殊功能寄存器SFR、外围模块、数据存储器、程序存储器、中断向量表。不同型号的存储器组织不尽不同,使用时得具体参考数据手册,但具有以下共性[1]:(1)特殊功能寄存器、8位外围模块、16位外围模块地址范围一样特殊功能寄存器 0x0000~0x000F;8位外围模块 0x0010~00FF16位外围模块 0x0100~0x01FF
发表于 2021-07-16
<font color='red'>MSP</font>-EXP<font color='red'>430</font>G2 LaunchPad学习笔记:<font color='red'>MSP430</font>G2231存储器组织
msp430单片机开发实录(25)
现象:产品开发完成,并且经过严苛、详细的测试后,已经开始批量生产了,但是大家提出一个问题:能不能把功耗再降低一些,目前产品的功耗有些高(超过50uA),用干电池供电的话,用不了1年就要换电池。试验:因为我们一直以来的产品都是电池供电的,对于产品的功耗一直都做得很低,这也是我们一直使用TI的MSP430系列单片机的原因,因为它的超低功耗做的确实很好。不过这款产品因为功能太多,并且有一个很好点的地方:每1s都要进行一次串口通信(每次通信几十个字节,波特率9600),在最初方案设计以及产品验证时,所有参与人员都认为目前的功耗已经做到最好了,没有再下降的空间了。并且这款产品的功耗与其他厂家同类产品相比,功耗基本一样。所以就觉得功耗降不下来
发表于 2021-07-16
MSP430F1611学习笔记
/* MSP430的I/O口的驱动能力*/每个I/O口最大输出或者吸收电流为6mA所有I/O电流总和不超过48mA// 晶振频率: 8.000200Mhz/*MSP430的3V与5V逻辑兼容性问题*/MSP430单片机的任何一个引脚输入电压不能超过VCC+0.3V,不能低于-0.3V,否则将启动内部泄放电路.泄放电路最大只能吸收2mA电流,超过2mA可能会损坏I/O口./* 发光二极管压降*/红色的压降为2.0--2.2V×××的压降为1.8—2.0V绿色的压降为3.0—3.2V。正常发光时的额定电流均为20mA。白色发光二极管的正向电压降约为3.5V左右,需要正向工作电流≥15mA左右时,才能使其正常发光。/* 位操作
发表于 2021-07-16
MSP430与ATK-NEO-6M GPS模块
近短时间在网上买了一个GPS模块,正好正在学习MSP430单片机,于是决心将GPS模块与MSP430结合起来,同时将代码贴出来,发现网上搜到好多资料都要注册才能下载,有些还要钱。自己动脑,才能自娱自乐。一、测试篇刚拿到ATK-NEO-6M这个型号的GPS模块,有点不大相信,近100块的东西居然只有3cm那么大一点。之前在网上下载了相关的资料,第一次快速测试肯定是借助电脑,正好msp430开发板上有max232模块,直接将GPS模块的TX接max232的TX,RX同样。PC端安装u-center,u-center 是由ublox 公司提供的GPS 评估软件,功能十分强大,可以对我们的ATK-NEO-6M GPS 模块进行全面的测试
发表于 2021-07-16
<font color='red'>MSP430</font>与ATK-NEO-6M GPS模块
msp430实现串口计算器
工程下载链接:https://download.csdn.net/download/qq_45467083/12100424 本次实验实现了基于串口通信的表达式解析与计算功能,如下图所示,向单片机输入表达式:9*9*8 +9/3*6-3*8 * (1 * 5+4 * (2-2)+5)/(3-1 * 9)=;(空格会自动忽略); 返回计算结果:706,等等。实验配置了一个波特率为115200的串口UART,在接受缓存满和发送缓存空的时候都会产生中断。在接受中断中调用oneCharProcess(revChar_temp);处理接受字符,在发送中断中发送待发送字符串。中断服务程序如下:/* ======== USCI A0/B0 TX
发表于 2021-07-16
<font color='red'>msp430</font>实现串口计算器
MSP430的学习(4)
TA是一个16的定时/计数器,最多拥有3个捕获/比较寄存器。TA可以支持捕获/比较功能  PWM输出和定时器功能。TA还有扩展中断的功能,中断可以由定时器溢出产生或捕获比较寄存器产生。定时器的时钟源可以是内部时钟源ACLK,SMCLK,或外部源TACLK INCLK。时钟源由TASSEL来选择,然后通过ID位来进行2 4或8分频。定时器的2种启动方式:1 :当计数到MCX〉0并且时钟源处于活动状态时。2:当定时器模式为up uo/down模式时,定时器可以通过写0到TACCR0来停止计数。定时器可以通过写一个非0的数值来重新开始计数。定时器模式控制:(操作模式由MC位来选择)。1:单调模式:用于计数周期不是0FFFFH的情
发表于 2021-07-16
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved