JZ2440 串口分析

来源:互联网 发布:软件技术服务包括什么 编辑:程序博客网 时间:2024/05/17 22:09

裸机系列代码地址:链接:http://pan.baidu.com/s/1pLHOd0v 密码:4x5s

UART:通用异步串行收发器

发送数据时:CPU将数据写入UART,UART按照一定的格式在一根线上串行发出

接收数据时:UART检测另一根线上的信号,将串行收集放在缓冲区中,CPU即可读取UART获得的数据

在两个设备进行串行通讯前两者的UART要约定数据的传输速率(波特率),数据的传输格式(多少个数据位,是否使用校验位
,是奇校验还是偶校验,有多少个停止位)

下图演示了UART使用7个数据位,偶校验,2个停止位的格式传输字符“A”

S3C2440 UART的特性
S3C2440有三路独立的UART通道,每个通道都可以工作于中断模式或MDA模式
S3C2440每个通道有16字节的发送FIFO和接收FIFO,发送数据时(中断模式),CPU先将数据写入发送FIFO中,FIFO中的数据到达FIFO阈值时
产生发送中断,UART会自动将FIFO中的数据复制到“发送移位器”中,发生移位器将数据一位一位的发送到TXD数据线上。接收数据时,“接收移位器”
将RXD中的数据一位一位的接收进来,然后复制到FIFO中,当接收FIFO中的数据达到FIFO阈值时,产生接收中断,CPU可以读取数据

S3C2440 UART结构图


S3C2440 UART的使用
(1)将所涉及的UART通道管脚设为UART功能
比如在UART0通道中,GPH2,GPH3分别用作TXD0,RXD0,要使用UART0通道时,需要设置GPHCON寄存器使得GPH2,GPH3引脚功能为TXD0,RXD0
(2)UBRDIVn寄存器:设置波特率
S3C2440 UART的时钟源有三种选择:PCLK,UEXTCLK,FCLK/n,其中n值通过UCON0,UCON1,UCON2联合设置。选定时钟源之后,设置波特率
UBRDIVn = (int)(UART_CLOCK/(buad_rate*16))-1
(3)ULCONn寄存器:设置传输格式
(4)UCONn寄存器:选择UART时钟源,设置UART中断方式
(5)UFCONn寄存器:设置是否使用FIFO,不使用的话可认为FIFO深度为1;设置FIFO的触发阈值
(6)UMCONn和UMSTATn:用于流量控制
(7)UTRSTATn寄存器:用来表明数据是否已经发送完毕,是否已经接收到数据
(8)UERSTATn寄存器:标示各种错误是否发生。溢出错误,校验错误,帧错误,break信号
(9)UTXHn寄存器:CPU将数据写入这个寄存器,UART即会将数据保存到缓冲区中,并自动发送
(10)URXHn寄存器:当UART接受到数据时,CPU读取这个寄存器,即可获得数据。

所以有两者方式检测读取数据和写数据的时机:

  (1)UTRSTATn标示可读

 (1)UTRSTATn标示可写
 (2)发送FIFO达到阈值,发数据中断产生

 (2)接受FIFO达到阈值,读数据中断产生

下面是一个串口的实例

Makefile文件

objs:= head.o init.o main.o uart.bin: $(objs) arm-linux-ld -Tuart.lds -o uart_elf $^arm-linux-objcopy -O binary -S uart_elf $@arm-linux-objdump -D -m arm uart_elf > uart.dis%.o:%.c arm-linux-gcc -Wall -O2 -c -o $@ $<%.o:%.s arm-linux-gcc -Wall -O2 -c -o $@ $< clean:rm -f uart_elf uart.dis uart.bin *.o 
链接文件uart.lds

SECTIONS {    . = 0x30000000;    .text          :   { *(.text) }    .rodata ALIGN(4) : {*(.rodata)}     .data ALIGN(4) : { *(.data) }    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }}
head.s文件
.text.global _start_start:ldr sp,=4096                     /*设置C函数使用的栈*/bl disable_watch_dogbl init_clock                    /*设置系统时钟,使得uart使用PCLK为50MHZ*/bl memsetup                      /*初始化存储控制器使得SDRAM可用*/bl copy_steppingstone_to_sdram   /*将代码复制到SDRAM中*/ldr pc,=on_sdram                 /*地址相关代码,从这里开始程序在SDRAM中运行*/on_sdram:ldr sp,=0x34000000                /*设置代码在SDRAM中运行时的栈*/bl init_uart0                     /*初始化串口0*/bl main bl halt_loophalt_loop:b halt_loop 
init.c文件

