LED流水灯(二)

记住看汇编的时候是红在上面 黑色在下面

 

 

startup.s 程序

 

; MDK跑马灯实验
;
  PRESERVE8               // 字节对齐关键词 ,汇编有8位对齐的要求,要添加

  AREA RESET, CODE, READONLY   //   AREA 伪指令 用于定义一个代码段或数据段,这里就是一个 代码段,段名为 RESET ,定义成 只读 ,参考  http://blog.csdn.net/beyondioi/article/details/7854011

  ENTRY              //   ENTRY伪指令用于指定汇编程序的入口点  ,参考 http://blog.csdn.net/beyondioi/article/details/7854011
start             //     作为汇编程序的一个标号,定义了程序的入口,既程序从start:处开始执行。 缺省也是可以的,但是奇怪的是  这里怎么没有 : 冒号啊,不是必须添加的吗???

; 关闭看门狗
  ldr r0, = 0x53000000 ; 将看门狗控制寄存器地址放入r0   //   寄存器也是有地址的 参考 s3C2440 手册或者书 99页,watch dog 地址 便是 0x53000000 ,可以看知乎: http://www.zhihu.com/question/30155201?sort=created
  mov r1, #0                                  // 
  str r1, [r0] ; 设置看门狗控制寄存器的值为0,          str 指令      将r1寄存器的值,传送到地址值为r0的(存储器)内存中

      

  bl initmem ;   跳转到initmem代码段,初始化内存    // 黄色箭头指到这里的时候,使用 图标,跳转到 initmem 标号的代码中



IMPORT xmain                             ; 引入xmain.c中的xmain函数
    ldr sp, =0x34000000             ; 调用C程序之前先初始化栈指针
  ldr lr, =endxmain                   ; 设置xmain函数的返回地址    为什么PC+ 0x0070              

  ldr pc, =xmain                        ; 跳转到C程序中的xmain函数的入口处执行

endxmain
  ldr r0, =0x56000010 ; LED的GPIO接口配置寄存器
  ldr r1, =0x00015400 ; GPIO配置数据
  str r1, [r0] ; 设置GPIO
  ldr r0, =0x56000014 ; LED控制寄存器地址
  ldr r1, =0x000000e0 ; 全部LED亮
  str r1,[r0]
loop
  b loop ; 死循环

 

initmem ; 内存初始化
  ldr r0, =0x48000000 ; 加载内存相关寄存器首地址r0
  ldr r1, =0x48000034 ; 加载内存相关寄存器尾地址到r1    //   相当于  LDR R1 ,[PC,#0x0058] 参考书 ARM体系(P85也),将内存单元 PC+0x0058 中的字读取到  R0 寄存器中,

          

         与      计算机为什么会 这样做呢?? PC=0x3C 加上 0x58 还是 94啊 不是 9C 相差了 8位,有点乱了,不过差不多了

 

  adr r2, memdata ; 将寄存器配置数据地址段首地址加载到r2    

       PC=0x000040     + 0x00010 = 0x00050 +  8 (也相差8位),读到了, R2=58 ,这么说来 R2 原来就是 0

 

initmemloop
  ldr r3, [r2], #4 ;    循环设置存寄存器 ,将地址为R2的内存单元数据读取到 r3 中,并且 R1=R1+4 
  str r3, [r0], #4 ;    与上面一样   
  teq r0, r1             
  bne initmemloop ; 循环到最后一个寄存器时退出函数,BNE指令,是个条件跳转,即:是“不相等(或不为0)跳转指令”。如果不为0就跳转到后面指定的地址,继续执行

     

     


  BX lr       ; mov pc,lr             

memdata             
  DCD 0x22000000 ;BWSCON                      //  PC 指针  0X000058
  DCD 0x00000700 ;BANKCON0
  DCD 0x00000700 ;BANKCON1
  DCD 0x00000700 ;BANKCON2
  DCD 0x00000700 ;BANKCON3
  DCD 0x00000700 ;BANKCON4
  DCD 0x00000700 ;BANKCON5
  DCD 0x00018005 ;BANKCON6   
  DCD 0x00018005 ;BANKCON7
  DCD 0x008e07a3 ;REFRESH
  DCD 0x000000b1 ;BANKSIZE
  DCD 0x00000030 ;MRSRB6
  DCD 0x00000030 ;MRSRB7

  END

 

 

第二个函数 cmain.c 函数

 1                      /*C语言函数*/
 2 /*端口F寄存器预定义*/
 3 
 4 #define    GPBCON        (*(volatile unsigned long *)0x56000010)  // GPBCON   控制寄存器的地址
 5 #define    GPBDAT        (*(volatile unsigned long *)0x56000014)
 6 #define LEDS           (1<<5|1<<6|1<<7|1<<8)
 7 #define DELAYVAL    (0xffff)
 8       
 9 extern int delay(int time); /*声明汇编函数*/
10 
11 int xmain(void)  
12 {
13    int i = 3;
14    GPBCON = 0x00015400;// 定义了 四个LED 都为输出端口
15    while(i>0)
16     {
17        GPBDAT=(GPBDAT&(~LEDS)) | (1<<6|1<<7|1<<8);  //  LED1 亮了,其余灭
18        delay(DELAYVAL);//调用汇编语言编写的延时程序
19 
20        GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<7|1<<8);   // LED2 亮了,其余灭
21        delay(DELAYVAL);//调用汇编语言编写的延时程序
22        
23        GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<8);   // LED3 亮了,其余灭
24        delay(DELAYVAL);//调用汇编语言编写的延时程序       
25       
26        GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<7);   // LED4 亮了,其余灭
27        delay(DELAYVAL);//调用汇编语言编写的延时程序
28        i--;
29     }
30     return 0;
31  }

现在我们主要老讨论下面这两行代码:

#define LEDS           (1<<5|1<<6|1<<7|1<<8)   

GPBDAT=(GPBDAT&(~LEDS)) | (1<<6|1<<7|1<<8);  //  LED1 亮了,其余灭

这个可以去看 另外一篇 LED 随笔,终于懂了啊



 

posted on 2015-10-18 14:25  无悔这一生。  阅读(401)  评论(0编辑  收藏  举报

导航