MAX3108和控制微处理器之间的基本接口解析

描述

本应用笔记是探讨MAX3108高性能通用异步接收器/发送器(UART)特性系列笔记中的第一篇,解释了MAX3108和控制微处理器之间的基本接口。应用笔记简要介绍了通过2、4或6引脚实现硬件连接;实现31个寄存器,可通过SPI或I²C接口访问;和三种复位机制。下面详细介绍了SPI和I²C接口以及伪代码示例。

介绍

MAX3108为高性能通用异步收发器(UART),采用晶圆级封装(WLP),理想用于低功耗便携式设备。其高级功能范围从单独的 128 字发送和接收 FIFO 到广泛的硬件介导流控制。然而,在应用利用这些特性之前,它必须与MAX3108及其31个内部寄存器进行可靠的通信。本应用笔记介绍了MAX3108通信的基本原理。有关伪代码的软件约定显示在附录中。

硬件连接

MAX3108与微处理器(μP)之间的通信通过2、4或6个引脚进行。两个专用引脚IRQ和RST通常连接到微处理器 GPIO 引脚。IRQ是微处理器的输入引脚。作为双功能信号,IRQ既指示MAX3108复位何时完成,又在发生某些可编程UART事件时通知微处理器。RST是微处理器的输出引脚。它可靠地强制MAX3108复位至已知状态。尽管可以在不使用这些引脚的情况下实现功能应用程序,但最好连接它们,除非缺少 GPIO 引脚。

MAX3108实现31个寄存器,每个寄存器一个字节宽,可通过SPI或I²C接口访问,该接口在硬件中选择。由于其更大的带宽和更简单的实现,SPI接口更可取。将 SPI I²C 引脚连接到高电平可实现 SPI 接口。将其设置为低电平可实现I²C接口。

MAX3108 SPI接口直接连接到微处理器上常用的SPI硬件引擎时效果最佳。

微处理器 SPI 引脚 MAX3108引脚
MISO MISO/SDA
MOSI MOSI/A1
SCLK SCLK/SCL
SS CS

与其他SPI接口实现不同,即使MAX3108是SPI总线上唯一的器件,从选择(SS)信号也必须连接到MAX3108。

同样,I²C接口在直接连接到微处理器上的I²C硬件引擎时效果最佳。

微处理器I²C引脚 MAX3108引脚
SCL SCLK/SCL
SDA MISO/SDA

 

与SPI接口不同,I²C接口依赖于总线上具有唯一I²C地址的每个外设。为帮助避免地址冲突,引脚MOSI/A1和%-overbar_pre%CS%-overbar_post%/A0上的硬件引脚搭接选项可将MAX3108 I²C外设地址固定为16种可能性之一。

重置

MAX3108具有三种复位机制,所有这些机制都使MAX3108处于已知状态,需要后续寄存器设置负载。

第一种复位机制是在上电时自动复位。MAX3108要完成复位,无需时钟。但是,1.8V电源必须启动并运行。LDOEN 必须连接高电平,或者如果 LDOEN 连接为低电平,则必须将有效的 1.8V 电源连接到 V18 引脚。仅在复位期间,%-overbar_pre%IRQ%-overbar_post%引脚不是中断指示器,而是复位完成指示器。一旦%-overbar_pre%IRQ%-overbar_post%引脚变为高电平,复位完成。如果MAX3108不存在或未上电,程序流可能会无限期地卡在环路中。如果这是一个问题,请添加一个计时器。如果 %-overbar_pre%IRQ%-overbar_post% 在 300μs 后仍未出现,您可以假设有问题。为避免在MAX3108完全就绪之前写入寄存器,应用必须遵循以下步骤。

/*
** Wait for the MAX3108 to come out of reset
*/
   
   // Wait for the IRQ pin to come up, as this
   // indicates that the MAX3108 reset is complete
   while (POLL_MAX3108_IRQ == 0);

第二种复位机制是通过MAX3108 RST引脚进行硬件复位。在这种情况下,手动将RST引脚脉冲为低电平,然后为高电平。与上电时自动复位一样,%-overbar_pre%IRQ%-overbar_post%引脚表示复位完成。如上所述,为防止MAX3108缺电或未上电时无限期卡在环路中,增加一个延迟最小为300μs的定时器。伪代码见下文。while

 

