1)最简单的小灯闪烁

首先是51单片机下,在Proteus下的仿真,小灯会的不停闪烁(想插入图片的,没弄好,也不用太需要)

先给出C语言下的代码(copy的)

#include//我们可以用,因为现在用的都是52系列了
#define bool bit;//习惯的人直接用bit就好了
#define ture 1
#define false 0

sbit D1=P1^0;

void delay02s(void)//0.2秒的延迟。这里用的延迟不推荐,因为不准,不过再不要求很准的下很方便,我们往后会接触到更精确的定时器功能
{
unsigned char i,j,k;
for(i=20;i>0;i--)
for(j=20;j>0;j--)
for(k=248;k>0;k--);
}

void main(void)
{
    while(1)
    {  
        D1=0 ;              
        delay02s();
        D1=1;              
        delay02s();
   

     }
}

接下来是汇编语言(汇编我也是边学边卖,所以完全copy啦)

************************************************************************************************汇编

  ORG 0        ;初始
START:  CLR P1.0     ;清零P1.0
  LCALL DELAY 
  SETB P1.0           ;使P1.0变为1。
  LCALL DELAY
  LJMP START          ;转入主程序
DELAY:  MOV R5,#20     ;延时子程序,延时0.2秒
D1:  MOV R6,#20
D2:  MOV R7,#248
  DJNZ R7,$
  DJNZ R6,D2
  DJNZ R5,D1
  RET
  END
延时程序分析

程序中的符号R7、R6是代表了一个个的RAM单元,是用来放一些数据的,下面我们再来看一下其它符号的含义。

DELAY: MOV R7,#250    ;(6)

D1: MOV R6,#250    ;(7)

D2: DJNZ R6,D2    ;(8)

DJNZ R7,D1    ;(9)  

RET          ;(10)  

MOV:这是一条指令,意思是传递数据。说到传递,我们都很清楚,传东西要从一个人的手上传到另一个人的手上,也就是说要有一个接受者,一个传递者和一样东西。从指令MOV R7,#250中来分析,R7是一个接受者,250是被传递的数,传递者在这条指令中被省略了(注意:并不是每一条传递指令都会省的,事实上大部份数据传递指令都会有传递者)。它的意义也

很明显:将数据250送到R7中去,因此执行完这条指令后,R7单元中的值就应当是250。在250前面有个#号,这又是什么意思呢?这个#就是用来说明250就是一个被传递的东西本身,而不是传递者(~就是立即寻址)。那么MOV R6,#250是什么意思,应当不用分析了吧。

DJNZ:这是另一条指令,我们来看一下这条指令后面跟着的两个东西,一个是R6,一个是D2,R6我们当然已知是什么了,查一下D2是什么。D2在本行的前面,我们已学过,这称之为标号。标号的用途是什么呢?就是给本行起一个名字。DJNZ指令的执行过程是这样的,它将其后面的第一个参数中的值减1,然后看一下,这个值是否等于0,如果等于0,就往下执行,如果不等于0,就转移,转到什么地方去呢?可能大家已猜到了,转到第二个参数所指定的地方去。本条指令的最终执行结果就是,在原地转圈250次(~$就是这本行的意思)。

