系统时钟(汇编语言程序设计)

系统时钟(汇编语言程序设计)—①

一直不知道该怎么描述S3C6410的PLL(锁相环),表示很难理解,我也算是瞎猫去碰“死耗子”吧。

我就去按照韦东山老师讲述的Clock去大概描述一下吧(当然也是参考了网上的些许内容),表示不是很多,看的很蛋疼。

1、首先介绍一下PLL(锁相环)

S3C6410里面包含有三个PLL,APLL、MPLL以及EPLL,通过设置它们来达到操作CPU的工作频率的目的(哎,幸亏以前学过点PLL,要不现在可就真的坑爹了)。直接看图:

 Tiny6410学习ing鈥敚ㄈRM裸机开发鈥敚4)、系统时钟(汇编语言程序设置)鈥①

首先可以看到有三个PLL,工作时钟也就分为三组(感觉自己在说废话),APLL用来为ARM芯片提供工作时钟;MPLL为AXI、AHB以及APB(这三个东西是必须要明白的,很重要,不明白它三就不算是懂ARM硬件!)总线上设备提供工作时钟;EPLL为特殊外设,例如:视频解码器,图片解码器等,提供工作时钟。

2、然后就是三种工作时钟的产生了(AXI、AHB和APB)

ARM1176最高产生667MHz的工作频率。用户可以通过设置内部时钟分频器的值来控制输出工作时钟,而不需要修改PLL的工作频率。分频器可以选择1-16的分频数。再来看一张图片:

 Tiny6410学习ing鈥敚ㄈRM裸机开发鈥敚4)、系统时钟(汇编语言程序设置)鈥①

S3C6410内部通过AXI、AHB以及APB三种不同的总线,来控制不同的外设,关闭总线上的时钟频率可以达到系统节能的目的(用过ATMEGA、LPC的应该都很清楚吧)。AXI和AHB总线最高工作在133MHz下,APB总线最高工作在66MHz下。

由于这两个总线上(AXI/AHB和APB)的工作频率不一致,提供给AXI/AHB的频率为HCLK,提供给APB的频率为PCLK。在这两种总线上进行数据同步传输时会采用特殊逻辑单元。

我就说这么点吧(下面其实应该具体介绍一下寄存器配置,以及UART、SPI、MMC等的工作时钟的产生~~),因为好多东西一下子是很难理解的(对于我来说是的!),所以我就不写了。

3、那就是直接步入正题了:

设置一个ARM频率(ARMCLK)为531MHz;AXI/AHB的工作时钟频率(HCLK)为133MHz;APB的工作时钟频率(PCLK)为66.5MHz。同时也要求设置FOUTAPL和FOUTMPL都为532MHz;DOUTMPLL和DOUTAPLL均为256MHz;HCLKX2为266MHz~~

然后看图片(这是韦山东视频里面的,貌似有点小错误,我擦毫不清楚!!~~):

 Tiny6410学习ing鈥敚ㄈRM裸机开发鈥敚4)、系统时钟(汇编语言程序设置)鈥①

1)首先呢就是要设置锁定时间(LOCK_TIME)

如图:

Tiny6410学习ing鈥敚ㄈRM裸机开发鈥敚4)、系统时钟(汇编语言程序设置)鈥①


 ldr r0,=0x7E00F000  
 ldr r1,=0x0000FFFF
 str r1,[r0]
 
 str r1,[r0, #4]  
 str r1,[r0, #8]  
 
 

 

PLL的锁定是需要一定时间的,这里并没有严格的要求,所以只需要按默认的情况来就哦了(其实这里完全可以不用设置)。

2)当CPU不是HCLK时,要设定为异步模式(这个我也不太清楚了就~~),然后设置好后就要等待直到CPU进入异步模式(这里只是需要来个循环检测就哦了~~)。

  
#define OTHERS 0x7e00f900
 ldr r0,=OTHERS
 ldr r1,[r0]
 bic r1,r1, #0xc0    
 str r1,[r0]



loop1:   
 ldr r0,=OTHERS
 ldr r1,[r0]
 and r1,r1,#0xf00     
 cmp  r1,#0
 bne  loop1
 

3)就是设置CLK_DIV0(0X7E00_F020)