#include "s3c2440.h"void disable_watch_dog(void){WTCON = 0x53000000;}/*注意这里必须用这种方式,用数组循环赋值的方式不可取*/void memsetup(void){volatile unsigned long *p = (volatile unsigned long *)0x48000000;/* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值     * 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到     * SDRAM之前就可以在steppingstone中运行     */    /* 存储控制器13个寄存器的值 */    p[0] = 0x22011110;     //BWSCON    p[1] = 0x00000700;     //BANKCON0    p[2] = 0x00000700;     //BANKCON1    p[3] = 0x00000700;     //BANKCON2    p[4] = 0x00000700;     //BANKCON3      p[5] = 0x00000700;     //BANKCON4    p[6] = 0x00000700;     //BANKCON5    p[7] = 0x00018005;     //BANKCON6    p[8] = 0x00018005;     //BANKCON7        /* REFRESH,     * HCLK=12MHz:  0x008C07A3,     * HCLK=100MHz: 0x008C04F4     */     p[9]  = 0x008C04F4;    p[10] = 0x000000B1;     //BANKSIZE    p[11] = 0x00000030;     //MRSRB6    p[12] = 0x00000030;     //MRSRB7}void copy_steppingstone_to_sdram(void){unsigned int *pdest = (unsigned int *)0x30000000;unsigned int *psrc  = (unsigned int *)0x00000000;while(psrc<(unsigned int *)4096){*pdest = *psrc;pdest++;psrc++;}}void init_clock(void){#define MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))CLKDIVN = 0x03;__asm__(    "mrc    p15, 0, r1, c1, c0, 0\n"        /* 读出控制寄存器 */     "orr    r1, r1, #0xc0000000\n"          /* 设置为“asynchronous bus mode” */    "mcr    p15, 0, r1, c1, c0, 0\n"        /* 写入控制寄存器 */    );MPLLCON = MPLL_200MHZ;}void init_uart0(void){GPHCON = 0xa0;      /*GPH2,GPH3用作TXD0,RXD0*/GPHUP  = 0x0c;      /*GPH2,GPH3内部上拉*/#define UART_PCLK   50000000#define baurd       115200#define UART_BRD    ((UART_PCLK/(baurd*16)) -1 )ULCON0 = 0x03;      /*数据位数为8,一个停止位,无奇偶校验*/UCON0 = 0x05;       /*查询方式,UART时钟源为PCLK*/UFCON0 = 0x00;      /*不使用FIFO*/UMCON0 = 0x00;      /*不使用流控*/UBRDIV0 = UART_BRD; /*波特率为115200*/
main.c文件

#include "s3c2440.h"#define TXD0READY (1<<2)#define RXD0READY (1)void putcc(unsigned char c){while( !(UTRSTAT0 & TXD0READY));UTXH0 = c;}unsigned char getcc(void){while( !(UTRSTAT0 & RXD0READY));return URXH0;}int isdigitt(char c){if ('0'<=c && c<='9')return 1;else return 0;}int isletter(char c){if ( ('a'<=c && c<='z') || (c>='A' && c<='Z') )return 1;elsereturn 0;}int main(){unsigned char c;while(1){c=getcc();if(isdigitt(c) || isletter(c))putcc(c+1);}return 0;}
头文件s3c2440.h

/*GPIO*/#define GPHCON (*(volatile unsigned long *)0x56000070)#define GPFCON (*(volatile unsigned long *)0x56000050)#define GPFDAT (*(volatile unsigned long *)0x56000054)#define GPHUP  (*(volatile unsigned long *)0x56000078)/*watch_dog*/#define WTCON (*(volatile unsigned long *)0x53000000)
/*uart0*/#define UBRDIV0 (*(volatile unsigned long *)0x50000028)#define ULCON0 (*(volatile unsigned long *)0x50000000)#define UCON0 (*(volatile unsigned long *)0x50000004)#define UFCON0 (*(volatile unsigned long *)0x50000008)#define UMCON0 (*(volatile unsigned long *)0x5000000C)#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)#define UERSTAT0 (*(volatile unsigned long *)0x50000014)#define UTXH0 (*(volatile unsigned long *)0x50000020)#define URXH0 (*(volatile unsigned long *)0x50000024)/*clock*/#define MPLLCON (*(volatile unsigned long *)0x4C000004)#define CLKDIVN (*(volatile unsigned long *)0x4C000014)





原创粉丝点击