第八天: 串口通信代码实战及uart stdio 移植

来源:互联网 发布:境外网络电视直播apk 编辑:程序博客网 时间:2024/06/06 09:54

    1.S5PV210串行通信接口详解2

    1. 本来串口的功能就是上节讲过的部分,但是后来的技术发展给串口叠加了一些高级功能,在像210这类的高级SoC的串口控制器中,都有这类高级功能。
    2. FIFO模式及其作用

    (1)典型的串口设计,发送/接收缓冲区只有1字节,每次发送/接收只能处理1帧数据。这样在单片机中没什么问题,但是到复杂SoC中(一般有操作系统的)就会有问题,会导致效率低下,因为CPU需要不断切换上下文。

    (2)解决方案就是想办法扩展串口控制器的发送/接收缓冲区,譬如将发送/接收缓冲器设置为64字节,CPU一次过来直接给发送缓冲区64字节的待发送数据,然后transmitter慢慢发,发完再找CPU再要64字节。但是串口控制器本来的发送/接收缓冲区是固定的1字节长度的,所以做了个变相的扩展,就是FIFO。

    (3)FIFO就是first in first out,先进先出。fifo其实是一种数据结构,这里这个大的缓冲区叫FIFO是因为这个缓冲区的工作方式类似于FIFO这种数据结构。

     

    1. DMA模式及其作用

    (1)DMA direct memory access,直接内存访问。DMA本来是DSP中的一种技术,DMA技术的核心就是在交换数据时不需要CPU参与,模块可以自己完成。

    (2)DMA模式要解决的问题和上面FIFO模式是同一个问题,就是串口发送/接收要频繁的折腾CPU造成CPU反复切换上下文导致系统效率低下。

    (3)传统的串口工作方式(无FIFO无DMA)效率是最低的,适合低端单片机;高端单片机上CPU事物繁忙所以都需要串口能够自己完成大量数据发送/接收。这时候就需要FIFO或者DMA模式。FIFO模式是一种轻量级的解决方案,DMA模式适合大量数据迸发式的发送/接收时。

     

    1. IrDA模式及其用法

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

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

    (3)分析可知,红外通信和串口通信非常像,都是每隔固定时间发送1或者0(判断1或0的物理方式不同)给接收方来通信。因此210就利用串口通信来实现了红外发送和接收。

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

     

     

     

    1. S5PC210串口通信接口详解3
      1. 串行通信与中断的关系
        1. 串口通信分为发送/接受2部分。发送方一般不需要(也可以使用)中断即可完成发送,接受方必须(一般来说必须,也可以轮询方式接收)使用中断接收
        2. 发送方可以选择使用中断,也可以选择不使用中断。使用中断的工作情景是:发送方先设置好中断并绑定一个中断处理程序,然后发送方丟一帧数据给transmittertransmitter发送耗费一段时间来发送这一帧数据,这段时间内发送方CPU可以去做别的事情,等transmitter发送完成会产生一个TXD中断,该中断会导致事先绑定的中断处理程序执行,在终端处理程序中CPU会切换回来继续给transmitter放一帧数据,然后CPU切换离开;不适用中断的工作情景是:发送方事先禁止TXD中断(当然也不需要给相应的中断处理程序了),发送方CPU给一帧数据到transmitter,然后transmitter耗费一段时间来发送这帧数据,这段时间CPU在这等着(CPU没有切换去做别的事情),待发送方发送完成后CPU再给它一帧数据继续发送直到所有数据发完。CPU是怎么知道transmitter已经发送完了?原来是有个状态寄存器,状态寄存器中有一个位叫发送缓冲区空标志,transmitter发送完成(发送缓冲区空了)就会给这个标志位置位,CPU就是通过不断查询这个标志位为1还是0来指导发送是否已经完成的。
        3. 因为串口通信是异步的,异步的意思就是说发送方占主导权。也就是说发送方随时想发就能发,但是接收方只有时刻等待才不会丢失数据。所以这个差异就导致发送方可以不用中断,而接收方不得不使用中断模式。
      2. 210串口通信的时钟设计
        1. 串口通信为什么需要时钟
          1. 因为串口通信需要一个固定的波特率,所以transmitterreceiver都需要一个时钟信号
          2. 时钟信号从哪里来? 源时钟信号时外部APB总线提供给串口提供给串口模块的(这就是为什么我们说串口是挂在APB总线上),然后进到串口控制器内部后给波特率发生器实质是一个分频器,在波特率发生器中进行分频,分频得到一个低频时钟,这个时钟就是给transmitterreceiver使用的
          3. 串口通信中时钟的设置主要是寄存器的操作,重点的有: 寄存器源设置(为串口控制器选择源时钟,一般选择为PCLK_PSYS,也可以是SCLK_UART),还有波特率发生器的2个寄存器。
          4. 波特率发生器有2个重要寄存器:UBRDIVnUBRDIVn,其中UBRDIVn是主要的设置波特率的寄存器,UDIVSLOTn是用来辅助设置的,目的是为了校准波特率的。
    2. S5PV210串行通信编程实战1
      1. 整个程序流程分析
        1. 整个串口通信相关包含两部分:uart_init负责初始化串口,uart_putc负责发送一个字节
      1. 串口控制器初始化关键步骤
        1. 初始化串口的TxRx引脚所对应的GPIOGPA0_1GPA0_0
        2. GPA0CON(0xE0200000),bit[3:0]=0b0010   bit[7:4] = 0b0010
        3. 初始化这几个关键寄存器UCON0   ULCON0 UMCON0 UBRDIVn UDIVSLOTn
        1. 主要的几个寄存器

    (1)ULCON0 = 0x3                // 0校验位、8数据位、1停止位

    (2)UCON = 0x5                // 发送和接收都是polling mode

    (3)UMCON0 = 0x0                // 禁止modem、afc

    (4)UFCON0 = 0x0                // 禁止FIFO模式

    (5)UBRDIV0和UDIVSLOT0和波特率有关,要根据公式去算的

     

    1. C源文件中定义访问寄存器的宏

    定义好了访问寄存器的宏之后,将来写代码时直接使用即可。

     

    1. S5PV210串行通信编程实战2

    串口Tx、Rx对应的GPIO的初始化

    给GPA0CON的相应bit位赋值为相应值,用C语言位操作来完成。

    1. UCON、ULCON、UMCON、UFCON等主要控制寄存器

    依据上节中分析的值进行依次设置即可。

    1. 波特率的计算和设置

    (1)第一步,用PCLK_PSYS和目标波特率去计算DIV_VAL: DIV_VAL = (PCLK / (bps x 16)) ?1

    (2)第二步,UBRDIV0寄存器中写入DIV_VAL的整数部分

    (3)第三步,用小数部分*16得到1个个数,查表得uBDIVSLOT0寄存器的设置值

    1. 串口发送和接收函数的编写

    (1)写发送函数,主要发送前要用while循环等待发送缓冲区为空才能发送。

    1. 综合调试

    注意Makefile的修改。

    1. 扩展练习-更改波特率后再调试

    自己练习。注意程序中改了波特率后,SecureCRT也要相应修改,不然收不到东西。

     

     

    1. uart stdio 的移植1
      1. 什么是stdio?
        1. #include<stdio.h>
        2. standard input output ,标准输入输出
        3. 标准输入输出就是操作系统定义的默认的输入和输出通道。一般在PC的情况下,标准输入指的是键盘,标准输出指的是屏幕。
        4. printfscanf函数可以和底层输入/输出函数绑定,然后这两个函数就可以和stdio绑定起来。也就是说我们直接调用printf函数输出,内容就会被标准输出输出出去。
        5. 在我们这里,标准输出当然不是屏幕了,而是串口。标准输出也不是键盘,而是串口。
      2. printf函数的工作原理
        1. printf函数工作时内部实际调用了2个函数:一个是vsprintf(主要功能是格式化打印信息,最终得到纯数字格式的打印信息等待输出),另一个就是真正的输出函数putc(操控标准输出的硬件,将信息发送出去)
      3. 移植printf函数的三种思路
        1. 我们希望在我们的开发板上使用printf函数进行(串口)输出。使用scanf函数进行(串口)输入,就像在PC机上键盘和屏幕进行输入输出一样。因此需要移植printf函数/scanf函数
        2. 我们说的移植不是编写,我们不希望自己完全从新编写而是想尽量借用也有的代码(叫移植)
        3. 一般移植printf函数可以有三个途径获取printf的实现源码:
          1. 最原始最原本的来源就是linux内核中的printk。难度较大、关键是麻烦;
          2. 简单一点的是从uboot中移植printf
          1. 跟简单的就是直接使用别人移植好的。
          2. 我们使用第三种方法,别人一直好的printf函数来自于友善之臂的Tiny210的裸机教程。
      4. 移植好的printf介绍
      5. uart stdio 移植 
        1. 修改Makefile进行printf移植
        2. makefilegcc的库文件介绍
        3. 多文件裸机工程及结构解析
        4. 编译运行及测试
    1. uart stdio

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

0 0
原创粉丝点击