STM8S汇编Word文件下载.docx
- 文档编号:19088397
- 上传时间:2023-01-03
- 格式:DOCX
- 页数:44
- 大小:30.70KB
STM8S汇编Word文件下载.docx
《STM8S汇编Word文件下载.docx》由会员分享,可在线阅读,更多相关《STM8S汇编Word文件下载.docx(44页珍藏版)》请在冰豆网上搜索。
也正是因为这一点,我对STM8越来越感兴趣了。
STM8与汇编语言(3)
STM8的开发环境用起来还是不错的,可以到ST的网站上下载安装程序ST_Toolset.exe。
利用该环境可以开发用汇编语言写的程序,而且与ST的三合一开发板配合起来,确实非常方便。
不过如果要想用C语言来开发,稍微有点麻烦,得去别的公司下载C的编译器(CXSTM8_16K.exe),而且下载完以后,还得去注册,等待许可文件。
实际上,我也按照ST介绍的方法做了,但始终都没有收到许可文件,也许本人实在愚笨。
但不管怎么说,我觉得ST这一点做得相当不好,实在有点抠门。
既然是免费的,为什么不一起打包提供给客户,这么麻烦,多耽误客户使用,得少卖多少STM8的芯片。
言归正传,还回到正题。
用汇编语言开发程序,最简单的就是利用ST开发环境中提供的汇编程序框架自动生成功能。
打开开发环境后,在File菜单中选择NewWorkspace,点击Createworkspaceandproject图标,然后就可以建立项目,在工具链中选STAssemblerLinker,最后选择MCU的型号,点击OK,就完成了一个项目的建立。
这个环境与微软的VC6开发环境很象,点开项目文件中的SourceFiles,能看到系统自动生成好了一个汇编语言的框架,我们编写程序只要在这框架基础上就可以了。
其实不用编写任何一条指令,这个框架程序是能够编译通过,并下载运行的。
自动生成的项目中包含3个重要的文件:
mapping.inc,mapping.asm和main.asm。
mapping.inc文件中定义的是一些常量,mapping.asm文件中定义的是一些内存的分配,主要的汇编代码都在main.asm。
下面是main.asm中的汇编代码及注释。
stm8/
#include"
mapping.inc"
segment'
rom'
;
下面是定义一个标号,ST汇编的写法,有点不习惯
这里的main标号是复位后的第一条指令,与后面的中断向量表中
的名字是对应的
main.l
;
initializeSP
ldwX,#stack_end
ldwSP,X;
设置堆栈指针
#ifdefRAM0
如果定义了RAM0,则要汇编以下代码
clearRAM0
ram0_start.bEQU$ram0_segment_start
ram0_end.bEQU$ram0_segment_end
ldwX,#ram0_start;
寄存器X指向要清除的内存起始地址
clear_ram0.l;
这是一个标号定义,用于后面的跳转指令
clr(X);
对应的内存单元清0
incwX;
寄存器X+1,指向下一个单元
cpwX,#ram0_end;
比较寄存器X是否等于内存的最后一个地址
jruleclear_ram0;
若不等于,则循环
#endif
#ifdefRAM1
如果定义了RAM1,则要汇编以下代码,代码含义与上面完全一样
clearRAM1
ram1_start.wEQU$ram1_segment_start
ram1_end.wEQU$ram1_segment_end
ldwX,#ram1_start
clear_ram1.l
clr(X)
incwX
cpwX,#ram1_end
jruleclear_ram1
clearstack
将堆栈区的内存单元清0,代码含义与上面完全一样
stack_start.wEQU$stack_segment_start
stack_end.wEQU$stack_segment_end
ldwX,#stack_start
clear_stack.l
cpwX,#stack_end
jruleclear_stack
infinite_loop.l;
定义一个标号
由于是一个框架,初始化内存后,进入一个死循环
jrainfinite_loop
下面代码写的是一段中断服务程序,不过也是空的
interruptNonHandledInterrupt
NonHandledInterrupt.l
当进入中断服务程序后,无其它动作,直接返回
iret
下面这张表很重要,定义了STM8所有的硬件中断对应的中断
服务程序的入口地址
segment'
vectit'
dc.l{$82000000+NonHandledInterrupt};
irq2
rupt};
irq24
end
把这个项目Build后,点击Debug中的StartDebugging就可以将程序下载到ST的三合一板上了,然后点击Run,程序就运行起来了,不过由于框架程序是一个空程序,初始化内存后就进入死循环了,因此什么效果也看不见。
因此我们必须在框架程序的基础上,编写自己的程序。
后面的程序例子都是在这个框架程序的基础上编写的。
STM8与汇编语言(4)
今天要做的实验是在ST的三合一开发板上,用汇编语言写一个程序,驱动板上的LED指示灯闪烁。
开发板上的LED1接在STM8的PD3上,因此要将PD3设置成输出模式,为了提高高电平时的输出电流,要将其设置成推挽输出方式。
这主要通过设置对应的DDR/CR1/CR2寄存器实现。
还是利用ST的开发工具,先生成一个汇编程序的框架,然后修改其中的main.asm,修改后的代码如下。
编译通过后,下载到开发板,运行程序,可以看到LED1在闪烁,且闪烁的频率为5HZ。
下面定义端口D的寄存器地址
PD_ODREQU$500f
PD_IDREQU$5010
PD_DDREQU$5011
PD_CR1EQU$5012
PD_CR2EQU$5013
定义堆栈空间的起始位置和结束位置
下面开始定义一个段,该段位于ROM中
定义复位后的第一条指令的标号(即入口地址)
首先要初始化堆栈指针
LDWX,#stack_end
LDWSP,X
LDA,#08
LDPD_DDR,A;
将PD3设置成输出
LDPD_CR1,A;
将PD3设置成推挽输出
LDA,#00
LDPD_CR2,A;
MAIN_LOOP.L
LDA,#08;
LDPD_ODR,A;
将PD3的输出设置成1
LDA,#100
CALLDELAY_MS;
延时100MS
LDA,#00;
JRAMAIN_LOOP;
函数功能:
延时
输入参数:
寄存器A--要延时的毫秒数,这里假设CPU的主频为2MHZ
输出参数:
无
返回值:
备注:
DELAY_MS.L
PUSHA;
将入口参数保存到堆栈中
LDA,#250;
寄存器A<
-250,作为下面的循环数
DELAY_MS_1.L
NOP;
用空操作指令进行延时4T
NOP
DECA;
-A-1,本条指令执行之间为1T
JRNEDELAY_MS_1;
若不等于0,则循环,
本条指令执行时间为2T(跳时)或1T(不跳时)
POPA;
从堆栈中恢复入口参数
将要延时的MS数-1
JRNEDELAY_MS;
若不等于0,则循环
RET;
函数返回
interruptNonHandledInterrupt
下面定义中断向量表
reset
irq0
8
end
STM8与汇编语言(5)
上一次的实验程序,完成了LED指示灯的驱动,用到了GPIO的输出方式,这一次要用GPIO的输入方式,进行按键的输入。
下面的代码是读入按键值,如果按键按下,则点亮LED,否则熄灭LED。
利用ST的开发工具,生成一个汇编程序的框架,然后修改其中的main.asm,修改后的代码如下。
编译通过后,下载到开发板,运行程序,可以看到当按下按键时,LED1点亮,当抬起按键时,LED1熄灭。
涉及到的硬件资源
LED1定义在PD3
KEY1定义在PD7
main.l;
LDWX,#stack_end
LDWSP,X
下面初始化IO端口
PD3设置成推挽输出
PD7设置成悬浮输入
将PD3设置成输出,PD7设置成输入
LDA,PD_IDR;
读入端口D的引脚输入寄存器
ANDA,#$80;
测试最高位是否为1
JRNEMAIN_LOOP_1;
若最高位为1,则跳转
LDA,#$08;
否则说明按键按下,PD3<
-1,点亮LED1
JRAMAIN_LOOP
MAIN_LOOP_1.L
LDA,#$00;
若按键没按下,PD3<
-0,熄灭LED1
iret
STM8与汇编语言(6)--8位定时器应用之一
STM8单片机中的外设资源是比较丰富的,定时器有8位的也有16位的,下面的实验程序,就是利用8位定时器4来进行延时,然后驱动LED闪烁。
同样还是利用ST的开发工具,生成一个汇编程序的框架,然后修改其中的main.asm,修改后的代码如下。
编译通过后,下载到开发板,运行程序,可以看到LED在闪烁,或者用示波器可以在LED引脚上看到方波。
在这里要特别提醒的是,从ST给的手册上看,这个定时器中的计数器是一个加1计数器,但本人在实验过程中感觉不太对,经过反复的实验,我认为应该是一个减1计数器(也许是我拿的手册不对,或许是理解上有误)。
例如,当给定时器中的自动装载寄存器装入255时,产生的方波频率最小,就象下面代码中计算的那样,产生的方波频率为30HZ左右。
若初始化时给自动装载寄存器装入1,则产生的方波频率最大,大约为3.9K左右。
也就是说实际的分频数为ARR寄存器的值+1。
STM8S207S8.INC"
定时器4的寄存器定义
TIM4_CR1EQU$5340
TIM4_IEREQU$5341
TIM4_SREQU$5342
TIM4_EGREQU$5343
TIM4_CNTREQU$5344
TIM4_PSCREQU$5345
TIM4_ARREQU$5346
LDPD_DDR,A;
下面初始化定时器4
LDA,#$00
LDTIM4_IER,A;
禁止中断
LDA,#$01
LDTIM4_EGR,A;
允许产生更新事件
LDA,#$07
LDTIM4_PSCR,A;
计数器时钟=主时钟/128=2MHZ/128
;
相当于计数器周期为64uS
LDA,#255
LDTIM4_ARR,A;
设定重装载时的寄存器值,255是最大值
LDTIM4_CNTR,A;
设定计数器的初值
;
定时周期=(ARR+1)*64=16384uS
产生方波频率=30.5HZ
b0=1,允许计数器工作
b1=0,允许更新
LDTIM4_CR1,A;
设置控制器,启动定时器
LDA,TIM4_SR;
读入定时器4的状态
ANDA,#01;
判断是否产生更新标志
JREQMAIN_LOOP;
若没有,则等待
LDA,#0;
清除更新标志
LDTIM4_SR,A
LDA,PD_ODR;
将LED驱动信号取反
XORA,#$08
LED闪烁频率=2MHZ/128/255/2=30.63
无限循环
;
nHandledInterrupt};
irq27
STM8与汇编语言(7)--8位定时器应用之二
上次写的是用STM8单片机中的8位定时器作为软件延时,采用的是查询方式。
在实际系统中,定时器的应用,更多的是采用中断方式,下面的代码就给出8位定时器在中断方式下的应用。
实验程序首先初始化驱动LED的端口,然后初始化8位的定时器4,最后启动中断允许,要记住,一定要将中断服务程序的入口地址填写到中断向量表中,并且要根据中断向量号在正确的位置上填写。
?
LDPD_CR1,A;
LDPD_CR2,A;
;
定时周期=(255+1)*64=16384uS
LD?
A,#$01;
LDA,#$01;
允许更新中断
RIM;
允许CPU全局中断
进入无限循环
下面是定时器4的中断服务程序
TIMER4_ISR.L
LDA,PD_ODR;
XORA,#$08
LED闪烁频率=2MHZ/128/256/2=30.5
IRET;
中断返回
对应的是定时器4的中断入口
nterrupt};
irq28
STM8与汇编语言(8)--16位定时器应用
当需要更长时间的定时时,最好使用16位的定时器,STM8单片机中都提供了2到3个的16位定时器,方便用户使用。
下面的代码给出了一个采用16位定时器实现的定时中断程序,在定时中断程序中,驱动LED指示灯的闪烁。
切记,一定要将中断服务程序的入口地址填写到中断向量表中,并且要根据定时器的中断向量号在正确的位置上填写。
STM8S207C_S.INC"
LDPD_CR2,A
LDTIM2_EGR,A;
LDA,#$01
LDTIM2_PSCR,A;
计数器时钟=主时钟/2=2MHZ/2
相当于计数器周期为1uS
设定重装载时的寄存器值
注意必须保证先写入高8位,再写入低8位
LDA,#$ea
LDTIM2_ARRH,A;
设定重装载时的寄存器值的高8位
LDA,#$60
LDTIM2_AR
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- STM8S 汇编
![提示](https://static.bdocx.com/images/bang_tan.gif)