实验(11)、UART操作

一、编写使用按键中断程序

1、程序功能:在串口上输入一个字符,单板接收到后将它的ASCII值加1后,从串口输出。

2、写程序如下:head.S、init.c、serial.c、main.c、s3c24xx.h、serial.h、makefile、uart.lds

(1)head.S程序如下:

@******************************************************************************

@ File:head.S

@功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行

@******************************************************************************

.extern main

.text

.global _start

_start:

Reset:

ldr sp, =4096 @设置栈指针,以下都是C函数,调用前需要设好栈

bl disable_watch_dog @关闭WATCHDOG,否则CPU会不断重启

bl clock_init @设置MPLL,改变FCLK、HCLK、PCLK

bl memsetup @设置存储控制器以使用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

(2)init.c程序如下:

/*

* init.c:进行一些初始化

*/

#include "s3c24xx.h"

void disable_watch_dog(void);

void clock_init(void);

void memsetup(void);

void copy_steppingstone_to_sdram(void);

/*

*关闭WATCHDOG,否则CPU会不断重启

*/

void disable_watch_dog(void)

{

WTCON = 0; //关闭WATCHDOG很简单,往这个寄存器写0即可

}

#define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))

#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))

/*

*对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV

*有如下计算公式:

* S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s)

* S3C2410: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)

*其中: m = MDIV + 8, p = PDIV + 2, s = SDIV

*对于本开发板,Fin = 12MHz

*设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,

* FCLK=200MHz,HCLK=100MHz,PCLK=50MHz

*/

void clock_init(void)

{

// LOCKTIME = 0x00ffffff; //使用默认值即可

CLKDIVN = 0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1

/*如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode”*/

__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" /*写入控制寄存器*/

);

/*判断是S3C2410还是S3C2440 */

if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

{

MPLLCON = S3C2410_MPLL_200MHZ; /*现在,FCLK=200M,HCLK=100M,PCLK=50M*/

}

else

{

MPLLCON = S3C2440_MPLL_200MHZ; /*现在,FCLK=200M,HCLK=100M,PCLK=50M*/

}

}

/*

*设置存储控制器以使用SDRAM

*/

void memsetup(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)

{

unsigned int *pdwSrc = (unsigned int *)0;

unsigned int *pdwDest = (unsigned int *)0x30000000;

while (pdwSrc < (unsigned int *)4096)

{

*pdwDest = *pdwSrc;

pdwDest++;

pdwSrc++;

}

}

(3)serial.c程序如下:

#include "s3c24xx.h"

#include "serial.h"

#define TXD0READY (1<<2)

#define RXD0READY (1)

#define PCLK 50000000 // init.c中的clock_init函数设置PCLK为50MHz

#define UART_CLK PCLK // UART0的时钟源设为PCLK

#define UART_BAUD_RATE 115200 //波特率

#define UART_BRD ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)

/*

*初始化UART0,115200,8N1,无流控

*/

void uart0_init(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;

}

(4)main.c程序如下:

#include "serial.h"

int main()

{

unsigned char c;

uart0_init(); //波特率115200,8N1(8个数据位,无校验位,1个停止位)

while(1){

//从串口接收数据后,判断其是否数字或子母,若是则加1后输出

c = getc();

if (isDigit(c) || isLetter(c))

putc(c+1);

}

return 0;

}

(5)s3c24xx.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)

#define GSTATUS1 (*(volatile unsigned long *)0x560000B0)

(6)serial.h程序如下:

void uart0_init(void);

void putc(unsigned char c);

unsigned char getc(void);

int isDigit(unsigned char c);

int isLetter(unsigned char c);

(7)Makefile程序如下:

objs := head.o init.o serial.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 -nostdlib -Wall -O2 -c -o $@ $<

%.o:%.S

arm-linux-gcc -nostdlib -Wall -O2 -c -o $@ $<

clean:

rm -f uart.bin uart_elf uart.dis *.o

8

results matching ""

    No results matching ""

    results matching ""

      No results matching ""