前言
基于JZ2440开发板
一、思维导图
二、代码
1.uart.c
代码如下(示例):
/************************************************************************
*
* 文件名:uart.c
*
* 功能: 键盘输入字符,信息会通过串口打印在界面上
*
* 创建人:LiZhenhao
*
* 时间:2021年10月10日15:51:49
*
* 版本号:1.0
*
* 修改记录:无
*
************************************************************************/
#include "S3C2440.h"
#include "uart.h"
void Uart_Init() {
/* 1、UART0的发送引脚是TXD0/GPH2,接收引脚RXD0/GPH3 */
GPHCON &= ~( ( 3 << 4 ) | ( 3 << 6 ) ); //GPHCON的bit7~bit6 和 bit5~bit4 清零
GPHCON |= ( ( 2 << 4 ) | ( 2 << 6) ); //GPHCON的bit7~bit6 和 bit5~bit4 都置为10
/* 2、空闲时收发引脚为高电平,可通过给GPHUP设置为0,使能内部上拉 */
GPHUP &= ~( 3 << 2 ); //对应的bit3~bit2位设置为0
/* 3、设置用PCLK时钟,收发引脚为查询方式 (UCON0) */
UCON0 = 0x05; //UCON0的bit1~bit0 和 bit3~bit2 都设置为01 其余位为0
/* 4、设置波特率 UBRDIV0(0x5000 0028) */
UBRDIV0 = 26; //UBRDIV0 = 50000000 / 115200 –1 ≈ 26
/* 5、设置数据格式 ULCON0(0x5000 0000) */
ULCON0 = 0x03; //8N1:8个数据位,无校验位,1个停止位
}
//先收后发
/* 接收数据 */
unsigned char Receive_Data(void) {
while( !(UTRSTAT0 & ( 1 << 0 ) ) ); //等待UTRSTAT0的bit0变为1(判断是否有数据,有数据才读数据)
return(URXH0);
}
/* 发送数据 */
void Send_Data(unsigned char data) {
while( !(UTRSTAT0 & ( 1 << 2 ) ) ); //等待UTRSTAT0的bit2变为1的时候,表明前面已经发送完。
UTXH0 = data;
}
void Send_Message(unsigned char* s) {
while(*s) {
Send_Data(*s);
s++;
}
}
2.main.c
代码如下(示例):
#include "main.h"
int main(int argc, char const *argv[])
{
unsigned char buffer;
unsigned char s[] = "hello world!\n\r";
Uart_Init();
Send_Message(s);
while(1) {
buffer = Receive_Data();
if( buffer == '\n') {
Send_Data('\r');
} else if( buffer == '\r') {
Send_Data('\n');
}
Send_Data(buffer);
}
return 0;
}
3.main.h
代码如下(示例):
#ifndef __MAIN_H__
#define __MAIN_H__
#include "S3C2440.h"
#include "uart.h"
#endif
4.S3C2440.h
代码如下(示例):
#ifndef __S3C2440_H__
#define __S3C2440_H__
#define GPFCON (*(volatile unsigned int*)0x56000050)
#define GPFDAT (*(volatile unsigned int*)0X56000054)
#define GPGCON (*(volatile unsigned int*)0x56000060)
#define GPGDAT (*(volatile unsigned int*)0x56000064)
#define GPHCON (*(volatile unsigned int*)0x56000070)
#define GPHUP (*(volatile unsigned int*)0x56000078)
#define UCON0 (*(volatile unsigned int*)0x50000004)
#define UBRDIV0 (*(volatile unsigned int*)0x50000028)
#define ULCON0 (*(volatile unsigned int*)0x50000000)
#define UTRSTAT0 (*(volatile unsigned int*)0x50000010)
#define URXH0 (*(volatile unsigned char*)0x50000024)
#define UTXH0 (*(volatile unsigned char*)0x50000020)
#endif
5.uart.h
代码如下(示例):
#ifndef __UART_H__
#define __UART_H__
void Uart_Init();
unsigned char Receive_Data();
void Send_Data(unsigned char data);
void Send_Message(unsigned char* s);
#endif
6.start.S
代码如下(示例):
.text
.global _start
_start:
/* 关闭看门狗 */
ldr r0, =0x53000000
ldr r1, =0
str r1, [r0]
/* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
/* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
ldr r0, =0x4C000000
ldr r1, =0xFFFFFFFF
str r1, [r0]
/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8 */
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0]
/* 设置CPU工作于异步模式 */
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
/* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0)
* m = MDIV+8 = 92+8=100
* p = PDIV+2 = 1+2 = 3
* s = SDIV = 1
* FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
*/
ldr r0, =0x4C000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1, [r0]
/* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
* 然后CPU工作于新的频率FCLK
*/
/* 设置内存: sp 栈 */
/* 分辨是nor/nand启动
* 写0到0地址, 再读出来
* 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
* 否则就是nor启动
*/
mov r1, #0
ldr r0, [r1] /* 读出原来的值备份 */
str r1, [r1] /* 0->[0] */
ldr r2, [r1] /* r2=[0] */
cmp r1, r2 /* r1==r2? 如果相等表示是NAND启动 */
ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
moveq sp, #4096 /* nand启动 */
streq r0, [r1] /* 恢复原来的值 */
bl main
halt:
b halt