应用笔记 3588

MAXQ2000微控制器软件I²C驱动


摘要 : I²C (内置于集成电路)是一种2线接口,实现集成电路之间的双向通信。本应用笔记介绍MAXQ2000微控制器的软件I²C驱动器,它采用微控制器的任意GPIO引脚,支持100kHz或400kHz的I²C通信。MAXQ系列微控制器具有高速、灵活的GPIO模块以及独立的I/O供电,适用于逐位控制等应用。

引言

I²C (内置集成电路)是一种2线接口,实现集成电路之间的双向通信。本应用笔记介绍maxqi2c库,它是MAXQ2000微控制器(µC)的软件I²C驱动。

maxqi2c库采用扩展C语言编写,由MAXQ的IAR嵌入式平台编译。它由两个文件组成:maxqi2c.hmaxqi2c.c。当这些文件包含在MAXQ2000固件工程时,使用µC的任意GPIO引脚,便可实现100kHz或者400kHz灵活的I²C通信。

MAXQ系列的微控制器具有高速、灵活的GPIO模块以及独立的I/O供电,适用于位拆裂等应用。

本应用笔记讨论的实例工程文件可以从Maxim Integrated网站下载。

配置maxqi2c

用户应将maxqi2c库文件(maxqi2c.hmaxqi2c.c)复制到MAXQ2000工程目录中,对文件进行配置,建立所需的I²C接口。通过编辑以下代码(清单1)实现所有的配置,该代码位于maxqi2c.h源文件的开始:

清单1. maxi2c.h用户定义代码。
/* USER MUST CUSTOMIZE THE FOLLOWING DEFINE STMTS - START */
  // Enter the port used for SDA and SCL
  #define SDA_PORT               0
  #define SCL_PORT               0

  // Enter the pin used for SDA and SCL
  #define SDA_PORT_BIT           0
  #define SCL_PORT_BIT           1

  // Uncomment one of these define statements to select I²C bus speed
  #define I2C_400_KHZ
  //#define I2C_100_KHZ
  
  // Comment out the following define statement to disable clock
  // stretching in i2cRecv()
  #define I2C_CLOCK_STRETCHING
/* USER MUST CUSTOMIZE THE FOLLOWING DEFINE STMTS - END   */
注释:用户定义代码编译时实现,因此,运行时间固定。

选择SCL和SDA引脚

需选择两个GPIO引脚用作SCL和SDA。为SCL和SDA选择了I/O之后,必须对SDA_PORTSCL_PORT定义语句进行编辑,以反映SDA和SCL所需的端口。也必须对SDA_PORT_BITSCL_PORT_BIT定义语句进行编辑,以反映SDA和SCL所需的引脚(在所选端口上)。

上面清单1中的源代码在I/O端口0分配引脚0,作为SDA,在I/O端口0分配引脚1,作为SCL。

选择通信速率

通过注释I2C_400_KHZI2C_100_KHZ两个定义语句之一来选择通信速率。

清单1的源代码通过400kHz I²C总线初始化maxqi2c库,进行通信。由于I²C接口是逐位控制,通信速率实际略低于400kHz (或者,另一种选择100kHz)。为达到全速400kHz通信,固件设计人员必须学习maxi2c库,去掉某些源代码,发挥库的灵活性。

注释:maxqi2c库包括时延以满足I²C规范。这些时延在maxqi2c.c文件的开始,假设MAXQ2000具有20MHz系统时钟;如果采用了速率较低的时钟,可以减小时延。

使用时钟扩展

maxqi2c库的时钟扩展仅在调用i2cRecv()函数开始传送时(地址传输完毕,经过地址确认后,或者在传送开始时)使用。因此,I²C传送可以采用以下格式的时钟扩展:
[S] [ADDR] [R] [A] [clock stretch] [DATA0] [A] ... [DATAN-1] [A]
or
[clock stretch] [DATA0] [A] ... [DATAN-1] [N] [P]
or
[clock stretch] [DATA0] [A] ... [DATAN-1] [A]
使用maxqi2c一节中的i2cRecv()说明,maxqi2c库使用实例一节中的代码解释了怎样产生这些格式的I²C命令。