/*
** Perform a hardware reset
*/
   SET_MAX3108_RESET_PIN_LOW;
   WAIT (1µs);
   SET_MAX3108_RESET_PIN_HIGH;

   // Wait for the IRQ pin to come up, as this
   // indicates that the MAX3108 reset is complete
   while (POLL_MAX3108_IRQ == 0);

第三种复位机制是软件控制的复位,依赖于MAX3108的SPI或I²C访问。与其他复位一样,MAX3108寄存器需要在复位完成后重新加载。使用以下伪代码调用重置。

 

/*
** Software reset of the MAX3108
*/
   MAX3108_Write (MAX3108R_MODE2, 0x01);
   MAX3108_Write (MAX3108R_MODE2, 0x00);

通过 SPI 接口

MAX3108与微处理器之间的通信通过%-overbar_pre%RST%-overbar_post%引脚、%-overbar_pre%IRQ%-overbar_post%引脚(均如上所述)以及应用微处理器和MAX3108寄存器之间的接口进行。该寄存器接口可以是SPI或I²C接口。有关SPI选项的详细信息在此处,而有关I²C接口的详细信息显示在通过I²C接口部分。

SPI 接口是微处理器上常用的硬件接口。SPI接口的另一个优点是它的速度。MAX3108可支持高达26Mbps的SPI数据速率,比目前大多数微处理器SPI硬件更快。

MAX3108 SPI接口不仅支持单寄存器读写,还支持突发读写。这些突发事务提高了寄存器接口的效率,进一步推开了寄存器接口成为瓶颈的点。

与其他SPI方案不同,微处理器上SPI主硬件的SS信号必须连接至MAX3108 %-overbar_pre%CS%-overbar_post%/A0引脚。除了选择SPI总线外设的传统用途外,%-overbar_pre%CS%-overbar_post%/A0引脚还向MAX3108发出SPI事务边界信号。%-overbar_pre%CS%-overbar_post%/A0的下降沿向MAX3108表示SPI接口上的下一个字节是MAX3108寄存器地址。%-overbar_pre%CS%-overbar_post%/A0的上升沿向MAX3108发出信号,表明SPI事务(单次读取、单次写入、突发读取或突发写入)已经结束。

SPI 事务本质上是双向的。对于从微处理器写入MAX3108的每个字节,MAX3108同时返回一个字节到微处理器。这些往往可以忽略;寄存器写操作忽略MAX3108的返回字节。类似地,寄存器读取返回其值,微处理器向MAX3108发送虚拟字节。这些虚拟字节不会降低接口速度,因为它们与有效的寄存器读取或写入数据同时发生。

单 SPI 写入

单个写入事务的伪代码如下所示:

 

/*
** Write one byte to the specified register in the MAX3108
**
** Arguments: 
** port: MAX3108 register address to write to (0x00 through 0x1e)
** val: the value to write to that register
**
** return value:  TRUE
**
*/
BOOL MAX3108_SPI_Write (unsigned int port,
                        unsigned char val) {
   unsigned int dummy;

   // Indicate the start of a transaction
   SET_MAX3108_CS_PIN_LOW;

   // Write transaction is indicated by MSbit of the
   // MAX3108 register address byte = 1.  SPI return
   // from the MAX3108 ignored
   dummy = SPI_SEND_BYTE (0x80 | port);

   // Now send the value to write, return value ignored
   dummy = SPI_SEND_BYTE (val);

   // Finally, indicate transaction completion
   SET_MAX3108_CS_PIN_HIGH;

   return TRUE;
}

突发 SPI 写入

MAX3108 SPI接口还支持突发写入,适用于快速FIFO填充或快速寄存器负载。如果寄存器地址为零,则突发写入将填充发送FIFO。这允许快速FIFO填充,无需切换MAX3108 %-overbar_pre%CS%-overbar_post%/A0线或为每个写入FIFO字节发送寄存器地址。

对于任何其他MAX3108寄存器地址,寄存器地址随着突发的每个后续字节自动递增,从而允许快速寄存器填充。

突发写入事务的伪代码如下所示:

 