执行完了DJNZ R6,D2之后(也就是R6的值等于0之后),就会去执行下面一行,也就是DJNZ R7,D1,请大家自行分析一下这句话执行的结果。(转去执行MOV R6,#250,同时R7中的值减1),最终DJNZ R6,D2这句话将被执行250*250=62500次,执行这么多次同一条指令干吗?就是为了延时。


单片机时序分析:

先提一个问题:我们学校里什么是最重要的?

(铃声)校长可以出差,老师可以休息,但学校一日无铃声必定大乱。整个学校就是在铃声的统一指挥下,步调一致,统一协调地工作着。这个铃是按一定的时间安排来响的,我们可以称之为“时序��时间的顺序”。一个由人组成的单位尚且要有一定的时序,计算机当然更要有严格的时序。事实上,计算机更象一个大钟,什么时候分针动,什么时候秒针动,什么时候时针动,都有严格的规定,一点也不能乱。计算机要完成的事更复杂,所以它的时序也更复杂。

我们已知,计算机工作时,是一条一条地从ROM中取指令,然后一步一步地执行,我们规定:计算机访问一次存储器的时间,称之为一个机器周期。这是一个时间基准,好象我们人用“秒”作为我们的时间基准一样,为什么不干脆用“秒”,多好,很习惯,学下去我们就会知道用“秒”反而不习惯。

一个机器周期包括12个时钟周期。下面让我们算一下一个机器周期是多长时间吧。设一个单片机工作于12M晶振,它的时钟周期是1/12(微秒)。它的一个机器周期是12*(1/12)也就是1微秒。(请计算一个工作于6M晶振的单片机,它的机器周期是多少)。

MCS-51单片机的所有指令中,有一些完成得比较快,只要一个机器周期就行了,有一些完成得比较慢,得要2个机器周期,还有两条指令要4个机器周期才行。这也不难再解,不是吗?我让你扫地的执行要完成总得比要你完成擦黑板的指令时间要长。为了恒量指令执行时间的长短,又引入一个新的概念:指令周期。所谓指令周期就是指执行一条指令的时间。INTEL对每一条指令都给出了它的指令周期数,这些数据,大部份不需要我们去记忆,但是有一些指令是需要记住的,如DJNZ指令是双周期指令。

下面让我们来计算刚才的延时。首先必须要知道晶振的频率,我们设所用晶振为12M,则一个机器周期就是1微秒。而DJNZ指令是双周期指令,所以执行一次要2个微秒。一共执行62500次,正好125000微秒,也就是125毫秒。


经典:如何精确计算延时子程序的执行时间?

    汇编语言的一大优势就是能够精确控制程序的执行时间,这在编写一些对时序要求严格的外围器件驱动时由为重要!

;延时子程序,12M晶振延时约253毫秒
DELAY:
MOV R4,#2------执行1个机器周期,耗时1微秒
L3: MOV R2 ,#250---执行1个机器周期,耗时1微秒
L1: MOV R3 ,#251---执行1个机器周期,耗时1微秒
L2: DJNZ R3 ,L2---执行2个机器周期,反复执行251次(2x251)=502微秒)
DJNZ R2 ,L1-----执行2个机器周期,反复执行250次(1+502+2)*250=126250微秒)
DJNZ R4 ,L3-----执行2个机器周期,反复执行2次 (1+1+502+126250+2)*2=253512微秒)

RET

delay 加上第一条总共延时1+253512=253513微秒
¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
51的代码很眼熟很简单是吧,那么我们接下来就要来看看MSP430的代码啦~
由于我对汇编很不熟悉,也大部分用C来做,所以一定有很多不正确的地方,对于MSP430 Proteus只有针对11x,12x,13x的仿真,我这边用的是从实验室借来的开发板,44x系的。
同样先是C语言的代码
#include
void main(void)
{
 WDTCTL=WDTPW + WDTHOLD;//停止看门狗,后面会提及
 P2DIR |= 0x02;//P2.1设置为输出
for(;;)
{
unsigned int i;
P2OUT ^= 0x02;//取反P2.1*因为这个16进制数是2吧,那么就是00000010吧
i=50000;
do (i--);
while(i!=0);
}
}
除了一些特别的也不用太解释了,先把汇编的代码给上(这是控制P1.0的),然后一起说。
#include
      ORG 01100h   ;初始,我开始很不明白为什么是01100h。它是一条伪指令是给编译器用的,指定了起始位置,就是指定了程序放在内存的哪里
RESET   mov.w #0A00h,SP;初始化了SP寄存器
StopWDT mov.w #WDTPW + WDTHOLD,&WDTCTL;关闭看门狗
SetupP1 bis.b #001h,&P1DIR ; P1.0 OUTPUT                           ;
Mainloop xor.b #001h,&P1OUT ;触发P1,异或的功能就是取反
Wait     mov.w #050000,R15;
L1       dec.w R15         ;减一
         jnz L1            ;跳转指令不为零时跳转
         jmp Mainloop      ;无条件跳转
                     ;
ORG      0FFFEh      ;查一下就知道这个地址是中断向量表的起始
DW       RESET       ;RESET是你的程序的标号,连接时在定位后有一个立即地址,将这个地址作为中断向量.这样该中断向量就指向RESET标号
END
#############################################################################################################
好啦以上就是所有的代码了,今天由于没有成功借到开发板,所以430的代码,没有调试,虽然这个闪烁灯书上有但是也不能确定准确的。下面就稍微说点其他作为复习吧
首先是看门狗,看门狗实际就是一个定时器,如果溢出就产生复位,是很有用的。然后是端口的使用配置端口时先配置功能选择PxSEL,若是I/O则继续配置方向PxDIR,若是输入则中断使能PxIE,若是能则配置中断触发沿选择PxIES。(注意P1,P2中断为多中断源,所以中断标志PxIFG的判断很重要)
争取以后自己能多写点呵呵。

 

 

你可能感兴趣的:(1)最简单的小灯闪烁)