通过设置CLK_DIV0的相关位,来设置ARMCLK、HCLK、PCLK、HCLKX2、DOUTMPLL这几个频率值(仔细观察都是上面图的最后边的几个频率,对喽,就是这样,先要设置好后面的频率,再设置前面的APLL和MPLL,然后再切换就哦了~~)

首先呢,介绍下公式:

ARMCLK=DOUTAPLL/(ARM_RATIO+1)

HCLKX2=HCLKX2IN/(HCLKX2_RATIO+1)

HCLK=HCLKX2/(HCLK_RATIO+1)

PCLK=HCLKX2/(PCLK_RATIO+1)

DOUTMPLL=MOUTMPLL/(MPLL_RATIO+1)

 

#define ARM_RATIO  
#define HCLKX2_RATIO     
#define HCLK_RATIO        
#define PCLK_RATIO        
#define MPLL_RATIO        
 ldr  r0,=0x7E00F020   
 ldr  r1,=(ARM_RATIO)|(MPLL_RATIO<<4)|(HCLK_RATIO<<8)|(HCLKX2_RATIO<<9)|(PCLK_RATIO<<12)
 str  r1,[r0]
 

4)配置APLL_CON(0X7E00_F00C)

在这之前建议先看一下这个寄存器。图片:

Tiny6410学习ing鈥敚ㄈRM裸机开发鈥敚4)、系统时钟(汇编语言程序设置)鈥①

直接看其位,根据公式设置就哦了~~

APLL_CON,FOUTAPL=MDIV*Fin/(PDIV*2^SDIV)

=266*12/(3*2^1)

=532MHz







#define APLL_CON_VAL ((1<<31)|(266<<16)|(3<<8)|(1))
 ldr  r0,=0x7E00F00C
 ldr  r1,=APLL_CON_VAL
 str  r1,[r0]  
 

 

5)设置MPLL_CON(0X7E00_F010)

跟4)的步骤是一样的~~

看上面的图片,然后根据公式设置就哦了~~

MPLL_CON, FOUTMPL=MDIV*Fin/(PDIV*2^SDIV)

=266*12/(3*2^1)

=532MHz

 






#define MPLL_CON_VAL ((1<<31)|(266<<16)|(3<<8)|(1))
 ldr  r0,=0x7E00F010
 ldr  r1,=MPLL_CON_VAL
 str  r1,[r0]  

 6)就是转换喽~~

 ldr r0,=0x7E00F01C
 ldr  r1,=0x03
 str  r1,[r0]

然后就是我做的实验了:

首先上图:

Tiny6410学习ing鈥敚ㄈRM裸机开发鈥敚4)、系统时钟(汇编语言程序设置)鈥①

然后是程序:

start.S

.globl _start

_start:


 ldr r0,=0x70000000
 orr r0,r0,#0x13
 mcr p15,0,r0,c15,c2,4


 ldr r0,=0x7e004000
 mov r1,#0
 str r1,[r0]


 bl clock_init


 ldr sp,=8*1024
 bl main

halt:
 halt

clock.S

.globl clock_init