要使能时钟扩展,则不应注释掉I2C_CLOCK_STRETCHING定义声明。如果不需要时钟扩展,通过注释掉I2C_CLOCK_STRETCHING定义语句禁用它。禁用时钟扩展会稍微提高maxqi2ci2cRecv()函数的速率。

上面清单1的源代码使能时钟扩展。

使用maxqi2c

由4个函数实现maxqi2c库从软件I²C驱动发送和接收数据:i2cInit()、i2cIsAddrPresent()、i2cSend()i2cRecv()。这些函数的文档也包含在maxqi2c.h文件中。

这些函数都不需要正式的参数,而是采用4个全局变量为这些函数存储参数:i2cData (无符号字符 *)、i2cDataLen (无符号整数)、i2cDataAddr (无符号字符)和i2cDataTerm (无符号字符)。该方法在函数调用时不进行数据复制,从而支持固件以更快的速率运行。4个用作maxqi2c库参数的全局变量是:i2cData (无符号字符 *)、i2cDataLen (无符号整数)、i2cDataAddr (无符号字符)和i2cDataTerm (无符号字符)。

i2cInit()

必须在调用任何其他maxqi2c函数之前调用该函数。它初始化maxqi2c.h文件中用户定义代码所选择的端口引脚。该函数不需要参数(局部或者全局),不返回数值。

i2cIsAddrPresent()

该函数使MAXQ2000能够查询I²C总线,以确定是否有特定地址的器件。该函数有一个参数――全局变量i2cDataAddr,它必须由器件地址装入,查询I²C总线是否有器件。该函数还返回一个数值(无符号字符类型)。如果找到了给定地址的器件,该数值等于I2C_XMIT_OK,如果没有找到给定地址的器件,则等于I2C_XMIT_FAILED

为确定在I²C总线上是否有特定器件,i2cIsAddrPresent()按照下面的格式发送一个I²C命令:

[S] [ADDR] [W] [A] [P]

i2cSend()

该函数使MAXQ2000能够通过软件I²C驱动向器件传送数据。i2cSend()需要以下4个参数(均为全局变量)来初始化:
  • i2cData (无符号字符*):被传送字节阵列的第一个字节指针。
  • i2cDataLen (无符号整数):向I²C总线传送的字节数(不包括器件地址)。
  • i2cDataAddr (无符号字符):数据将被传送到的器件的地址。注意,如果该变量设置为0,将不发送地址,传送I²C数据。
  • i2cDataTerm (无符号字符):I²C传送如何结束。调用i2cSend(): I2C_TERM_NONE或者I2C_TERM_STOP时,该变量可以取两个值。
在I²C总线上向器件传送数据的格式取决于4个全局变量的取值。表1列出了这些全局变量不同取值时的I²C命令格式。

表1. i2cSend()送出的I²C命令
i2cDataLen(hex) i2cDataAddr(hex) i2cDataTerm I²C Command Format
0x0002 0x7E I2C_TERM_STOP [S] [ADDR] [W] [A] [DATA0] [A] [DATA1] [P]
0x0002 0x7E I2C_TERM_NONE [S] [ADDR] [W] [A] [DATA0] [A] [DATA1] [A]
0x0002 0x00 I2C_TERM_NONE [DATA0] [A] [DATA1] [A]
0x0002 0x00 I2C_TERM_STOP [DATA0] [A] [DATA1] [A] [P]

注释:表1中的最后3个格式显示了i2cSend()怎样向I²C总线上的同一个器件连续发送数据。

如果寻址器件每一字节作出应答,i2cSend()函数返回一个等于I2C_XMIT_OK的数值(无符号字符类型),如果寻址器件每字节没有应答,返回值则等于I2C_XMIT_FAILED。当一个字节没有得到应答时,函数将立即返回。

