s3c2440串口

一、简介

        通用异步收发器(Universal Asynchronous Receiver  Transmitter),简称“串口”,它可以工作在中断模式或者DMA模式。用系统时钟它可以产生高达

921.6Kbps的波特率。s3c2440共有3个串口,每个串口都2个64位的FIFO用于接收与发送数据。串口之间采用全双工的模式发送数据,最简单的接线方式就是串口1的tx接串口2的rx,串口1的rx接串口2的tx,两个串口在共地即可。2440的串口用的TTL电平(0~3.3V),而我们的计算机采用的是RS232电平(逻辑0:

3~15v 逻辑1:-3~-15v),两者通信需要电平转换。传输过程如下(8位数据位,1位停止位,无校验位):

                 LSB                                                             MSB


(1)平时处于高电平,空闲状态

(2)数据发送时变成低电平发送一位起始位,之后数据从高到低位依次发送

(3)数据位发送完毕若有需要会发送校验位(本图无校验位),最后发送一位停止位,接着返回步骤一

二、内部工作原理

     每个串口有波特率发生器、传输器、接收器和控制单元组成,波特率发生器的时钟可由PCLK、FCLK/n和外部时钟提供,发送数据时数据首先被放到FIFO中,然后数据被复制到移位器中,移位器一位位的发送到tx引脚,接收数据时数据从rx引脚被移位器接收,然后复制到FIFO中。

page333

三、串口寄存器的使用

(1)

page341

 数据长度:我们选择11,即8位       停止位:我们选0,即每帧1位停止位    校验模式:0xx,无校验        红外模式:0  选择普通模式

(2)串口控制寄存器




接收模式:01 中断请求或轮询模式    传输模式:01 中断请求或轮询模式    发送break信号: 0 不发送,普通模式       回环模式:0 普通模式

接收错误中断:0 不产生     接收超时中断:0 不产生    接收中断类型:我们不使用中断,默认   发送中断类型:不使用,默认

时钟源选择:00或者10 PCLK    FCLK 分频:未使用0000

如果使用一些特殊的波特率,可以尝试使用FCLK或者外部时钟

(3)UART FIFO control registers与UART FIFO status registers,这里没有使用FIFO

(4)UART MODEM control registers与UART modem status registers,这里也没有使用

(5)串口接收发送状态寄存器

page347
接收buffer状态:0 空,即没有数据    1接收到了数据

传输buffer状态: 0 数据正在传输       1空,数据传输完毕

传输空:             0   传输数据buffer或移位数据buffer不为空                           1传输数据buffer和移位数据buffer都为空

(6)UART  error status registers

page348

0~4位表示溢出错误、校验错误、帧错误、break信号检测,读取后相应的位自动清零

如果接收数据使用了FIFO,则会有一个“错误FIFO”表明接收到的错误,cpu只有在读出这个错误数据时才会发现错误。要想清除“错误FIFO”,则必须读出错误数据,,并读出UART  error status registers相应的位。

(7)


将数据写到寄存器,启动数据传输。注意数据的大小端分别对应不同地址

(8)


当接收到数据时,读这个寄存器会得到数据,也要注意数据的大小端分别对应不同地址

(9)


波特率计算:UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1

当使用外部时钟时UBRDIVn被设置为0.

例如:UBRDIVn=(int)(50000000/(115200x16))-1=26


四、实验代码

目的:输入一个字符把这个字符的值加一输出,采用轮询方式

head.S


.text
.global _start
_start:
    mov sp, #4096
    bl disable_watch_dog
    bl clock_init
    bl set_up_mem_ctl
    bl copy_steppingstone_to_sdram
    ldr sp, =0x34000000
    ldr pc, =on_sdram
on_sdram:
    bl init_uart0
    bl main
halt_loop:
    b halt_loop
   

init.c

#include "s3c2440.h"


void disable_watch_dog(void)
{
    WTCON = 0X00;
}

void clock_init(void)
{
    CLKDIVN = 0x03;                //应先设置分频值,在设定MPLLCON
    __asm__(
            "mrc p15,0,r1,c1,c0,0\n"
            "orr r1, r1, #0xc0000000\n"
            "mcr p15,0,r1,c1,c0,0\n");
    MPLLCON = (0x2a << 12) | (0x01 << 4) | 0x01;     //MPLL为200MHz
}

