串口时钟使用了PCLK,所以在初始化串口之前需要先将系统时钟初始化,(除非想一直使用默认时钟)。
一、代码
1. start.S 主要功能是:
a.关闭看门狗
b. 初始化系统时钟
c. 设置堆栈
d. 跳到main函数
-
.text
-
.global _start
-
_start:
-
/*disable watchdog*/
-
ldr r0, =0x53000000
-
mov r1, #0x0
-
str r1, [r0]
-
-
#define COCKTIME 0x4C000000
-
#define MPLLCON 0x4C000004
-
#define UPLLCON 0x4C000008
-
#define CLKCON 0x4C00000C
-
#define CLKSLOW 0x4C000010
-
#define CLKDIVN 0x4C000014
-
#define CAMDIVN 0x4C000018
-
/*FCLK:HCLK:PCLK=1:4:8*/
-
ldr r0, =CLKDIVN
-
mov r1, #0x05
-
str r1, [r0]
-
-
mrc p15, 0, r0, c1, c0, 0
-
orr r0, r0, #0xc0000000
-
mcr p15, 0, r0, c1, c0,0
-
-
/*MPLL=(2*m*Fin)/(P*(1<<S)), m=(MDIV+8), p=PDIV+2 s=SDIV*/
-
ldr r0, =MPLLCON
-
ldr r1, =((0x5C<<12)|(0x01<<4)|(0x01))
-
str r1, [r0]
-
-
ldr r0, =0x10000
-
1:
-
sub r0, r0, #1
-
bne 1b
-
-
/*UPLL=(m*Fin)/(P*(1<<S)), m=(MDIV+8), p=(PDIV+2), s=SDIV*/
-
ldr r0, =UPLLCON
-
ldr r1, =((0x10<<12)|(0x01<<4)|(0x01))
-
str r1, [r0]
-
-
ldr r0, =0x10000
-
1:
-
sub r0, r0, #1
-
bne 1b
-
-
/* set up the stack */
-
ldr sp, =1024*4
-
bl main
-
-
loop:
-
b loop
2. main.c 主要功能是:
a. 初始化串口
b. 进入死循环,每次点亮一个led灯,顺便打印一个字母'a'
-
#include "uart.h"
-
#define GPBCON (*(volatile unsigned int *) 0x56000010)
-
#define GPBDAT (*(volatile unsigned int *) 0x56000014)
-
-
static inline void delay (unsigned long loops)
-
{
-
__asm__ volatile ("1:\n"
-
"subs %0, %1, #1\n"
-
"bne 1b":"=r" (loops):"0" (loops));
-
}
-
-
void main()
-
{
-
int i = 1;
-
GPBCON = 0x15400;
-
init_uart();
-
while(1)
-
{
-
GPBDAT = 0x7FF&(~i<<5);
-
i *= 2;
-
if(16==i)
-
i = 1;
-
delay(400000);
-
putc('a');
-
}
-
return ;
-
}
3.uart.c 主要功能:
a. 初始化串口
b. 实现发送与接收函数getc与putc
-
#define GPHCON (* (volatile unsigned int *) 0x56000070)
-
#define GPHUP (* (volatile unsigned int *) 0x56000078)
-
-
#define ULCON0 (* (volatile unsigned int *) 0x50000000)
-
#define UCON0 (* (volatile unsigned int *) 0x50000004)
-
#define UFCON0 (* (volatile unsigned int *) 0x50000008)
-
#define UMCON0 (* (volatile unsigned int *) 0x5000000C)
-
#define UTRSTAT0 (* (volatile unsigned int *) 0x50000010)
-
#define UERSTAT0 (* (volatile unsigned int *) 0x50000014)
-
#define UFSTAT0 (* (volatile unsigned int *) 0x50000018)
-
#define UMSTAT0 (* (volatile unsigned int *) 0x5000001C)
-
#define UTXH0 (* (volatile unsigned char *) 0x50000020)
-
#define URXH0 (* (volatile unsigned char *) 0x50000024)
-
#define UBRDIV0 (* (volatile unsigned int *) 0x50000028)
-
-
#define BAUD_RATE 115200
-
-
void uart_init(void)
-
{
-
GPHCON = 0x000000A0;
-
GPHUP = 0x000007FF;
-
ULCON0 = (0x03); //8N1
-
UCON0 = (0x01<<2)|(0x01);
-
UFCON0 = 0;
-
UMCON0 = 0;
-
UBRDIV0 = (int)((50*1000*1000)/(BAUD_RATE*16))-1;
-
}
-
-
unsigned char uart_getc(void)
-
{
-
while(!(UTRSTAT0 & 0x01))
-
;
-
return (URXH0 & 0xff);
-
}
-
-
void uart_putc(char c)
-
{
-
while (!(UTRSTAT0&0x02))
-
;
-
UTXH0 = c;
-
if('\n' == c)
-
uart_putc('\r');
-
}
-
-
void uart_puts(char *s)
-
{
-
while (*s)
-
{
-
uart_putc(*s++);
-
}
-
}
注: uart.c中的uart_putc函数(ascii中: \n__换行__LF__0x10 \r__回车__CR__0x13 )
1. 当键盘敲下 Enter键时,从串口收到的按键是0x0d(即:\r 回车符:将光标移动到行首,而不换行)。
2. 当调用puts("hello\n");时putc收到\n后,将换行但光标的列不变,然后再输出\r,将光标移动到换行之后的行首,这样效果就跟平常的回车一样了。
4. uart.h
-
void uart_init(void);
-
unsigned char uart_getc(void);
-
void uart_putc(char c);
编译时只需要在Makefile的OBJS中添加uart.o就可以了。
二、测试一下getc函数
2.1 将main中主循环改为接收一个字符然后打印
-
uart_init();
-
while(1)
-
{
-
c=uart_getc();
-
uart_putc(c);
-
}
阅读(2199) | 评论(0) | 转发(1) |