ARM之串口的RTC时钟实现

1、阅读 Real Time Clock (RTC) 的简要描述

2、观看RTC框图后,并向下找到Read/Write Register(读写寄存器BCD)

3、在Register Description(寄存器描述中找到所需要的寄存器)年月日、时分秒以及RTC控制寄存器

备注:一般全局控制器需要,局部控制器看情况,不确定的可以先选上,在后续操作中再判断是否需要,并记录好所找的的寄存器基地址+偏移地址

4、阅读初步筛选好的寄存器的详细信息并进一步进行筛选,怎么实现需求

5、进行相关代码的编写

6、牢记main函数只是实现函数的调用,其他函数尽可能的进行封装

 main.c:由于这里只使用了串口和RTC,所以只对串口进行了封装

#include "uart.h"

//通用控制器
#define RTCCON   *(unsigned int volatile*)0x10070040
//秒、分、时、天、月、年
#define BCDSEC   *(unsigned int volatile*)0x10070070
#define BCDMIN   *(unsigned int volatile*)0x10070074
#define BCDHOUR  *(unsigned int volatile*)0x10070078
#define BCDDAY   *(unsigned int volatile*)0x10070080
#define BCDMON   *(unsigned int volatile*)0x10070084
#define BCDYEAR  *(unsigned int volatile*)0x10070088

//自定义睡眠函数
void delay(){
    int t = 0xfffff*3;
    while(t--);
}
void rtc_init(){
    RTCCON = 1;
    BCDYEAR = 0X022;
    BCDMON = 0x9;
    BCDDAY = 0x7;
    BCDHOUR = 0x18;
    BCDMIN = 0x29;
    BCDSEC = 0x30;
}
void rtc_show(){
    char c = 0;
    //年
    uart_send('2');
    uart_send( ((BCDYEAR>>8)&0xf)+'0' );
    uart_send( ((BCDYEAR>>4)&0xf)+'0' );
    uart_send( ((BCDYEAR>>0)&0xf)+'0' );
    uart_send('-');
    //月
    uart_send( ((BCDMON>>4)&0x1)+'0' );
    uart_send( ((BCDMON>>0)&0xf)+'0' );
    uart_send('-');
    //日
    uart_send( ((BCDDAY>>4)&0x3)+'0' );
    uart_send( ((BCDDAY>>0)&0xf)+'0' );
    uart_send(' ');
    //时
    uart_send( ((BCDHOUR>>4)&0x3)+'0' );
    uart_send( ((BCDHOUR>>0)&0xf)+'0' );
    uart_send(':');
    //分
    uart_send( ((BCDMIN>>4)&0x8)+'0' );
    uart_send( ((BCDMIN>>0)&0xf)+'0' );
    uart_send(':');
    //秒
    uart_send( ((BCDSEC>>4)&0x8)+'0' );
    uart_send( ((BCDSEC>>0)&0xf)+'0' );
    //windows换行需要一个 \n + \r
    uart_str("\n\r");
}
void main()
{
    uart_init();
    rtc_init();
    while(1){
        rtc_show();
        delay();
    }
} 

uart.c:

#define GPA1CON      *(unsigned int volatile*)0x11400020
#define ULCON2       *(unsigned int volatile*)0x13820000
#define UCON2        *(unsigned int volatile*)0x13820004
#define UTXH2        *(unsigned int volatile*)0x13820020
#define URXH2        *(unsigned int volatile*)0x13820024
#define UBRDIV2      *(unsigned int volatile*)0x13820028
#define UFRACVAL2    *(unsigned int volatile*)0x1382002c
#define UTRSTAT2     *(unsigned int volatile*)0x13820010
void uart_init(){
    //波特率发生器
    //GPA1CON 0x11400020  [7:4] 0x2 = UART_2_TXD 发送
    GPA1CON = GPA1CON & ~(0xf<<4) | (0x2<<4);
    //GPA1CON 0x11400020  [3:0] 0x2 = UART_2_RXD 接收 
    GPA1CON = GPA1CON & ~(0xf<<0) | (0x2<<0);
    //指定数据位有几位,这里是8位
    ULCON2 = 0x3;
    //全局控制,清除0-5位待用,0x1<<2:轮询发送 <<0:轮询接收
    UCON2 = UCON2 & ~0x3f | (0x1<<2) | (0x1<<0);
//100MHZ = 100000000   100MHZ/(115200*16)-1	115200:波特率的位/秒
    UBRDIV2 = 53;
    UFRACVAL2 = 4;
}
void uart_send(char c){
    //检测有效数据,防止无效数据的发送
    //当传输buf无有效数据传输,且传输移位为空时,该位自动设置为1
    while( !(UTRSTAT2&(0x1<<2)) );
    UTXH2 = c;
}
void uart_str(char *s){

    while(*s!='\0'){
        uart_send(*s);
        s++;
    }
}
char uart_recv(){
    //检测有效数据
    //当接收buf含通过RXDn端口接收的有效数据时,自动将该位设置为1
    while( !(UTRSTAT2&0x1) );
    //接收数据位为8位
    return (URXH2 & 0xff);
}

Makefile:

all:
	arm-linux-gcc myadd.S -o start.o -c -g
	arm-linux-gcc uart.c -o uart.o -c -g
	arm-linux-gcc main.c -o main.o -c -g
	arm-linux-ld  start.o uart.o  main.o -o start.elf -Ttest.lds
	arm-linux-objcopy start.elf start.bin -O binary
clean:
	rm *.o *.elf *.bin

uart.h:

#ifndef __MY_UART__
#define __MY_UART__

void uart_init();
void uart_send(char c);
void uart_str(char *s);
#endif

test.lds、myadd.S:ARM之串口的收发_承诺$枷锁的博客-CSDN博客

效果:

FS4412 # go 41000000
## Starting application at 0x41000000 ...
2022-09-07 18:09:00
2022-09-07 18:09:01
2022-09-07 18:09:02
2022-09-07 18:09:02
2022-09-07 18:09:03
2022-09-07 18:09:04
2022-09-07 18:09:05
2022-09-07 18:09:06
2022-09-07 18:09:07
2022-09-07 18:09:08

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值