教你如何在单片机中使用汇编优雅照明

2021-07-27 17:07 来源:电子说

汇编器现在可能很少见到了,但是有些地方还是有汇编器的,比如MCU的启动文件和RTOS底层代码。

不知道你学过汇编,还是用汇编语言编译过。

今天,我想和大家分享一些关于汇编语言的事情。

一个

学习汇编语言当我学习MCU编程10年的时候,老师还是用汇编来教我们,包括教学实验,要求我们写程序作为交换。

MOV甲,#00HMOV P1,甲

我记得那次,老师让我们背组装说明。虽然现在很多汇编指令都写不出来,但是看了很多汇编代码之后,基本上明白了它的意思。

以前计算机三级(PC技术)的计算机考试用的是汇编编程,但我当时的计算机考试还是得了满分。当时觉得自己很牛逼。现在我好像是个菜鸟

2

当我开始学习汇编从汇编到C语言的时候,真的是用汇编在51单片机上写流水灯程序。看完用C语言写的流水灯程序,突然发现用C语言写程序是那么的简单方便。

于是,我当时就开始放弃汇编,转向C语言。包括我自己在大学实验室的学习,DIY和全国大学生电子设计竞赛,都是用C语言写的。

一个10行汇编程序只需要一行C语言代码就可以实现,这是C语言相对于汇编简化的优势。

但是,用C语言编写的程序在编译后会转换为汇编。例如,当我们在线调试代码时,我们将看到类似的“汇编窗口”:

9ce82660-eb93-11eb-a97a-12bb97331649.png

由于单片机运行速度不高,内存和Flash容量不大,需要节省程序空间。

因此,使用程序集的优点是代码运行更高效,并节省了代码存储空间。

对比汇编语言和C语言编写水灯程序的主要缺点:语法复杂、可读性差、代码量大等。

我们来分享一个例子:单片机上的51流水灯程序。分别用C语言和汇编写,对比一下就知道了。

c语言版本:

/* * * * * * * * * * * * * *宏定义* * * * * * * * * * * * * * * * * * * * * * * */# define main _ fosc 22118400 l//定义主时钟

/* * * * * * * * * * * * * *延迟函数* * * * * * * * * * * * * * * * * * * * * * * * */void delay _ ms(u8ms){ u16i;do { I=MAIN _ Fosc/13000;while(-I);//每个循环14T } while(-ms);}

/* * * * * * * * * * * * * * * * *主函数* * * * * * * * * * * * * * * * * * * * * * * * void main(void){ P0 m1=0;P0M0=0//设为准双向端口P1M 1=0;P1M0=0//设置为准双向端口P2M 1=0;P2M0=0//设为准双向端口p3m 1=0;P3M0=0//设为准双向端口p4m 1=0;P4M0=0//设为准双向端口P5 m1=0;P5M0=0//设置为准双向端口P6 m1=0;P6M0=0//设置为准双向端口p7m 1=0;P7M0=0//设置为准双向端口

而(1){ P17=0;delay _ ms(250);delay _ ms(250);P17=1;P16=0;delay _ ms(250);delay _ ms(250);P16=1;p47=0;delay _ ms(250);delay _ ms(250);p47=1;p46=0;delay _ ms(250);delay _ ms(250);p46=1;}}

汇编语言版本:

;* * * * * * * * * * * * * *宏定义* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * fosc _ khz equ 22118;22118KHZ

STACK _ PORTER EQU 0D0H;堆栈开始时的地质学

;* * * * * * * * * * * * * * * *延迟函数* * * * * * * * * * * * * * * * * * * * f _ delay _ ms:push 02h;入栈R2 PUSH 03H;堆栈R3上的Push04h斯塔克R4

MOVR2

L_delay_ms_1: MOV R3,#HIGH (Fosc_KHZ/13) MOV R4,# LOW(Fosc _ KHZ/13)L _ delay _ ms _ 2:MOV A,R4;1T总计13T/环路DEC R4;2T JNZ L _ delay _ ms _ 3;4T DEC R3L _ delay _ ms _ 3:DEC A;1T ORL A,R3;1T JNZ L _ delay _ ms _ 2;4T DJNZ R2,L_delay_ms_1

POP 04H栈外R2 POP 03H;弹出R3 POP 02H弹出R4 RET

;* * * * * * * * * * * * * * *主程序* * * * * * * * * * * * * * * * * * * * * * * org 0100h;resetF_Main: CLR A MOV P0M1,A;设置为准双向端口MOV P0M0,A MOV P1M1,A;设置为准双向端口MOV P1M0,A MOV P2M1,A;设置为准双向端口MOV P2M0,A MOV P3M1,A;设置为准双向端口MOV P3M0,A MOV P4M1,A;设置为准双向端口MOV P4M0,A MOV P5M1,A;设置为准双向端口MOV P5M0,A MOV P6M1,A;设置为准双向端口MOV P6M0,A MOV P7M1,A;设置为准双向端口MOV P7M0,a

MOV SP,# STACK _ PORTER MOV PSW,# 0;选择组0 R0~R7

L_MainLoop: CLR P1.7 MOV A,# 250 LCALL F _ delay _ ms250毫秒LCALL F_delay_ms,延迟250毫秒;Setb p1.7,延迟250毫秒

CLR P1.6 MOV A,# 250 LCALL F _ delay _ ms250毫秒LCALL F_delay_ms,延迟250毫秒;Setb p1.6,延迟250毫秒

CLR P4.7 MOV A,# 250 LCALL F _ delay _ ms250毫秒LCALL F_delay_ms,延迟250毫秒;Setb p4.7,延迟250毫秒

CLR P4.6 MOV A,# 250 LCALL F _ delay _ ms250毫秒LCALL F_delay_ms,延迟250毫秒;Setb p4.6,延迟250毫秒

SJMP主环路

上面两个程序的功能是一样的(流水灯),但是对比代码,有什么区别?

对于有编译基础的同学来说,这个简单的流水灯程序可能很容易理解。

然而,对于大多数人来说,他们肯定会发现汇编很难阅读。是的,这是汇编的“特色”。

最后是汇编语法,对于大部分读者来说,我现在不建议进一步学习,只需要了解一些基本内容。

有一小部分人想从事底层开发,比如底层驱动、MCU验证、固件库开发等。当他们有时间的时候,他们可以学习更多的组装技术。

编辑:jq

延伸 · 阅读