/*
** Write a burst of bytes to the MAX3108
**
** Arguments:
** port: MAX3108 register address to write to
** len: number of bytes to send to MAX3108 registers
** ptr: pointer to the bytes to send
**
** return value:  TRUE
**
*/
BOOL MAX3108_SPI_Puts (unsigned int port,
                       unsigned int len,
                       unsigned char *ptr) {

   unsigned int dummy;

   // Indicate the start of a transaction
   SET_MAX3108_CS_PIN_LOW;

   // Write transaction indicated by MSbit of the
   // MAX3108 register address byte = 1.  SPI return
   // from the MAX3108 ignored
   dummy = SPI_SEND_BYTE (0x80 | port);

   // Covers the case where len==0
   while (len--) {
      dummy = SPI_SEND_BYTE (*ptr++);  // return value ignored
   }

   // Indicate transaction completion
   SET_MAX3108_CS_PIN_HIGH;

   return TRUE;
}

注意,对于突发写入事务,第一个字节是MAX3108寄存器地址,所有后续字节都是寄存器值写入。最终寄存器写入由CS A0引脚变为高电平表示。

SPI硬件引擎(通常基于DMA)也控制MAX3108 CSA0引脚,通常通过标有overbar_post overbar_pre SS的引脚。当CS A0 变低时,表示下一个 SPI 事务开始。CSA0必须保持较高的最短时间为100ns。此时确保MAX3108识别出交易已完成。

单 SPI 读取

通过SPI读取寄存器字节涉及发送寄存器地址,后跟虚拟字节。来自虚拟字节的SPI反馈是所选MAX3108寄存器的值。

单次读取的伪代码如下:

 

/*
** Read one byte from the specified register in the MAX3108
**
** Arguments: 
** port: MAX3108 register address to read from
**
** return value:  the register value
**
*/
unsigned int MAX3108_SPI_Read (unsigned int port) {
   unsigned int dummy;
   unsigned int val;

   // Indicate the start of a transaction
   SET_MAX3108_CS_PIN_LOW;

   // Read transaction indicated by MSbit of the
   // address byte = 0.  SPI return from the MAX3108
   // ignored
   dummy = SPI_SEND_BYTE (port & 0x7f);

   // Now send a dummy byte to collect the 
   // register value
   val = SPI_SEND_BYTE (0x00);

   // Finally, indicate transaction completion
   SET_MAX3108_CS_PIN_HIGH;

   return val;
}

突发 SPI 读取

MAX3108 SPI接口还支持突发读取,适用于快速FIFO清空或快速寄存器扫描。如果寄存器地址为零,则突发读取为空接收FIFO。这样就可以快速进行FIFO转储,而无需切换MAX3108 %-overbar_pre%CS%-overbar_post%/A0线或为每个FIFO字节读取发送寄存器地址。

对于任何其他MAX3108寄存器地址,寄存器地址随着突发的每个后续字节自动递增,从而允许快速寄存器扫描。

突发读取事务的伪代码如下:

 

/*
** Read a burst of bytes from the MAX3108
**
** Arguments:
** port: MAX3108 register address to read from
** len: number of bytes to get from MAX3108 registers
** ptr: pointer to where to place the bytes
**
** return value:  TRUE
**
*/
BOOL MAX3108_SPI_Gets (unsigned int port,
                       unsigned int len,
                       unsigned char *ptr) {

   unsigned int dummy;

   // Indicate the start of a transaction
   SET_MAX3108_CS_PIN_LOW;

   // Read transaction indicated by MSbit of the
   // address byte = 0.  SPI return from the MAX3108
   // ignored
   dummy = SPI_SEND_BYTE (port & 0x7f);

   // Covers the case where len==0
   while (len--) {
      *ptr++ = SPI_SEND_BYTE (0x00);
   }

   // Indicate transaction completion
   SET_MAX3108_CS_PIN_HIGH;

   return TRUE;
}

注意,对于突发读取事务,第一个字节是MAX3108寄存器地址,所有后续字节都是假字节,其返回值为寄存器值。最终寄存器读取由%-overbar_pre%CS%-overbar_post%/A0引脚变为高电平表示。

通过I²C接口

MAX3108寄存器和微处理器之间的通信也可以通过I²C接口进行。