i2cRecv()

该函数使MAXQ2000能够使用软件I²C驱动从器件接收数据。i2cRecv()函数需要以下4个参数(均为全局变量)来初始化:
  • i2cData (无符号字符*):存储接收数据阵列的第一个字节指针。
  • i2cDataLen (无符号整数):从I²C总线上接收到的字节数(不包括器件地址)。
  • i2cDataAddr (无符号字符):将要接收数据的器件地址。注意,如果该变量设置为0,将不发送地址,接收I²C数据。
  • i2cDataTerm (无符号字符):I²C传送如何结束。调用i2cRecv(): I2C_TERM_NONEI2C_TERM_ACK或者I2C_TERM_NACK_AND_STOP时,该变量可以取三个值。
在I²C总线上从器件接收数据的格式取决于4个全局变量的取值。表2列出了这些全局变量不同取值时的I²C命令格式。

表2. 禁用时钟扩展,i2cRecv()发送的I²C命令
i2cDataLen(hex) i2cDataAddr(hex) i2cDataTerm I²C Command Format
0x0002 0x7E I2C_TERM_NACK_AND_STOP [S] [ADDR] [R] [A] [DATA0] [A] [DATA1] [N] [P]
0x0002 0x7E I2C_TERM_ACK [S] [ADDR] [R] [A] [DATA0] [A] [DATA1] [A]
0x0002 0x00 I2C_TERM_ACK [DATA0] [A] [DATA1] [A]
0x0002 0x00 I2C_TERM_NACK_AND_STOP [DATA0] [A] [DATA1] [N] [P]

注释:表2中的最后3个格式显示了i2cRecv()怎样从I²C总线上的同一个器件连续接收数据。

如果地址作为I²C命令的一部分进行发送,没有得到应答,i2cRecv()函数返回一个等于I2C_XMIT_FAILED的数值(无符号字符),否则,返回I2C_XMIT_OK

带有时钟扩展的maxqi2c库使用实例

以下实例显示了怎样利用maxqi2c库从MAX1169 ADC接收16位采样,由MAXQ的RS-232端口,将这些数据传送至PC。

原理

采用MAX1169 ADC评估板MAXQ2000评估板(Rev B)实现了该实例。图1显示了两块评估板的连接。MAXQ2000 I/O端口的引脚0和引脚1 (分别在J2-30和J2-28)用作I²C总线上的主机SDA和SCL线。

图1. MAX1169评估板和MAXQ2000评估板(Rev B)连接原理图,将由maxqi2c库使用。
图1. MAX1169评估板和MAXQ2000评估板(Rev B)连接原理图,将由maxqi2c库使用。

注释:MAXQ2000评估板上的MAXQ2000高频晶振(Y1)以20MHz晶振替代。MAX1169评估板的跳接器设置和MAXQ2000评估板的开关设置在表3表4中:

表3. MAX1169评估板的跳接器设置
跳接器 短路器位置
JU1 引脚1和2之间安装短路器
JU2 引脚1和2之间安装短路器
JU3 引脚1和2之间安装短路器
JU4 没有短路器
JU5 没有短路器

表4. MAXQ2000评估板(Rev B)开关设置
开关 位置
SW1-1 断开
SW1-2 断开
SW1-3 断开
SW1-4 打开
SW1-5 断开
SW1-6 断开
SW1-7 打开
SW1-8 断开
SW6-1 断开
SW6-2 断开
SW6-3 断开
SW6-4 断开
SW6-5 断开
SW6-6 断开
SW6-7 断开
SW6-8 打开

固件

该实例(max1169.c)的固件文件在附录A中给出。完整的工程资料可以在Maxim MAXQ2000网页下载,采用MAXQ IAR嵌入式平台编译。该实例中,maxqi2c库的用户定义代码(在maxqi2c.h文件的开始)与清单1的源代码完全相同。