void set_up_mem_ctl(void)
{
    volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;

    /* 这个函数之所以这样赋值,而不是像前面的实验(比如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)
{
    volatile unsigned int *source_addr = (volatile unsigned int *)0x00;
    volatile unsigned *dest_addr = (volatile unsigned int *)0x30000000;
    unsigned int length = 4096;
    while(length--)
        *dest_addr++ = *source_addr++;
}

void init_uart0(void)
{
    GPHCON  |= 0xa0;    // GPH2,GPH3用作TXD0,RXD0
    GPHUP   = 0x0c;     // GPH2,GPH3内部上拉
    ULCON0 = 0x03;                //8位数据位,1位停止位,无校验位,普通模式(非红外模式)
    UCON0  = 0X05;
    UBRDIV0 = 26;                //波特率115200bps
}

main.c

#include "s3c2440.h"
#include "uart.h"

int main(void)
{
    char c;
    while(1){
        c = uart0_get_char();
        uart0_put_char(c + 1);
    }
    return 0;
}

Makefile


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.bin uart_elf uart.dis *.o   

s3c2440.h

/* WOTCH DOG register */
#define     WTCON           (*(volatile unsigned long *)0x53000000)

/* SDRAM regisers */
#define     MEM_CTL_BASE    0x48000000
#define     SDRAM_BASE      0x30000000

/* NAND Flash registers */
#define NFCONF              (*(volatile unsigned int  *)0x4e000000)
#define NFCMD               (*(volatile unsigned char *)0x4e000004)
#define NFADDR              (*(volatile unsigned char *)0x4e000008)
#define NFDATA              (*(volatile unsigned char *)0x4e00000c)
#define NFSTAT              (*(volatile unsigned char *)0x4e000010)

/*GPIO registers*/
#define GPBCON              (*(volatile unsigned long *)0x56000010)
#define GPBDAT              (*(volatile unsigned long *)0x56000014)

#define GPFCON              (*(volatile unsigned long *)0x56000050)
#define GPFDAT              (*(volatile unsigned long *)0x56000054)
#define GPFUP               (*(volatile unsigned long *)0x56000058)

#define GPGCON              (*(volatile unsigned long *)0x56000060)
#define GPGDAT              (*(volatile unsigned long *)0x56000064)
#define GPGUP               (*(volatile unsigned long *)0x56000068)

#define GPHCON              (*(volatile unsigned long *)0x56000070)
#define GPHDAT              (*(volatile unsigned long *)0x56000074)
#define GPHUP               (*(volatile unsigned long *)0x56000078)



/*UART registers*/
#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 UTXH0               (*(volatile unsigned char *)0x50000020)
#define URXH0               (*(volatile unsigned char *)0x50000024)
#define UBRDIV0             (*(volatile unsigned long *)0x50000028)


/*interrupt registes*/
#define SRCPND              (*(volatile unsigned long *)0x4A000000)
#define INTMOD              (*(volatile unsigned long *)0x4A000004)
#define INTMSK              (*(volatile unsigned long *)0x4A000008)
#define PRIORITY            (*(volatile unsigned long *)0x4A00000c)
#define INTPND              (*(volatile unsigned long *)0x4A000010)
#define INTOFFSET           (*(volatile unsigned long *)0x4A000014)
#define SUBSRCPND           (*(volatile unsigned long *)0x4A000018)
#define INTSUBMSK           (*(volatile unsigned long *)0x4A00001c)

/*external interrupt registers*/
#define EINTMASK            (*(volatile unsigned long *)0x560000a4)
#define EINTPEND            (*(volatile unsigned long *)0x560000a8)

/*clock registers*/
#define    LOCKTIME        (*(volatile unsigned long *)0x4c000000)
#define    MPLLCON        (*(volatile unsigned long *)0x4c000004)
#define    UPLLCON        (*(volatile unsigned long *)0x4c000008)
#define    CLKCON        (*(volatile unsigned long *)0x4c00000c)
#define    CLKSLOW        (*(volatile unsigned long *)0x4c000010)
#define    CLKDIVN        (*(volatile unsigned long *)0x4c000014)


/*PWM & Timer registers*/
#define    TCFG0        (*(volatile unsigned long *)0x51000000)
#define    TCFG1        (*(volatile unsigned long *)0x51000004)
#define    TCON        (*(volatile unsigned long *)0x51000008)
#define    TCNTB0        (*(volatile unsigned long *)0x5100000c)
#define    TCMPB0        (*(volatile unsigned long *)0x51000010)
#define    TCNTO0        (*(volatile unsigned long *)0x51000014)


uart.c

#include "s3c2440.h"
char uart0_get_char(void)
{
    char ret_char;
    while(!(UTRSTAT0 & 0x01));
        ret_char = URXH0;
    return ret_char;
}

void uart0_put_char(char c)
{
    while(!((UTRSTAT0>>2) & 0x01 ));
        UTXH0 = c;
}


uart.h

char uart0_get_char(void);
void uart0_put_char(char c);


uart.lds

SECTIONS {
    . = 0x30000000;
    .text          :   { *(.text) }
    .rodata ALIGN(4) : {*(.rodata)}
    .data ALIGN(4) : { *(.data) }
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值