I²C接口是微处理器上常见的硬件辅助接口。I²C接口的另一个优点是它只使用两个引脚。I²C接口不是为每个外设单独选择片(如SPI接口),而是依赖于具有唯一I²C地址的每个外设。为避免与同一I²C总线上的其他I²C外设发生冲突,MAX3108可通过MOSI/A1和%-overbar_pre%CS%-overbar_post%/A0引脚的引脚搭接,对16个唯一的I²C外设地址进行引脚编程。在下面的伪代码中,假定预处理器变量MAX3108_I2C_PERIPHERAL_ADDRESS使用适当的I²C寄存器写入地址进行定义,该地址与同一总线上的任何其他I²C外设的地址是唯一的。

MAX3108不仅支持标准模式(100kbps)和快速模式(400kbps)I²C,还支持快速模式加(1Mbps)I²C。

MAX3108 I²C接口不仅支持单寄存器读写,还支持突发读写。这些突发事务提高了寄存器接口的效率,进一步推开了寄存器接口成为瓶颈的点。

单路I²C写入

单个写入事务的伪代码如下所示:

 

/*
** Write one byte to the specified register in the MAX3108
**
** Arguments: 
** port: MAX3108 register address to write to
** val: the value to write to that register
**
** return value:  TRUE – register successfully written
**                FALSE – I2C protocol error of some kind
**
*/
BOOL MAX3108_I2C_Write (unsigned int port,
                        unsigned char val) {
   
   // Indicate the start of a transaction and send the
   // MAX3108 write peripheral address (LSbit = 0)
   I2C_SET_START_CONDITION;
   I2C_SEND_BYTE (MAX3108_I2C_PERIPHERAL_ADDRESS);

   // Is anybody out there?
   if (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;  // no – close out the
      return FALSE;            //  transaction
   }

   // The MAX3108 is out there, now send the MAX3108
   // register to write
   I2C_SEND_BYTE (port);

   // Possibly illegal MAX3108 register address?
   If (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;
      return FALSE;
   }

   // Now send the byte to write
   I2C_SEND_BYTE (val);

   // Did the MAX3108 get confused?
   If (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;
      return FALSE;
   }

   // The MAX3108 is OK with our write, make it so
   I2C_SET_STOP_CONDITION;
   return TRUE;
}

突发I²C写入

MAX3108 I²C接口还支持突发写入,适用于快速FIFO填充或快速寄存器负载。如果寄存器地址为零,则突发写入将填充发送FIFO。这允许快速FIFO填充,而无需为每个写入FIFO字节产生I²C前导码开销。

对于任何其他MAX3108寄存器地址,寄存器地址随着突发的每个后续字节自动递增,从而允许快速寄存器填充。

突发写入事务的伪代码如下所示:

 

/*
** Write a burst of bytes to the MAX3108
**
** Arguments:
** port: MAX3108 register address to write to
** len: number of bytes to send to MAX3108 registers
** ptr: pointer to the bytes to send
**
** return value:  TRUE – register successfully written
**                FALSE – I2C protocol error of some kind

**
*/
BOOL MAX3108_I2C_Puts (unsigned int port,
                       unsigned int len,
                       unsigned char *ptr) {

   // Indicate the start of a transaction and send the
   // MAX3108 write peripheral address (LSbit = 0)
   I2C_SET_START_CONDITION;
   I2C_SEND_BYTE (MAX3108_I2C_PERIPHERAL_ADDRESS);

   // Is anybody out there?
   if (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;  // no – close out the
      return FALSE;            //  transaction
   }

   // The MAX3108 is out there, now send the MAX3108
   // register address
   I2C_SEND_BYTE (port);

   // Possibly illegal MAX3108 register address?
   If (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;
      return FALSE;
   }

   while (len--) {
      // Now send the byte to write
      I2C_SEND_BYTE (*ptr++);

      // Did the MAX3108 get confused?
      if (!I2C_TEST_ACK) {
         I2C_SET_STOP_CONDITION;
         return FALSE;
      }
   }

   // The MAX3108 is OK with our write, make it so
   I2C_SET_STOP_CONDITION;
   return TRUE;
}

注意,对于突发写入事务,第一个字节是MAX3108 I²C外设地址,第二个字节是MAX3108寄存器地址,所有后续字节都是要写入的寄存器值。最终寄存器写入由 STOP 条件指示。

单路I²C读取

通过I²C读取寄存器字节包括发送MAX3108读寄存器地址,然后I²C重启条件,将I²C总线从写(到MAX3108指定MAX3108寄存器)转为读(获取寄存器值)。

单次读取的伪代码如下:

 

