完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
楼主觉得如何呀?
|
|
|
|
本帖最后由 guyuemao 于 2016-9-27 00:28 编辑
采用的芯片:MSP430F1611(USART0 Master方式) 设备地址:BH1710(写地址0x46,读地址0x47),AT24C02(写地址0xA0,读地址0xA1) 工程文件:(采取模块化方法,只需添加I2C文件并修改相应的器件模块即可) 懒兔子I2C范例.rar 接口电路: 一般情况下,大家在调试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字节数据,格式及代码如下: StartSlaveAddressWACKDataACKStop 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[]。 |
|
|
|
云汉达人 51单片机的测试代码,自己改写
|
|
|
|
这速度够快的啊
|
|
|
|
云汉达人 专业搜资料;P
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
云汉达人 这个不给币真的好吗?
|
|
|
|
guyuemao 发表于 2016-9-27 00:25 感谢大神。 |
|
|
|
会员你好,有了答案要及时选择最佳答案,别忘了哦
|
|
|
|
会员你好,有了答案要及时选择最佳答案,别忘了哦
|
|
|
|
这种就是个最简单的I2C通信,直接去TI 的SDK里面找个范例改一下就行
|
|
|
|
只有小组成员才能发言,加入小组>>
772 浏览 0 评论
1148 浏览 1 评论
2527 浏览 5 评论
2858 浏览 9 评论
移植了freeRTOS到STMf103之后显示没有定义的原因?
2709 浏览 6 评论
keil5中manage run-time environment怎么是灰色,不可以操作吗?
1065浏览 3评论
190浏览 2评论
453浏览 2评论
368浏览 2评论
M0518 PWM的电压输出只有2V左右,没有3.3V是怎么回事?
453浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-20 05:37 , Processed in 1.210450 second(s), Total 103, Slave 84 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号