stm32使用XR20M1172详细攻略·SPI转UART串口

  • 1.XR20M1172总结概述

XR20M1172是一块高性能的2通道通用异步接收器和发送器,通常用于串口不够用或外设模块只支持串口的场景中,其输入端有SPI和IIC两种协议可选,输出端两路UART,既可以SPI转串口或IIC转串口。

 

XR20M1172的协议可定制化程度很高,利用寄存器配置可以很灵活的设置各种所需要的场景,如波特率设置、RTS、奇偶校验、特殊字符匹配、发送接收中断、软硬流控、输入输出FIFO、休眠等等,功能很多,但我们在当前项目的使用当中只涉及了少数的必要功能,所以可能描述的会不全面。

 

XR20M1172有很多寄存器,但用户可以访问的寄存器都分配在0x00 ~ 0x0F的16个地址中,其中有很多寄存器是共用同一个地址的,由LCR寄存器和只读/只写权限不同,来决定你当时访问操作的具体是哪一个寄存器。

 

我们在项目中使用XR20M1172这块芯片的背景是,STM32F103的串口不够用了,所以用它来扩展串口,所以下面的内容是基于STM32使用场景,从SPI协议的理论上来讲,这块芯片可以CS很多块同时使用,让你从此告别串口不够用的时代。

  • 2.从使用流程到数据收发

如何使用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的内部寄存器之前我们有必要了解一下其数据读写时序与位格式:

                                          stm32使用XR20M1172详细攻略·SPI转UART串口_第1张图片

 

                                           stm32使用XR20M1172详细攻略·SPI转UART串口_第2张图片

上面两个图中是XR20M1172数据手册中所给的首字节格式和收发数据时序,XR20M1172收发数据都是连续两个字节为一帧,首字节设定当前操作是要读/写、地址、串口通道,首字节格式格式如上图示。第二个字节保存为要发送或接收的数据。

 

SPI和XR20M1172收发数据都需要通过写操作来给SDA提供时钟信号,所以无论是读还是写,都是由主机MCU给XR20M1172主动发数据,在写操作的时候不保存所返回的数据即可,在读的时候随便给XR20M1172发一个数据来提供时钟信号。

  • 3.内部寄存器配置

现在可以讲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,
EFR[4] = 1

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两个输出串口的波特率,在数据手册中给出了一个不算复杂却描述的很绕的公式,具体的在这里就不复述了,可以去看数据手册,这里就给一个非常简便的计算公式:

                                                                            div= CF/SDR/Baud

其中:

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有很多的功能我们并没有充分的用到,所以还有很多知识点盲区,请勿触及。

你可能感兴趣的:(嵌入式+,C/C++,STM32)