clock_init:
 


 ldr r0,=0x7E00F000  
 ldr r1,=0x0000FFFF
 str r1,[r0]
 
 str r1,[r0, #4]  
 str r1,[r0, #8]   


 
#define OTHERS 0x7e00f900
 ldr r0,=OTHERS
 ldr r1,[r0]
 bic r1,r1, #0xc0    
 str r1,[r0]



loop1:   
 ldr r0,=OTHERS
 ldr r1,[r0]
 and r1,r1,#0xf00     
 cmp  r1,#0
 bne  loop1  

 


#define ARM_RATIO  
#define HCLKX2_RATIO     
#define HCLK_RATIO        
#define PCLK_RATIO        
#define MPLL_RATIO        
 ldr  r0,=0x7E00F020   
 ldr  r1,=(ARM_RATIO)|(MPLL_RATIO<<4)|(HCLK_RATIO<<8)|(HCLKX2_RATIO<<9)|(PCLK_RATIO<<12)
 str  r1,[r0]
 







#define APLL_CON_VAL ((1<<31)|(266<<16)|(3<<8)|(1))
 ldr  r0,=0x7E00F00C
 ldr  r1,=APLL_CON_VAL
 str  r1,[r0]  

 







#define MPLL_CON_VAL ((1<<31)|(266<<16)|(3<<8)|(1))
 ldr  r0,=0x7E00F010
 ldr  r1,=MPLL_CON_VAL
 str  r1,[r0]  

 

 ldr r0,=0x7E00F01C
 ldr  r1,=0x03
 str  r1,[r0]
 
 mov  pc,lr

 

 

led.c

void delay()
{
 volatile unsigned long i=0x10000;
 while(i--);
}

int main()
{
 int i=0;
 volatile unsigned long *gpkcon0=(volatile unsigned long *)0x7f008800;
 volatile unsigned long *gpkdat=(volatile unsigned long *)0x7f008808;
 
 *gpkcon0=0x11110000;

 while(1)
 {
  for(i=0;i<1000;i++)
  {
   if(i%2==0)
    *gpkdat=0;
   else
    *gpkdat=0xf0;

   delay();
  }
 }

 return(0);
}

 

最后是Makefile:

led.bin: start.o clock.o led.o
 arm-linux-ld -Ttext 0 -o led.elf start.o clock.o led.o
 arm-linux-objcopy -O binary led.elf led.bin
 arm-linux-objdump -D led.elf > led.dis

%.o : %.S
 arm-linux-gcc -o $@ $< -c

%.o : %.c
 arm-linux-gcc -o $@ $< -c
 
clean:
 rm *.o led.elf led.bin led.dis

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
汇编语言课设 设计时钟 实现整点报时,实测没有错误。掌握综合使用基本输入输出设备、通用接口芯片、专用接口芯片的方法;n 掌握实时处理程序的编制和调试方法。实验要求:设计一个定时显示装置,用实验仪的八个LED数码管显示时间,时间显示格式为24小时制,如14-35-45。具体完成如下几个功能:1) 通过键盘设置时间。2) 整点报时功能。分秒值为59分55秒时开始报时,每秒钟蜂鸣器鸣叫一声,到整点报时停止。3) 设置闹钟功能。闹钟时间到,蜂鸣器开始鸣叫,鸣叫时间最长半分钟。可通过按键停止蜂鸣。 键盘控制时钟的启停和时间的设置,键的定义参见上图。F键(启停键)—— 程序启动后,按下该键时钟启动;再次按下该键,暂停计时,显示当前时间。C键(设置键)—— 按下C键后,为时钟设置时、分、秒初始值。D键(设置键)—— 按下D键后,设置闹钟的时、分初始值。E键(闹钟控制键)——闹钟响的时候,按下该键,闹钟停止。实验设备:8255系列模块;8253模块;8259模块。实验提示: (1)硬件连线键盘的控制、LED显示模块——用8255控制;时间的精确定时——用8253定时器1s的中断信号;整点报时控制—— (2)软件编程程序中设置一个启停标志stop,当stop值为0时启动时钟;stop值为0FFH时,暂停时钟。当时间的分秒值为59分55秒时,用8255控制8253的GATE1,设置为1,启动定时器1工作,报时。时间到整点后,GATE1清0。程序由以下模块组成: 主程序模块:对8253、8259A等芯片进行初始化,设置中断向量,扫描键盘,根据按键值作相应的处理。流程图参见下图。注意:设置初始时间时要考虑边界,时间的最大值为23:59:59,不能超出此范围。8253中断服务程序:刷新一遍数码管,计时时间到一秒,修改当前时间,整点报时。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值