第二课,2440串口的学习

注:以下内容学习于韦东山老师arm裸机第一期视频教程


一.uart(Universal ASynchronous Receiver and Transmitter)简介

    1.1 串口的作用

        1.1.1 打印调试信息

        1.1.2 外接各种模块,例如GPS,蓝牙等

    

    1.2 串口使用

        1.2.1 设置波特率

        1.2.2 数据格式(数据位,停止位,校验位,流控)

        

    1.3 串口协议

        假设ARM要发送一个字节给电脑,例如一个字符'A' = 0x41,对应2进制 0100 0001

        

        1.3.1 双方先约定好每一位占据的时间(波特率),假设为1s

        1.3.2 首先arm将TXD引脚拉低,维持1bit(1s)时间

        1.3.3 PC机载低电平开始处计时

        1.3.4 arm根据数据驱动引脚TXD电平,每一位维持1bit(1s)时间,发送8位,称为数据位

                PC机在数据位的中间读取引脚状态

        1.3.5 第7位发送完成之后,发送校验位(奇偶校验位,数据位+校验位中为1的个数是奇数或者偶数)

                                    校验位现在基本用不到了,电子技术很稳定

        1.3.6 最后发出停止位,高电平(可以约定停止位占据的时间)

        

    1.4 逻辑电平

        这些电平对应为逻辑电平,即1,0分别对应多少V,有很多种逻辑电平。

        

        例如TTL/CMOS逻辑电平,12V-3V表示0,-3V-12V表示1,不适合长距离传输

            引入RS232电平适合长距离传输。

        开发板上的电平是TTL电平,电脑上是RS232电平,如果要想连接需要引入电平转换芯片,将TTL电平转换为RS232电平(mini2440)

        对于JZ2440没有使用电平转换芯片,因为很多电脑没有使用串口,串口0直接接usb串口芯片连接电脑.

                                                                串口1,串口2仍然保持TTL电平

        

二.2440串口结构

    2.1 2440串口结构图如下:

    
    

    2.2 串口发送

        对于2440,我们需要将数据从内存中取出通过串口控制器发送出去,在串口线上我们是逐位发送的。


        2.2.1 因此肯定会有一个移位器对应图的Transmit Shifter

        2.2.2 移位的数据来自于fifo,图中的Transmit Buffer Register,

        2.2.3 而fifo中的数据来自于内存。

    

    2.3 串口接受

        在串口线上接受数据也是逐位接受的

        2.3.1 移位器逐位接受数据

        2.3.2 放入fifo

        2.3.3 程序从fifo中取出数据

    

    2.4 问题-> 如何知道数据/接受发送完毕?

        2.4.1 中断CPU

        2.4.2 查询状态

        

三.Uart编程(具体参考程序代码注释)

    3.1 串口初始化

        3.1.1 配置引脚

              a.配置GPHCON寄存器,配置串口0的TXD,RXD引脚
              b.配置GPHUP寄存器,TXD,RXD上拉,因为起始位是通过拉低电平来表示的
        

        3.1.2 设置波特率

                在2440芯片手册上有如下公式:

          

           我们需要设置UBRDIVn来控制串口的时钟分频得到波特率

                            

        3.1.3 设置数据格式(8n1)

        

    3.2 输出函数

    3.3 接受字符函数

    代码如下:

            
        #include "uart.h"

        /* 115200,8n1 */
        void Uart0Init()
        {
            /* 1.配置引脚 */
            /* 1.1 配置GPH2,GPH3用作TXD,RXD */
            GPHCON &= ~((0X3 << 2*2) | (0X3 << 2*3));

            /* 1.2 配置GPH2,GPH3内部上拉 */
            GPHUP &= ~((0x1 <<2) | (0x1 << 3));

            /* 2.设置波特率115200 */

            /*
             * 2.1 设置UART clock
             *        UCON0 bit[11:10] = 0, UART clock = PCLK = 50M
             *       UCON0 bit[1:0] = 1, 中断/轮询模式接受
             *       UCON0 bit[3:2] = 1, 中断/轮询模式发送
             */
            UCON0 = 0x5;

            /* 2.2 设置分频系数UBRDIVn
             *   UBRDIVn = (int)(UART clock / (baud * 16)) - 1
             *            = (int)(PCLK / (115200 * 16)) - 1
             *             = (int)(50000000 / (115200 * 16)) - 1 = 26;
             */
            UBRDIV0 = 26;

            /* 3.设置数据格式 */
            ULCON0 = 0x3;     /* 8n1 */

        }


        void putchar(char c)
        {
            while (!(UTRSTAT0 & (1 << 1)));
            UTXH0 = c;
        }

        int getchar()
        {
            while (!(UTRSTAT0 & (1 << 0)));
            return URXH0;
        }

        void puts(const char *s)
        {
            while (*s)
            {
                putchar(*s);
                s++;
            }
        }
       

    测试代码如下:

        
        #include "uart.h"

        int main()
        {
            char c;
            
            Uart0Init();
            puts("Hello, World!\n");

            while (1)
            {
                c = getchar();    
                if(c == '\n')
                    putchar('\r');
                if(c == '\r')
                    putchar('\n');
                putchar(c);  /* 回显输入语句 */
            }
            
            return 0;
        }







猜你喜欢

转载自blog.csdn.net/qq_36521904/article/details/80595119