weiqi7777

cortex-a8裸机系列:第十一章 串口

0
阅读(2003)

一、            210UART控制器

210提供了4UART4UART可以工作在中断或者DMA模式。串口能产生中断或者DMA请求数据传输信号。UART支持最大比特率3Mbps。每个UART包含了两个FIFO,用来接收和发送数据。

         对于ch0,有256字节,对于ch1,有64字节,对于ch2ch3,有16字节。

 

         UART包括一个波特率产生器,发送器,接收器和控制单元。

clip_image002

        

         时钟源可以有两个选择,PCLKSCLK_UART

         当数据写入到发送FIFO,硬件会自动的将数据拷贝到发送移位器中,然后通过发送管脚(TXDN)一位一位发送出去。

         当从接收移位器从接收数据管脚(RXDN)中接收到数据后,会将该数据拷贝到接收FIFO中。

二、            自动流控(AFCauto flow control

解决发送方和接收方之间数据传输不一致导致数据丢失的情况,因此加了几个信号,实现流控制。

         对于发送方,要发送数据的时候,要将一根控制线拉高,接收方接收到该控制信号为高,表示要接收数据。

对于接收方,可以接收数据的时候,将一根控制线拉高,发送方接收到该控制信号为高,表示可以发送数据。

所以,流控的目的是使串口通信变得可靠,在发送方速率比接收方快的时候,流控可以保证发送和接收均不会漏掉数据。不过,现在已经是不使用该功能了。

三、            IrDA模式及其用法

1.         IrDA其实就是红外,红外就是红外线通信(电视机,空调遥控器就是红外通信)。

2.         红外编码传输和串口传输很类似,按照一定时间,发送红外,有发送红外线,表示传输1,没有发送红外线,表示传输0

3.         红外通信的原理:发送方固定间隔时间向接收方发送红外信号(表示10)或者不发送红外信号(表示01),接收方每隔固定时间去判断有无红外线信号来接收10

4.         因此红外通信和串口通信很类似,都是每隔固定时间发送1或者0(判断10的物理方式不同)给接收方来通信。因此,210就利用串口通信来实现了红外发送和接收

5.         210的某个串口支持IrDA,开启红外模式后,我们只需要向串口写数据,这些数据就会以红外光的方式向外发射出去(当然是需要一些外部硬件支持),然后接收方接收这些红外数据即可解码得到我们的发送信息。

四、            串口中断

串口中断,有三类

1.         接收中断,当接收到数据,并接收数据达到FIFO的触发数目,产生中断

2.         发送中断,方发送数据,FIFO中的数据小于或等于FIFO的触发数目,产生中断

3.         错误中断,传输发生一些其他错误,产生中断

clip_image004

对于发送,有一个状态寄存器,其中有一位叫做发送缓冲器空标志,发送器发送完成((发送缓冲区空了)就会给这个标志位置位,CPU就是通过不断查询这个标志位为1还是0来知道发送是否已经完成。

对于接收,有一个状态寄存器,其中有一位叫做接收缓冲器满标志,CPU通过不断查询这个标志位判断是否接收到数据。但是这样,效率就很低了,因此,对于接收,要使用中断的模式。

五、            波特率设置

串口,有一个很重要的东西,就是波特率的设置。波特率如果设置的不正确,那么串口通道是不能正常通信的。

波特率设置,有两个重要寄存器,UBRDIVnUDIVSLOTn。其中UBRDIVn为主要波特率设置的寄存器,UDIVSLOTn为辅助的寄存器,目的是为了校准波特率。

计算公式

clip_image006

关于UDIVSLOTn,推荐的值

clip_image008

 

我们写程序的时候,就使用手册上推荐的参数,设置波特率就行了。

六、            串口初始化

1.    将串口管脚设置为串口功能

clip_image010

clip_image012

2.    设置串口功能的关键寄存器

UCONx, ULCONx, UMCONx, UFCONx, UBRDIVx, UIDVSLOTOx

对于UCONx867页),设置串口的数据传输的格式。包括数据位,停止位,奇偶校验位,以及工作模式。

clip_image014

对于ULCONx,设置串口的发送和接收工作模式,以及时钟源选择和一些其他设置。

clip_image016

clip_image018

对于UFCONx,设置关于FIFO的功能。

clip_image020

对于UMCONx,设置关于流控和modem功能。

clip_image022

对于UBRDIVx, UIDVSLOTOx寄存器(878页),设置波特率

clip_image024

clip_image026

3.    读取串口发送接收状态

UTRSTAT寄存器

发送的时候,有两个信号,一个是Transmitter empty ,一个是transmitter buffer empty。两个在没有使用FIFO的时候,效果是一样的,但是如果使用FIFO的话,就要使用transmitter buffer empty

Transmitter empty是包括传输的FIFO和传输的移位寄存器,两个都为空,这一位的值才会为1

transmitter buffer empty只是指FIFO,当FIFO空的时候,该位才为1。所以当使用串口FIFO功能的时候,要检测这一位,判断发送是否完成。

Receive buffer data ready1,表示接收到数据。

clip_image028

4.    发送数据

直接往寄存器UTXH写入值即可。但是前提是发送FIFO,没有满。

5.    读取数据

直接读取寄存器URXH即可。但是前提是接收FIFO中有数据。

七、            移植stdio

         printf函数和scanf函数可以和底层输入、输出函数绑定,然后这两个函数就可以和stdio绑定起来。也就是直接调用printf函数输出,内容就会从标准输出输出出去。

         因此,这个时候标准输出就不是屏幕了,而是串口。标准输入也不是键盘,而是串口。

1.    printf函数原理

printf函数工作时内部实际调用了2个关键函数:

一个是vsprintf函数(主要功能是格式化打印信息,最终得到纯字符串格式的打印信息等待输出)

另一个就是真正的输出函数(操控标准输出的硬件,将信息发送出去)

 

         移植printf函数可以有3个途径获取printf的实现源码:

1)       最原始最原本的来源就是linux内核中的printk。难度较大而且麻烦。

2)       uboot中移植

3)       直接使用别人移植好的

 

使用全局变量定义了两个缓冲区,一个是接收数据用,一个是发送数据用。

clip_image029

 

最终,printf函数调用putc函数,所以要实现putc,实现数据发送。scanf函数调用getc函数,所以要实现getc

移植,修改顶层的makefile,增加一些变量,并将变量导出,让子文件夹的makefile使用这些变量。

然后再进入到子文件夹,运行makefile

clip_image031

clip_image032

2.    printf函数

printf

         调用vsprintf

                   调用vsnprintf

                            调用number

vsprintf函数的作用是按照我们的printf传进去的格式化文本,对变参进行处理,然后将之格式化后缓存在一个实现分配好的缓冲区中。

printf后半段调用putc函数将缓冲区中格式化后的字符串直接输出到标准输出(也就是串口)。