本应用笔记是探讨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的特性,几乎不需要转换为特定的目标微处理器。它们将依靠本应用笔记中描述的读、写、获取和放置基元来封装微处理器特有的问题。
审核编辑:郭婷
-
处理器
+关注
关注
68文章
19259浏览量
229649 -
寄存器
+关注
关注
31文章
5336浏览量
120230 -
微处理器
+关注
关注
11文章
2258浏览量
82402
发布评论请先 登录
相关推荐
评论