TI 有关I2C的使用, 提供了EEPROM的例程, 该例程在controlSUITE中可以找到. 该例程写得非常完美, 值得借鉴, 但对于初学者来说还是有难度的. 看了ltbytyn君两篇关于TI 28027的两篇关于I2C的文章, 很受启发, 在此非常感谢他的无私分享.
I2C模块应用篇(查询法)
富士通FRAM应用心得
但在参考上述程序进行设计时 (使用TMS320F28335 I2C), 仍然会遇到种种问题, 特别是初学者, 会花费很多时间, 过程让人倍受煎熬. 下面我将近期项目测试时用到的例程与大家一起分享, 一起学习.
请看下面多字节写的代码
- /******************************************************************************
- 函数名称 : I2CA_Init
- 功能描述 : 初始化I2CA外设, CLK=400kHz
- 传 参 : 无
- 返 回 值 : 无
- ******************************************************************************/
- void I2CA_Init(void)
- {
- // Initialize I2C
- I2caRegs.I2CSAR = I2C_SLAVE_ADDR; // Slave address - RTC control code
- #if (CPU_FRQ_150MHZ) // Default - For 150MHz SYSCLKOUT
- I2caRegs.I2CPSC.all = 14; // Prescaler - need 7-12 Mhz on module clk (150/15 = 10MHz)
- #endif
- #if (CPU_FRQ_100MHZ) // For 100 MHz SYSCLKOUT
- I2caRegs.I2CPSC.all = 9; // Prescaler - need 7-12 Mhz on module clk (100/10 = 10MHz)
- #endif
- I2caRegs.I2CCLKL = 10; // NOTE: must be non zero
- I2caRegs.I2CCLKH = 5; // NOTE: must be non zero
- //I2caRegs.I2CIER.all = 0x24; // Enable SCD & ARDY interrupts
- I2caRegs.I2CIER.all = 0x00; // Disable I2CA interrupts
- I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset
- // Stop I2C when suspended
- I2caRegs.I2CFFTX.all = 0x0000; // Disable FIFO mode
- I2caRegs.I2CFFRX.all = 0x0000; // Disable RXFIFO
- return;
- }
- /******************************************************************************
- 函数名称 : DS1338_WriteMultiByte
- 功能描述 : 设置多个时间寄存器初始值, 或向RAM区的某起始地址写入多个字节(不超过RAM区长度)的内容, 未考虑地址循环情况
- 传 参 : slaveAddr--从设备地址
- regAddr--寄存器或纯存储器地址
- regDat[]--写入的数据
- datLen--数据长度(数据长度和地址长度总和可以超过FIFO深度, 但应在寻址区间内)
- 返 回 值 : 无
- ******************************************************************************/
- void DS1338_WriteMultiByte(Uint16 slaveAddr, Uint16 regAddr, Uint16 regDat[], Uint16 datLen)
- {
- Uint16 i;
- // Wait until the STP bit is cleared from any previous master communication.
- // Clearing of this bit by the module is delayed until after the SCD bit is
- // set. If this bit is not checked prior to initiating a new message, the
- // I2C could get confused.
- [color=Red]while(I2caRegs.I2CMDR.bit.STP == 1);[/color]
- // Setup slave address
- I2caRegs.I2CSAR = slaveAddr;
- // Check if bus busy
- [color=Red]while(I2caRegs.I2CSTR.bit.BB == 1);[/color]
- [color=Blue]// Setup number of bytes to send(datLen + 1)
- I2caRegs.I2CCNT = datLen + 1;[/color]
- // Setup the address to send
- I2caRegs.I2CDXR = regAddr;
- // Send start as master transmitter
- I2caRegs.I2CMDR.all = 0x6E20;
- // Setup data to send
- for (i=0; i<datLen; i++)
- {
- [color=Sienna]while(I2caRegs.I2CSTR.bit.XRDY == 0);[/color]
- I2caRegs.I2CDXR = regDat[i];
- }
- }
复制代码
这里没有开启FIFO, 没有使能中断, 仅通过查询寄存器的状态来进行写操作控制. 红色语句部分, 可以让你连续写操作(几个写函数在一起)时不会出错. 绿色语句中数据长度设置错误会导致停在---
while(I2caRegs.I2CSTR.bit.XRDY == 0);
下面再来看看多字节多
- /******************************************************************************
- 函数名称 : DS1338_ReadMultiByte
- 功能描述 : 读取多个时间寄存器初始值, 或从RAM区的某起始地址读取多个字节的内容, 未考虑地址循环情况
- 传 参 : slaveAddr--从设备地址
- regAddr--寄存器或纯存储器地址
- regDat[]--读取数据的地址
- datLen--数据长度
- 返 回 值 : 无
- ******************************************************************************/
- void DS1338_ReadMultiByte(Uint16 slaveAddr, Uint16 regAddr, Uint16 regDat[], Uint16 datLen)
- {
- unsigned char i;
- // Wait until the STP bit is cleared from any previous master communication.
- // Clearing of this bit by the module is delayed until after the SCD bit is
- // set. If this bit is not checked prior to initiating a new message, the
- // I2C could get confused.
- while(I2caRegs.I2CMDR.bit.STP == 1);
- I2caRegs.I2CSAR = slaveAddr;
- // Check if bus busy
- while(I2caRegs.I2CSTR.bit.BB == 1);
- // Send data to setup RTC address
- I2caRegs.I2CCNT = 1; // Setup how many bytes to expect
- I2caRegs.I2CDXR = regAddr;
- I2caRegs.I2CMDR.all = 0x2620;
- [color=Red]// Wait Register-access-ready
- while(I2caRegs.I2CSTR.bit.ARDY == 0);[/color]
- // Send restart as master receiver
- I2caRegs.I2CCNT = datLen; // Setup how many bytes to expect
- I2caRegs.I2CMDR.all = 0x2C20;
- for(i=0; i<datLen; i++)
- {
- [color=DarkRed]while(I2caRegs.I2CSTR.bit.RRDY == 0);[/color]
- regDat[i] = I2caRegs.I2CDRR;
- }
- }
复制代码
红色语句部分很重要, 不知ltbytyn君代码中美和没有这句, 是不是28027没有这个寄存器(应该不会吧), 感觉应该是 28027的主频低的缘故.
不加判断的话, 同样会导致停在---
while(I2caRegs.I2CSTR.bit.XRDY == 0)处.
小结:
1 这种查询方法效率较低, 耗费CPU资源, 没有利用FIFO, 在实时应用中不可取. 附件中有FIFO例程.
2 I2C总线是比较基础的硬件外设, 很多场合都会用到. TI 的MSP430, C2000, Cortex-M3/M4 均有该外设, 但不同的MCU, I2C使用起来不尽相同, 不过原理都是相通的.
下面附上整个工程源码, 仅供参考.
查询法, 无FIFO
Example_2833x_i2c_ds1338.rar
(181.58 KB, 下载次数: 175)
FIFO 无中断例程
Example_2833x_i2c_ds1338_fifo.rar
(236.81 KB, 下载次数: 172)