/*
** Read one byte from the specified register in the MAX3108
**
** Arguments: 
** port: MAX3108 register address to read from
**
** return value:  the register value (0x00XX)
**                0xff00 is there was some error
**
*/
unsigned int MAX3108_I2C_Read (unsigned int port) {

   unsigned int val;

   // Indicate the start of a transaction and send the
   // MAX3108 write peripheral address (LSbit = 0)
   I2C_SET_START_CONDITION;
   I2C_SEND_BYTE (MAX3108_I2C_PERIPHERAL_ADDRESS);

   // Is anybody out there?
   if (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;  // no – close out the
      return 0xff00;           //  transaction
   }

   // The MAX3108 is out there, now send the MAX3108
   // register address
   I2C_SEND_BYTE (port);

   // Possibly illegal MAX3108 register address?
   If (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;
      return 0xff00;
   }

   // Now turn the I2C bus around by sending the MAX3108
   // I2C peripheral read address (LSbit = 1)
   I2C_SET_RESTART_CONDITION;
   I2C_SEND_BYTE (MAX3108_I2C_PERIPHERAL_ADDRESS | 0x01);

   if (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;
      return 0xff00;
   }

   // Now get the register value
   val = I2C_RECEIVE_BYTE;
   I2C_SEND_NACK;
   I2C_SET_STOP_CONDITION;

   return (val);
}

突发I²C读取

MAX3108 I²C接口还支持突发读取,适用于快速FIFO清空或快速寄存器扫描。如果寄存器地址为零,则突发读取为空接收FIFO。这允许快速FIFO转储,而不会产生与每个FIFO字节读取的I²C前导码相关的开销。

对于任何其他MAX3108寄存器地址,寄存器地址随着突发的每个后续字节自动递增,从而允许快速寄存器扫描。

突发读取事务的伪代码如下所示:

 

/*
** Read a burst of bytes from the MAX3108
**
** Arguments:
** port: MAX3108 register address to read from
** len: number of bytes to get from MAX3108 registers
** ptr: pointer to where to place the bytes
**
** return value:  TRUE – if all read
**                FALSE – if there was any error
**
*/
BOOL MAX3108_I2C_Gets (unsigned int port,
                       unsigned int len,
                       unsigned char *ptr) {




   // Indicate the start of a transaction and send the
   // MAX3108 write peripheral address (LSbit = 0)
   I2C_SET_START_CONDITION;
   I2C_SEND_BYTE (MAX3108_I2C_PERIPHERAL_ADDRESS);

   // Is anybody out there?
   if (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;  // no – close out the
      return FALSE;           //  transaction
   }

   // The MAX3108 is out there, now send the MAX3108
   // register address
   I2C_SEND_BYTE (port);

   // Possibly illegal MAX3108 register address?
   If (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;
      return FALSE;
   }

   // Now turn the I2C bus around by sending the MAX3108
   // I2C peripheral read address (LSbit = 1)
   I2C_SET_RESTART_CONDITION;
   I2C_SEND_BYTE (MAX3108_I2C_PERIPHERAL_ADDRESS | 0x01);

   if (!I2C_TEST_ACK) {
      I2C_SET_STOP_CONDITION;
      return FALSE;
   }

   // Now get the register values
   while (len--) {
      *ptr++ = I2C_RECEIVE_BYTE;
      if (len)
         I2C_SEND_ACK;     // all but last read
      else
         I2C_SEND_NACK;    // last read only
   }
 
   I2C_SET_STOP_CONDITION;
   return TRUE;
}

注意,对于突发读事务,第一个字节是MAX3108 I²C外设写地址,第二个字节是MAX3108寄存器地址,第三个字节是MAX3108 I²C外设读地址,所有后续字节都是寄存器值。微处理器在要读取更多寄存器时,以 ACK 条件响应每个字节读取。NACK条件表示从MAX3108读取的最终寄存器。

结论

按照本应用笔记提供的编码指南,可以快速启动并运行微处理器和MAX3108之间的接口。

本应用笔记中伪代码例程的大部分翻译都是特定于微处理器的。除中断处理程序外,本系列中的其他特定代码应用笔记详细探讨了MAX3108的特性,几乎不需要转换为特定的目标微处理器。它们将依靠本应用笔记中描述的读、写、获取和放置基元来封装微处理器特有的问题。

审核编辑:郭婷

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分