max1169.c文件包括两个头文件:iomaxq200x.hmaxqi2c.h。注意,实例中的iomaxq200x.h文件将忽略MAXQ包含路径IAR嵌入式平台中的iomaxq200x.h文件。iomaxq200x.h文件为maxqi2c库所需的每个端口引脚进行定义。包含了maxqi2c.h文件,以支持固件调用maxqi2c库函数。

固件分成5步,在max1169.c文件中标出(参见附录A)。

第1步初始化UART0,以19200bps进行异步通信。注意,如果MAXQ2000系统时钟不是20MHz,必须修改寄存器PR0的分配以获得所需的波特率。

第2步调用i2cInit()函数,以初始化I²C总线MAXQ2000所使用的引脚。

第3步初始化参数,调用i2cRecv()函数。参数经过初始化,按照下面的格式传送I²C命令:
[S] [ADDR] [R] [A] [clock stretch] [DATA0] [A] [DATA1] [A (termination)] 
第4步将地址参数设置为0。使i2cRecv()函数按照下面的格式传送I²C命令:
[clock stretch] [DATA0] [A] [DATA1] [A (termination)] 
第5步是周期不确定的循环。该循环调用i2cRecv() (按照第4步定义的格式),从MAX1169接收一个16位采样。由UART0将该16位采样传送(MSB在前)至PC。由于匹配参数i2cDataTerm总是等于I2C_TERM_ACK,循环的周期不确定,MAX1169不会看到停止状态。

附录A: max1169.c
/*
 * DEMO of maxqi2c Software I²C Driver
 * (uses evkits for the MAX1169 and MAXQ2000)
 * 
 * DESC: Test program for the maxqi2c.c/maxqi2c.h I²C
 *       driver for the MAXQ2000. The program reads
 *       16-bit samples from the MAX1169 (running in 
 *       continuous conversion mode) and transmits them
 *       using the UART0 port.
 *
 * NOTE - THE FOLLOWING CODE ASSUMES THE MAXQ2000 HAS
 *        A Fsysclk=20MHz.
 */

#include "iomaxq200x.h"
#include "maxqi2c.h"

void main()
{
   unsigned char data[2];

   // 1. Init UART0
   PD7_bit.bit0 = 1;      // Set TX0 pin as output
   SCON0        = 0x42;
   SMD0         = 0x02;
   PR0          = 0x07DD; // 19200bps

   // 2. Init bit-banged I²C port
   i2cInit();

   // 3. Send initial I²C request
   // [S] [ADDR+R] [A] [clock_stretch] [DATA0] [A] [DATA1] [A (termination)] 
   i2cData     = (unsigned char *)(&data); // cast needed!
   i2cDataAddr = 0x7E;
   i2cDataLen  = 0x0002;
   i2cDataTerm = I2C_TERM_ACK;
   i2cRecv();

   // 4. Init continuous conversion
   // [clock_stretch] [DATA0] [A] [DATA1] [A (termination)]
   i2cDataAddr = 0x00;

   // 5. Receive a 16-bit sample and transfer it to the UART0 port
   //    one byte at a time. Repeat forever...
   while (1)
   {
      i2cRecv();
      
      while(!SCON0_bit.TI);   // Wait for UART0 Buffer to be empty
      SCON0_bit.TI = 0;       // Reset TI flag
      SBUF0        = data[0]; // Send data byte 0
      while(!SCON0_bit.TI);   // Wait for UART0 Buffer to be empty
      SCON0_bit.TI = 0;       // reset TI flag
      SBUF0        = data[1]; // Send data byte 1
   }
}
下一步
EE-Mail 订阅EE-Mail,接收关于您感兴趣的新文档的自动通知。
© , Maxim Integrated Products, Inc.
The content on this webpage is protected by copyright laws of the United States and of foreign countries. For requests to copy this content, contact us.
APP 3588:
应用笔记 3588,AN3588, AN 3588, APP3588, Appnote3588, Appnote 3588