XR20M1172是一块高性能的2通道通用异步接收器和发送器,通常用于串口不够用或外设模块只支持串口的场景中,其输入端有SPI和IIC两种协议可选,输出端两路UART,既可以SPI转串口或IIC转串口。
XR20M1172的协议可定制化程度很高,利用寄存器配置可以很灵活的设置各种所需要的场景,如波特率设置、RTS、奇偶校验、特殊字符匹配、发送接收中断、软硬流控、输入输出FIFO、休眠等等,功能很多,但我们在当前项目的使用当中只涉及了少数的必要功能,所以可能描述的会不全面。
XR20M1172有很多寄存器,但用户可以访问的寄存器都分配在0x00 ~ 0x0F的16个地址中,其中有很多寄存器是共用同一个地址的,由LCR寄存器和只读/只写权限不同,来决定你当时访问操作的具体是哪一个寄存器。
我们在项目中使用XR20M1172这块芯片的背景是,STM32F103的串口不够用了,所以用它来扩展串口,所以下面的内容是基于STM32使用场景,从SPI协议的理论上来讲,这块芯片可以CS很多块同时使用,让你从此告别串口不够用的时代。
如何使用XR20M1172这块芯片,从初始化到发送接收流程如下:
引脚初始化 – 接收中断初始化 – 配置内部寄存器(波特率/输入输出/缓存/串口协议等) - 发送/接收
流程很简单对不对?重点还是在配置XR20M1172这个环节。那下面来讲讲MCU与XR20M1172的连接通信。我们本次使用的是STM32的SPI3端连接(SPI3的SCK引脚PB3是用于JTAG的,所以在使用之前需要先屏蔽掉PB3的JTAG功能复用成SPI3-SCK),在设置好XR20M1172与MCU连接的各引脚后(必须要有SCK/RST/MOSI/MISO/NCS)。就需要考虑MCU与XR20M1172的初次通信了。
其中NCS在配置好后可以直接片选,如果只用到一个SPI也可以不用复选,其中RST在配置完引脚后一定要复位XR20M1172用于重置内部所有寄存器,复位的方式是拉低RST并保持40ns以上,这个时间长点没事儿,一定要确保各引脚配置正确,尤其MISO引脚,很多SPI项目中都是配置的GPIO_Mode_AF_PP复用模式,鉴于稳定性,可以‘或’上GPIO_Mode_IN_FLOATING浮点模式,RST引脚在初始化完成后一定要拉低复位芯片,不然工作可能会遇到一些莫名的错误,在复位完成后切记一定要再拉高,不然会一直处于复位状态。
在引脚配置完成后,配置STM32的内部SPI端口,这里重点要注意的是MCU端的SPI的CPOL和CPHA一定要跟XR20M1172保持一致,不然通信会错,这里我们的STM32配置成:
SPI_CPOL = SPI_CPOL_Low;
SPI_CPHA = SPI_CPHA_1Edge;
然后DataSize配置成8位,SPI双线全双工,MCU主机模式。
在配置XR20M1172的内部寄存器之前我们有必要了解一下其数据读写时序与位格式:
上面两个图中是XR20M1172数据手册中所给的首字节格式和收发数据时序,XR20M1172收发数据都是连续两个字节为一帧,首字节设定当前操作是要读/写、地址、串口通道,首字节格式格式如上图示。第二个字节保存为要发送或接收的数据。
SPI和XR20M1172收发数据都需要通过写操作来给SDA提供时钟信号,所以无论是读还是写,都是由主机MCU给XR20M1172主动发数据,在写操作的时候不保存所返回的数据即可,在读的时候随便给XR20M1172发一个数据来提供时钟信号。
现在可以讲XR20M1172的内部寄存器配置了。
XR20M1172在使用中会用到的寄存器如下表:
地址 |
寄存器 |
读\写 |
注释 |
16C550兼容寄存器 |
|||
0x00 |
RHR - 接收保持寄存器 THR - 发送保持寄存器 |
只读 只写 |
LCR[7] = 0 |
0x00 |
DLL - 除数LSB |
读\写 |
LCR[7] = 1, LCR ¹ 0xBF |
0x01 |
DLM - 除数MSB |
读\写 |
|
0x02 |
DLD - 除数分数 |
读\写 |
LCR[7] = 1, LCR ¹ 0xBF, |
0x01 |
IER - 中断使能寄存器 |
读\写 |
LCR[7] = 0 |
0x02 |
ISR - 中断状态寄存器 FCR - FIFO控制寄存器 |
只读 只写 |
|
0x03 |
LCR - 线路控制寄存器 |
读\写 |
|
0x04 |
MCR - 调制解调器控制寄存器 |
读\写 |
LCR ¹ 0xBF |
0x05 |
LSR - 线路状态寄存器 |
只读 |
|
0x06 |
MSR - 调制解调器状态寄存器 |
只读 |
|
0x07 |
SPR - Scratch Pad Register |
读\写 |
|
0x06 |
TCR - 传输控制寄存器 |
读\写 |
|
0x07 |
TLR - 触发电平寄存器 |
读\写 |
|
0x08 |
TXLVL - 发送FIFO电平 |
只读 |
LCR[7] = 0 |
0x09 |
RXLVL - 接收FIFO级别 |
只读 |
|
0x0A |
IODir - GPIO方向控制寄存器 |
读\写 |
|
0x0B |
IOState -GPIO状态寄存器 |
读\写 |
|
0x0C |
IOIntEna-GPIO中断使能寄存器 |
读\写 |
|
0x0D |
保留 |
|
|
0x0E |
IOControl - GPIO控制寄存器 |
读\写 |
|
0x0F |
EFCR - 额外功能控制寄存器 |
读\写 |
|
0x02 |
EFR - 增强功能寄存器 |
读\写 |
LCR = 0xBF |
0x04 |
Xon-1 - Xon字符1 |
读\写 |
|
0x05 |
Xon-2 - Xon字符2 |
读\写 |
|
0x06 |
Xoff-1 - Xoff字符1 |
读\写 |
|
0x07 |
Xoff-2 - Xoff字符2 |
读\写 |
XR20M1172配置主要在几个非常关键的寄存器上,虽然XR20M1172数据手册上没给我们具体的配置流程,但我们仔细分析上面的内部寄存器表可以发现,在注释栏中有一个寄存器LCR决定着其它寄存器是否能访问,所以我们要设置的第一个寄存器就是LCR – Line status register(不要在意上表中的中文翻译与英文对不上,很实际的说这个表就是Google机翻的,用完就黑-_-!),
我们主要配置XR20M1172的四个地方,软硬流控、波特率、中断、接收数据FIFO区,这四个没有严格的先后顺序要求(没测过,猜想是这样)。
我们先配置软硬流控,在我们的项目中只用到了软流控,既XR20M1172的增强功能,涉及五个寄存器EFR/XON1/XON2/XOFF1/XOFF2,观察内部寄存器表,在注释栏看到我们要设置这五个寄存器就需要先设置LCR = 0Xbf,然后再根据数据手册第四章中的TABLE 8中的内容配置好所需要的软控。在这里我们需要设置好EFR-Bit-4 = 1,在下面的波特率设置中需要它为1才能访问某些地方。
同样,我们要配置波特率,通过数据手册中关于波特率设置相关章节可以发现,XR20M1172的波特率设置主要涉及三个寄存器DLL/DLM/DLD。配置XR20M1172两个输出串口的波特率,在数据手册中给出了一个不算复杂却描述的很绕的公式,具体的在这里就不复述了,可以去看数据手册,这里就给一个非常简便的计算公式:
其中:
CF: Crystal frequency XR20M1172的外部晶振频率(1.83MHz – 24MHz)
SDR: serial data rate 设置的SPI BAUD RATE(16 – 根据MCU的时钟主线计算 – 72M时为4.5M – 这里可能有错,没有确认,我们设置的是16,以数据手册为准)
Baud: baud rate 你想设置的波特率
div: DLL/DLM的波特率整数串联值,其高8位写入DLM,低8位写入DLL
将div写入DLM/DLL中后,如果波特率有小数除数部分,则将小数部分写入DLD中,如果没有就不用写。
设置XR20M1172可预置分频器分频比,根据我们所选用的晶振频率,决定是否要设置该分配比,在EFR bit 4 = 1的情况下可以写入MCR[7]来设置该分频比:
MCR[7] = 1 -> 外部晶振直接用做时钟
MCR[7] = 0 -> 外部晶振除以4用做时钟
在写寄存器的时候,一定要根据内部寄存器表中的注释栏所要求的先决条件,才能准确的写入成功。建议测试的时候,每设置一次就轮询一次所有的寄存器的值,看是否设置成功。
XR20M1172有多个中断,且有中断优先级设定,在使用大于1个中断的时候一定要设置好其内部的中断优先级,否则会搞不清楚IRQ引脚上的中断信号是来自于哪个中断源。我们在项目中只使用到接收FIFO中断,既在FIFO中接收到一定量的数据后,XR20M1172的IRQ引脚拉低给出一个中断信号,该中断信号在你读出所有FIFO中的数据后会自动清掉,但在你没有读出之前其会一直保持低电平中断状态。设置XR20M1172的中断主要是配置IER中断使能寄存器,设置IER之前要先将LCR[7] = 0,根据数据手册很容易配置接收就绪中断只要将IER[0] = 1就可以使能了。
XR20M1172的发送接收有两种模式,一种是透传模式(我这么认为的),一种是FIFO模式。透传模式下,XR20M1172直入直出,一次只能收发一个字节的数据,通过THR/RHR两个寄存器,直出数据,不鼓励接收也使用这种模式,有时候你不知道它啥时候会来数据不是么。FIFO模式下,XR20M1172的数据会先缓存到发送接收的两个独立FIFO中,FIFO大小为64个字节,超过这个大小的时候,数据会溢出状态寄存器会置位,超出的数据会丢失。
FIFO模式的使能和FIFO缓存区大小设定主要涉及FCR/TXLVL/RXLVL,其中FCR配置FIFO的使能以及FIFO溢出中断触发的数据大小阀值(既超过该数值就发出中断,数据手册中有一个表格说明了8种选择),其中TXLVL/RXLVL两个计数寄存器是保持当前实时的接收FIFO中的数据量,发送FIFO中的剩余空间。
至此,基本XR20M1172已经可以用于收发数据了。
收发函数,发送函数很好写,跟串口发送函数一样,一个字节一个字节的发就是了。收函数就在中断函数中置一个标志位,然后在外面写接收函数,同样一个一个接就是了。
Ps:我们在使用过程中,主要遇到的问题在于XR20M1172数据手册中并没有明确的给出寄存器配置流程,以及波特率配置、MCU与XR20M1172的初次通信。
PPs: XR20M1172有很多的功能我们并没有充分的用到,所以还有很多知识点盲区,请勿触及。