微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 关于MSP硬件I2C讲解

关于MSP硬件I2C讲解

时间:11-21 来源:互联网 点击:

AT24C02发送需要写入的存储字节的首地址即可。

在单字节和多字节写操作过程中,尤其要注意UCTXSTT标志位的变化位置。UCTXSTT标志位会在从机接收完写控制字节或读控制字节之后变化,但是在写控制字节发送之后,必须先填充TXBUF,再尝试等待STT标志位复位,此时STT标志位和TXIFG标志位会同时变化。若从机没有应答,那么NACK标志位也会发生变化。再次强调需要先填充TXBUF,在等待STT标志位复位。以下代码将导致程序一直停留在while(UCB0IFG & UCTXSTT)处,具体的原因可查看MSP430参考手册。

  1. while(UCB0CTL1&UCTXSTP);
  2. UCB0CTL1|=UCTR;//写模式
  3. UCB0CTL1|=UCTXSTT;//发送启动位
  4. //等待UCTXSTT=0同时变化,但是很遗憾该变化不会发送
  5. while(UCB0IFG&UCTXSTT);
  6. UCB0TXBUF=word_addr;//发送字节地址


3.写多个字节

3.1代码实现

  1. uint8_teeprom_writepage(uint8_tword_addr,uint8_t*pword_buf,uint8_tlen)
  2. {
  3. while(UCB0CTL1&UCTXSTP);
  4. UCB0CTL1|=UCTR;//写模式
  5. UCB0CTL1|=UCTXSTT;//发送启动位
  6. UCB0TXBUF=word_addr;//发送字节地址
  7. //等待UCTXIFG=1与UCTXSTT=0同时变化等待一个标志位即可
  8. while(!(UCB0IFG&UCTXIFG))
  9. {
  10. if(UCB0IFG&UCNACKIFG)//若无应答UCNACKIFG=1
  11. {
  12. return1;
  13. }
  14. }
  15. for(uint8_ti=0;i
  16. {
  17. UCB0TXBUF=*pword_buf++;//发送寄存器内容
  18. while(!(UCB0IFG&UCTXIFG));//等待UCTXIFG=1
  19. }
  20. UCB0CTL1|=UCTXSTP;
  21. while(UCB0CTL1&UCTXSTP);//等待发送完成
  22. return0;
  23. }


3.2 代码分析

多字节写函数和单字节写函数相似,不做过多的解释。

4.读单个字节

单字节读函数是4中读写函数中最为复杂的,复杂的原因在于读最后一个字节之前就需要操作UCTXSTP标志位。

4.1 代码实现

  1. uint8_teeprom_readbyte(uint8_tword_addr,uint8_t*pword_value)
  2. {
  3. UCB0CTL1|=UCTR;//写模式
  4. UCB0CTL1|=UCTXSTT;//发送启动位和写控制字节
  5. UCB0TXBUF=word_addr;//发送字节地址,必须要先填充TXBUF
  6. //等待UCTXIFG=1与UCTXSTT=0同时变化等待一个标志位即可
  7. while(!(UCB0IFG&UCTXIFG))
  8. {
  9. if(UCB0IFG&UCNACKIFG)//若无应答UCNACKIFG=1
  10. {
  11. return1;
  12. }
  13. }
  14. UCB0CTL1&=~UCTR;//读模式
  15. UCB0CTL1|=UCTXSTT;//发送启动位和读控制字节
  16. while(UCB0CTL1&UCTXSTT);//等待UCTXSTT=0
  17. //若无应答UCNACKIFG=1
  18. UCB0CTL1|=UCTXSTP;//先发送停止位
  19. while(!(UCB0IFG&UCRXIFG));//读取字节内容
  20. *pword_value=UCB0RXBUF;//读取BUF寄存器在发送停止位之后
  21. while(UCB0CTL1&UCTXSTP);
  22. return0;
  23. }

4.2代码分析

这段代码给人一个错觉,MSP430先发送了停止位,然后再读取了一个字节内容。其实实际情况并不是这样的。I2C读操作时,主机读取最后一个字节内容之后,应向从机发送无应答NACK(无应答区别于应答),之后主机发送停止位。MSP430为了完成这一组合动作,要求用户提前操作UCTXSTP标志位,在读取RXBUF之后做出发送NACK和I2C停止位的“组合动作”。

  1. while(!(UCB0IFG&UCRXIFG));
  2. *pword_value=UCB0RXBUF;//读取BUF寄存器在发送停止位之后
  3. UCB0CTL1|=UCTXSTP;//发送停止位

以上代码可能导致后续的I2C操作无法进行。

5.读多个字节

5.1代码实现

  1. uint8_teeprom_readpage(uint8_tword_addr,uint8_t*pword_buf,uint8_tlen)
  2. {
  3. while(UCB0CTL1&UCTXSTP);
  4. UCB0CTL1|=UCTR;//写模式
  5. UCB0CTL1|=UCTXSTT;//发送启动位和写控制字节
  6. UCB0TXBUF=word_addr;//发送字节地址
  7. //等待UCTXIFG=1与UCTXSTT=0同时变化等待一个标志位即可
  8. while(!(UCB0IFG&UCTXIFG))
  9. {
  10. if(UCB0IFG&UCNACKIFG)//若无应答UCNACKIFG=1
  11. {
  12. return1;
  13. }
  14. }
  15. UCB0CTL1&=~UCTR;//读模式
  16. UCB0CTL1|=UCTXSTT;//发送启动位和读控制字节
  17. while(UCB0CTL1&UCTXSTT);//等待UCTXSTT=0
  18. //若无应答UCNACKIFG=1
  19. for(uint8_ti=0;i
  20. {
  21. while(!(UCB0IFG&UCRXIFG));//读取字节内容,不包括最后一个字节内容
  22. *pword_buf++=UCB0RXBUF;
  23. }
  24. UCB0CTL1|=UCTXSTP;//在接收最后一个字节之前发送停止位
  25. while(!(UCB0IFG&UCRXIFG));//读取最后一个字节内容
  26. *pword_buf=UCB0RXBUF;
  27. while(UCB0CTL1&UCTXSTP);
  28. return0;
  29. }


5.2代码分析

读单个字节和写单个字节相似。唯一需要注意的是,写操作需要先填充TXBUF,而读操作不存在这个问题。试想一下,I2C写操作时必定会向I2C从机写入一个字节内容,所以先填充TXBUF也是合情合理的事情,填充TXBUF之后MSP430会进行一连串的动作——发送I2C起始位、I2C读控制器和写入从机的第一个字节。

6 单元测试

单元测试分为两个部分。单字节写函数和单字节读函数分为一组,先使用单字节邪恶函数向某地址写入某内容,在使用单字节读函数读出某内容,如果写入的参数和读出的内容相同,则测试通过

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top