通过使用UART0实现接收的数据

来源:互联网 发布:北大青鸟java课程表 编辑:程序博客网 时间:2024/06/07 10:48
 

实验目的:通过使用UART0实现接收的数据(字母/数字)原样输出的操作,借此掌握S3C2410的UART使用。

实验环境及说明:恒颐S3C2410开发板H2410。H24X0E扩展板上串行通讯接口3个,可以完成与PC 机的通讯调试。系统串口0和1为RS232 电平;系统串口2为TTL 电平。默认情况下系统使用串口0与PC机通讯,波特率为:115200、8 位数据位、1位停止位、无奇偶校验、无硬件流控。

实验思路:开发板上电启动后,自动将NandFlash开始的4K数据复制到SRAM中,然后跳转到0地址开始执行。然后来设置MPLL来改变FCLK、HCLK、PCLK的值,初始化存储控制器来使用SDRAM。之后进入main函数中完成UART0的初始化和数据的收发操作。

知识掌握:通用异步收发器(Universal Asynchronous Receiver Transmitter,UART):它用来实现串行数据的传输,相当于我们通常所说的串口。
★UART工作原理说明
●数据传输概况---数据发送时,CPU将并行数据写入UART,UART按照一定的格式在一根线(TxD)上串行发出;数据接收时,UART检测另一根线(RxD)上的信号,将串行数据放在缓冲区中供CPU读取UART获得这些数据。UART之间以全双工方式传输数据,最精简的连线方式只使用3根线(TxD用于发送数据,RxD用于接收数据,GND用于提供双方参考电平)。
●数据传输流程---通常数据线处于空闲(1)状态;当要发送数据时,UART改变TxD数据线的状态(1--->0),并维持1位的时间,接收方在检测到这一开始位的时候,再等待1.5位时间就开始一位一位地检测数据线的状态以得到数据;UART一帧中可以有5/6/7/8位的数据,发送方一位一位地改变数据线的状态发送数据(首先发送最低位);如果使用校验功能,UART在发送完数据位后,还要发送1个校验位(分奇校验和偶校验两种校验方法:数据线连同校验位中"1"的个数等于奇/偶数);最后发送停止位(长度有1位/1.5位/2位3种),数据线恢复到空闲(1)状态。

★S3C2410 UART的特性:3个独立通道,每个通道可以工作于中断模式或DMA模式,UART由波特率发生器、发送器、接收器、控制逻辑组成。时钟源有两种选择PCLK和UEXTCLK,使用系统时钟时波特率可达230.4Kbit/s,其波特率可通过编程来控制。


★S3C2410 UART的使用:在使用UART前,需要设置波特率,传输格式,设置管脚为UART功能(比如UART通道0中,GPH2、GPH3分别用作TXD0、RXD0,要使用UART通道0时,先设置GPHCON寄存器将GPH2、GPH3引脚功能设置为TXD0、RXD0),选择UART通道的工作模式为中断模式或者DMA模式。设置好之后,往某个寄存器中写入数据即可发送,读取某寄存器即可得到接收的数据,可以通过查询状态寄存器或者设置中断来获知数据是否已经发送完毕,是否已经接收到数据。UART相关的寄存器(寄存器比较多,详情参看Datasheet):
●UBRDIVn寄存器(n=0~2)---用于设置波特率。UBRDIVn =(int)(PCLK/(bps x 16))-1或UBRDIVn =(int)(UCLK/(bps x 16))-1。
●ULCONn寄存器---设置传输格式。注意下设为红外模式与正常模式稍有不同。
●UCONn寄存器---用于选择UART的时钟源,设置UART中断方式等。
●UFCONn和UFSTATn寄存器---用于设置是否使用FIFO,设置各FIFO的触发阈值,可以通过调协UFCONn寄存器来复位各个FIFO。读取UFSTATn寄存器可以知道各个FIFO是否已满,其中有多少数据。如果不使用FIFO时,可以认为FIFO的深度为1;如果使用FIFO时,S3C2410的FIFO深度为16。
●UMCONn和UMSTATn寄存器---用于流量控制。
●UTRSTATn寄存器---用来表明数据是否已经发送完毕,是否已经接收到数据。
●USERSTATn寄存器---用于表示各种错误的发生。
●UTXHn寄存器---CPU将数据写入到这个寄存器,UART即会将它保存到缓冲区中,并自动发送出去。
●URXHn寄存器---当UART接收到数据时,CPU读取这个寄存器,即可获得数据。


关键代码解析:
★head.S头文件来初始化,设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
.equ        MEM_CTL_BASE,       0x48000000
.equ        SDRAM_BASE,         0x30000000
.text
.global _start
_start:
Reset:                  
    ldr sp, =4096                                           @设置栈指针
    bl  disable_watch_dog                      @关闭WATCHDOG,否则CPU会不断重启
    bl  init_clock                                         @设置MPLL,改变FCLK、HCLK、PCLK
    bl  mem_control_setup                         @设置存储控制器以使用SDRAM
    bl  copy_steppingstone_to_sdram     @复制代码到SDRAM中
    ldr pc, =on_sdram                              @跳到SDRAM中继续执行
on_sdram:
    ldr sp, =0x34000000                             @重设置栈指针
    ldr lr, =halt_loop                                 @设置返回地址
    ldr pc, =main                                      @调用main函数
halt_loop:
    b   halt_loop

★serial.c文件实现UART0的初始化及数据收发操作,主要代码:
//初始化UART0:115200、8N1、无流控
void init_uart0(void)
{
    GPHCON  |= 0xa0;    //GPH2、GPH3用作TXD0、RXD0
    GPHUP   = 0x0c;     //GPH2、GPH3内部上拉
    ULCON0  = 0x03;     //8N1(8个数据位、无较验、1个停止位)
    UCON0   = 0x05;     //查询方式,UART时钟源为PCLK
    UFCON0  = 0x00;     //不使用FIFO
    UMCON0  = 0x00;     //不使用流控
    UBRDIV0 = UART_BRD; //波特率为115200
}
//发送一个字符
void putc(unsigned char c)
{
    //等待,直到发送缓冲区中的数据已经全部发送出去
    while (!(UTRSTAT0 & TXD0READY));    
    //向UTXH0寄存器中写入数据,UART即自动将它发送出去
    UTXH0 = c;
}
//接收字符
unsigned char getc(void)
{
    //等待,直到接收缓冲区中的有数据
    while (!(UTRSTAT0 & RXD0READY));    
    //直接读取URXH0寄存器,即可获得接收到的数据
    return URXH0;
}
//判断一个字符是否数字
int isDigit(unsigned char c)
{
    if (c >= '0' && c <= '9')
        return 1;
    else
        return 0;      
}
//判断一个字符是否英文字母
int isLetter(unsigned char c)
{
    if (c >= 'a' && c <= 'z')
        return 1;
    else if (c >= 'A' && c <= 'Z')
        return 1;      
    else
        return 0;
}

原创粉丝点击