STM8与汇编语言(14)--切换时钟源<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
STM8单片机的时钟源,即可以选内部的,也可以选外部的,在系统运行过程中,可以很方便地切换。
下面的实验程序首先将主时钟源切换到外部的晶体振荡器上,振荡频率为8MHZ,然后,然后快速闪烁LED指示灯。接着,将主时钟源又切换到内部的振荡器上,振荡频率为2MHZ,然后再慢速闪烁LED指示灯。通过观察LED指示灯的闪烁频率,可以看到,同样的循环代码,由于主时钟源的改变的改变,闪烁频率和时间长短都发生了变化。
同样还是利用ST的开发工具,生成一个汇编程序的框架,然后修改其中的main.asm,修改后的代码如下。
stm8/
#include "mapping.inc"
#include "STM8S<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />207C_S.INC"
; 定义堆栈空间的起始位置和结束位置
stack_start.w EQU $stack_segment_start
stack_end.w EQU $stack_segment_end
segment 'rom' ; 下面开始定义一个段,该段位于ROM中
main.l ; 定义复位后的第一条指令的标号(即入口地址)
;
; 首先要初始化堆栈指针
LDW X,#stack_end
LDW SP,X
LD A,#08
LD PD_DDR,A ; 将PD3设置成输出
LD A,#08
LD PD_CR1,A ; 将PD3设置成推挽输出
LD A,#00
LD PD_CR2,A ;
LD A,#$01
LD CLK_ECKR,A ; 允许外部高速振荡器工作
WAIT_HSE_READY.L
LD A,CLK_ECKR
AND A,#$02
JREQ WAIT_HSE_READY ; 等待外部高速振荡器准备好
; 注意:经过上述切换后,主时钟从HSI/8(2MHZ)切换到HSE(8MHZ)
;
MAIN_LOOP.L
;下面设置CPU时钟分频器,使得CPU时钟=主时钟
;通过发光二极管,可以看出,程序运行的速度确实明显提高了
LD A,#$02
LD CLK_SWCR,A ; SWEN <- 1
LD A,#$B4
LD CLK_SWR,A ; 选择芯片外部的高速振荡器为主时钟
WAIT_CLK_SWITCH_1.L
LD A,CLK_SWCR
AND A,#$08
JREQ WAIT_CLK_SWITCH_1 ; 等待切换成功
LD A,#$00 ; 清除切换标志
LD CLK_SWCR,A
LD A,#10 ; LED高速闪10次
HIGH_SPEED.L
PUSH A ; 保存寄存器
LD A,#08
LD PD_ODR,A ; 将PD3的输出设置成1
LD A,#100
CALL DELAY_MS ; 延时100MS
LD A,#00
LD PD_ODR,A ; 将PD3的输出设置成1
LD A,#100
CALL DELAY_MS ; 延时100MS
POP A ; 恢复寄存器
DEC A
JRNE HIGH_SPEED
;下面设置CPU时钟分频器,使得CPU时钟=主时钟/4
;通过发光二极管,可以看出,程序运行的速度确实明显下降了
LD A,#$02
LD CLK_SWCR,A ; SWEN <- 1
LD A,#$E1 ; 选择HSI为主时钟源
LD CLK_SWR,A
WAIT_CLK_SWITCH_2.L
LD A,CLK_SWCR
AND A,#$08
JREQ WAIT_CLK_SWITCH_2 ; 等待切换成功
LD A,#$00 ; 清除切换标志
LD CLK_SWCR,A
; 注意:经过上述切换后,主时钟从HSE(8MHZ)切换到HSI/8(2MHZ)
LD A,#10 ; LED低速闪10次
LOW_SPEED.L
PUSH A ; 保存寄存器
LD A,#08
LD PD_ODR,A ; 将PD3的输出设置成1
LD A,#100
CALL DELAY_MS ; 延时100MS
LD A,#00
LD PD_ODR,A ; 将PD3的输出设置成1
LD A,#100
CALL DELAY_MS ; 延时100MS
POP A ; 恢复寄存器
DEC A
JRNE LOW_SPEED
JRA MAIN_LOOP
; 函数功能:延时
; 输入参数:寄存器A -- 要延时的毫秒数,这里假设CPU的主频为2MHZ
; 输出参数:无
; 返 回 值:无
; 备 注:无
DELAY_MS.L
PUSH A ; 将入口参数保存到堆栈中
LD A,#250 ; 寄存器A<-250,作为下面的循环数
DELAY_MS_1.L
NOP ; 用空操作指令进行延时4T
NOP
NOP
NOP
NOP
DEC A ; 寄存器A<-A-1,本条指令执行之间为1T
JRNE DELAY_MS_1 ; 若不等于0,则循环,
; 本条指令执行时间为2T(跳时)或1T(不跳时)
POP A ; 从堆栈中恢复入口参数
DEC A ; 将要延时的MS数-1
JRNE DELAY_MS ; 若不等于0,则循环
RET ; 函数返回
interrupt NonHandledInterrupt
NonHandledInterrupt.l
iret
; 下面定义中断向量表
segment 'vectit'
dc.l {$82000000+main} ; reset
dc.l {$82000000+NonHandledInterrupt} ; trap
dc.l {$82000000+NonHandledInterrupt} ; irq0
dc.l {$82000000+NonHandledInterrupt} ; irq1
dc.l {$82000000+NonHandledInterrupt} ; irq2
dc.l {$82000000+NonHandledInterrupt} ; irq3
dc.l {$82000000+NonHandledInterrupt} ; irq4
dc.l {$82000000+NonHandledInterrupt} ; irq5
dc.l {$82000000+NonHandledInterrupt} ; irq6
dc.l {$82000000+NonHandledInterrupt} ; irq7
dc.l {$82000000+NonHandledInterrupt} ; irq8
dc.l {$82000000+NonHandledInterrupt} ; irq9
dc.l {$82000000+NonHandledInterrupt} ; irq10
dc.l {$82000000+NonHandledInterrupt} ; irq11
dc.l {$82000000+NonHandledInterrupt} ; irq12
dc.l {$82000000+NonHandledInterrupt} ; irq13
dc.l {$82000000+NonHandledInterrupt} ; irq14
dc.l {$82000000+NonHandledInterrupt} ; irq15
dc.l {$82000000+NonHandledInterrupt} ; irq16
dc.l {$82000000+NonHandledInterrupt} ; irq17
dc.l {$82000000+NonHandledInterrupt} ; irq18
dc.l {$82000000+NonHandledInterrupt} ; irq19
dc.l {$82000000+NonHandledInterrupt} ; irq20
dc.l {$82000000+NonHandledInterrupt} ; irq21
dc.l {$82000000+NonHandledInterrupt} ; irq22
dc.l {$82000000+NonHandledInterrupt} ; irq23
dc.l {$82000000+NonHandledInterrupt} ; irq24
dc.l {$82000000+NonHandledInterrupt} ; irq25
dc.l {$82000000+NonHandledInterrupt} ; irq26
dc.l {$82000000+NonHandledInterrupt} ; irq27
dc.l {$82000000+NonHandledInterrupt} ; irq28
dc.l {$82000000+NonHandledInterrupt} ; irq29
end
2010-6-11
文章评论(0条评论)
登录后参与讨论