目录

  • 第一节 硬件知识_LED原理图
    • 1、 点亮LED需要做的事情:
    • 2、 LED原理图
  • 第二节:S3C2440启动流程与GPIO
    • 1、原理图中的net
    • 2、看芯片手册
    • 3、补充几个概念、补充S3C2440框架知识、启动过程知识
  • 第三节:编写第一个程序点亮LED
    • 1、几条汇编代码:
    • 2、汇编程序为:
    • 3、 编译、烧写程序
  • 第四节:汇编与机器码
    • 1、几个CPU寄存器名称(别称)的概念
    • 2、查看机器码的方法:
  • 4、 一个作业:
  • 第5节:编程知识_进制
  • 第6节:字节序和位操作
    • 1、 字节序
    • 2、 位操作
      • (1) 移位:移位运算符可以在二进制的基础上对数字进行平移。
      • (2) 取反:
      • (3) 位与:
      • (4) 位或:
      • (5) 置位:这里举的例子是想要把bit7、8置为1
      • (6) 清位:这里举的例子是想要把bit7、8置为0
    • 第7讲:编写C程序控制LED
      • 1、 C指针操作
      • 2、 控制LED
    • 第7节:几个汇编指令
      • 1、 add和sub
      • 2、BL:(branch and linlc)(跳转并返回)
      • 3、ldm和stm(操作多个寄存器)
  • 第9讲:解剖c程序的内部机制
  • 第10节:完善LED程序_编写案件程序
    • 1、 看门狗概念:
    • 2、 led循环点亮三盏灯程序
    • 3、编写按键程序

第一节 硬件知识_LED原理图

1、 点亮LED需要做的事情:

(1) 看原理图确定控制LED的引脚;
(2) 看主芯片手册,确定如何设置/控制引脚;
(3) 写程序。

2、 LED原理图



再改进:如果引脚能力不足,可以用三极管,使引脚仅起开关作用。


注:主芯片引脚输出高/低电平即可改变LED状态,所以我们不用去关心GPIO引脚输出的到底是3.3V还是1.2V。

第二节:S3C2440启动流程与GPIO

1、原理图中的net


注:韦东山的LED1的引脚为GPF4,我的友善之臂板子是GPB5;另外,所说的“输出I/O”指电平。

2、看芯片手册



GPBCON是端口配置寄存器,用来配置为输出引脚。设置GPBCON[11:10] = 0b01,GPB5配置为输出;注:[11:10]表示第11和第10位(位就是比特,就是bits,一个二进制就是一比特); 0b01中,0b表示二进制,01表示11和10这两位分别是01。就是说把0x400写入到GPBCON寄存器,即写到地址0x56000010上(0x400是用“寄存器位查看小工具”把第11位和第10位置为01得到的十六进制数)。
GPBDAT是端口数据寄存器,用来设置端口电平状态,方法为把0或1写到对应的位。设置GPBDAT[5] = 1,则输出高电平;设置GPBDAT=0,则输出低电平。就是说若输出高电平的话则把0x20写到地址0x56000014上,若输出低电平则把写到地址0x56000014上(0x20是第五位置为1得到的十六进制数)。

3、补充几个概念、补充S3C2440框架知识、启动过程知识

概念补充:
Nor flash 一般是小程序用,nand flash用于大程序;
GPIO就是通用I/O口;
SOC是system on chip片内系统;
SRAM(static read access memory静态随机存储器,RAM存储在断电后数据消失);
基地址即起始地址。
框架为:

启动过程:
(1) NOR启动:NOR Flash基地址为0,片内RAM地址为0x40000000;
过程为:CPU读出NOR上第1个指令(前4字节),然后执行,然后再读第2个指令(也是4字节),然后执行。以此一直执行。
(2) NAND 启动:片内4kRAM基地址为0
过程为:2440硬件把nand前4k内容复制到片内RAN,然后CPU从0地址取出第一条指令执行。
注意flash与SRAM的区别:
(1)FLASH是用来存储程序的,SRAM是用来存储程序运行中的中间变量(SRAM一般作为CPU的二级缓存)。
(2)flash写入的内容不会因电源关闭而失去,读取速度慢,成本较低,一般用作程序存储器或者低速数据读取的情况;
SRAM有最快的读写速度,但电源掉落后其内容也会失去,价格昂贵,一般用作cpu的二级缓存,内存条也不用这个,适合高速数据读取的场合。
两者的关系为flash为ROM,sram为RAM。

第三节:编写第一个程序点亮LED

1、几条汇编代码:

(可以理解[R1]表示的是内存的地址,(1)、(2)所说的“R1的值x”实际上是地址)
(1)LDR:读内存。格式为:LDR R0, [R1] (假设R1的值是x,读取地址x上的数据(4字节)保存到R0中)。
(2)STR:写内存命令。格式为:STR R0,[R1] (假设R1的值是x,把R0的值写到地址x中去(也是4字节))。
(3)B:跳转
(4)MOV:格式为:MOV R0,R1 (把R1的值给赋值给R0,R0 = R1)
MOV R0,#0x100 (就是R0 = 0x100)
(5)LDR R0,= 0x12345678 (这是伪指令,它会被拆分为几条真正的RAM指令,最终结果为:R0 = 0x12345678)
注意第(4)个指令MOV和第(5)个指令的区别:MOV的R1只能是简单数(立即数),比如#0x100。具体原因如下图:

2、汇编程序为:

(这是一个.S文件)

/*
*点亮LED:GPB5
*/.text
.global _start
_start:/*配置GPB5为输出引脚
*把0x400写到地址0x56000010
*我理解,0x56000010这个端口配置寄存器(包含所有的GPB)的地址给CPU的r1寄存器,再把0x400这个十六进制数给CPU的r0寄存器,再把r0的值给r1寄存器,则5这个口被激活
*/ldr r1, =0x56000010/*把0x56000010这个地址作为值给r1*/ldr r0, =0x400/*把0x400这个地址作为值给r0。或者用mov r0, #0x400*/str r0, [r1]/*把r0的值写到r1的地址中去*//*设置GPB5输出高电平
*把0写到地址0x56000014
*/ldr r1, =0x56000014/*把0x56000014这个地址给r1*/ldr r0, =0/*把0这个地址给r0*/str r0, [r1]/*把r0的值写到r1的地址中去*//*死循环*/
halt:b halt

3、 编译、烧写程序

韦东山是用的在线远程Ubuntu系统,我用的是我电脑上的Ubuntu系统:
写好的汇编程序,要在Ubuntu中输入以下指令分别进行编译、链接、转bin文件

arm-linux-gcc -c -o led_on.o led_on.S
arm-linux-ld -Ttext 0 led_on.o -o led_on.elf
arm-linux-objcopy -O binary -S led_on.elf led_on.bin

注:为了方便,可以用makefile

第四节:汇编与机器码

1、几个CPU寄存器名称(别称)的概念

pc(program cunter程序计数器):把一个地址写到R15寄存器(也就是pc寄存器)中去的时候,程序就跳到那个地址去。
当执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称为“取指令”。与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。此后经过分析指令,执行指令。完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。
lr(link register返回地址):当一个函数执行结束后,要返回刚开始的地址,这个寄存器就是存放这个地址的。
sp(stack pointer):栈指针

2、查看机器码的方法:

在Ubuntu系统执行命令:

arm-linux-objdump -D led_on.elf > led_on.dis

把led_on.dis文件(反汇编文件)用notepad++打开
注:编译器把汇编码转换为机器码,机器码就是bin文件里的内容
led_on.dis如下:

bin文件要用UltraEdit这个软件打开如下:



对于上面这一副图片中蓝色框选的部分,[0x1c]是地址,地址中的内容是下面蓝色横线中的0x000050。
ldr r1,[pc,#20]的意思就是把0x5000050存到r1中去。

4、 一个作业:

直接在上面的led_on.bin文件(机器码)做修改,使得led2点亮。注:led2的引脚为GPB6。若写汇编程序则应该将前面汇编编码的“ldr r0, = 0x400”换成ldr r0, = 0x1000
作业答案如下:
我们需要直接修改机器码,就相当于是把汇编码中的mov r0,#0x400 转换为mov r0,#0x1000,即确定mov r0,#0x1000的机器码。
先打开ARM架构手册(ARM Architecture Reference Manual.pdf)查看MOV指令机器码的结构:

Shifter_operand是立即数,由rotate(4位)和immed(8位)两部分组成。如果确定了rotate和immed的值那么机器码就确定了。确定rotate和immed方法如下:
比如说,我们要确定mov r0,#0x1000的机器码,方法如下:
0x1000的二进制为:

第12位为1,也就是说需要由00000001(注:immed是始终等于1的)到第12位为1需要循环右移20位,20/2=10,也就是说rotate为10(即1010),即其立即数为1010 0000 0001;然后把e3a00b01(这是GPB5的)的二进制的后12为位的立即数改成1010 0000 0001就得到了mov r0,#0x1000的机器码0xe3a00a01,然后把led1的bin文件的e3a00b01替换为e3a00a01,led2就亮了。

第5节:编程知识_进制

1、 在windows cmd命令中输入calc就会弹出计算器。Windows计算器中的程序员计算器可以进行进制的转换
2、 N进制逢n进1
3、 为什么引入二进制?
因为晶体管只有2个状态(on:1;off : 0),数据使用多个晶体管表示,使用二进制可以与硬件的晶体管对应,如:8bit数据如下图表示:

为什么用八进制?答案如下图:

如何快速地转换2/8/16进制:

二进制到8/16进制,用8421法,8进制是3位一组(421),然后相加;16进制是4位一组(8421),然后相加。
8/16进制到二进制,是把8进制的每位展开为3位2进制数,把16进制数的每位展开为4位2进制数。


C语言各种进制表示方法:

第6节:字节序和位操作

1、 字节序

一般的arm芯片默认是小字节序,对于2440可以设置某个寄存器来设置使用小字节序还是大字节序。注:下面图片中的A就是低地址,A+3是高地址。

2、 位操作

(1) 移位:移位运算符可以在二进制的基础上对数字进行平移。

左移运算是将一个二进制位的操作数按指定移动的位数向左移动,移出位被丢弃,右边移出的空位一律补0。右移运算是将一个二进制位的操作数按指定移动的位数向右移动,移出位被丢弃,左边移出的空位一律补0,或者补符号位,这由不同的机器而定。在使用补码作为机器数的机器中,正数的符号位为0,负数的符号位为1。
左移n位就相当于乘以2的n次方;右移n位相当于除以2的n次方。具体这样算的原因是,左移了以后,剩下的所有值的权重增加了;右移了以后,剩下的所有值的权重减少加了。

(2) 取反:

(3) 位与:

(4) 位或:

(5) 置位:这里举的例子是想要把bit7、8置为1

(6) 清位:这里举的例子是想要把bit7、8置为0

第7讲:编写C程序控制LED

1、 C指针操作

(1) 变量和指针的原理

(2) 指针的使用方法

2、 控制LED


所以由上得到main函数:

int main() {unsigned *pGPBCON = 0x56000010;unsigned *pGPBDAT = 0x56000014;*pGPBCON = 0x400;*pGPBDAT = 0;return 0;
}

那么问题来了:
(1)写出了main函数之后,谁来调用它;
(2)main函数中的变量(pGPBCON、pGPBDAT)保存在内存中,这个内存地址是多少?
怎么来回答呢,我们写一个汇编程序,新建文件start.S,用于给main函数设置内存和调用main函数,写程序如下:

注:普及一下sp指针 在随机存储器区划出一块区域作为堆栈区,数据可以一个个顺序地存入(压入)到这个区域之中,这个过程称为‘压栈’(push)。通常用一个指针(堆栈指针SP—StackPointer)实现做一次调整,SP总指向最后一个压入堆栈的数据所在的数据单元(栈顶)。从堆栈中读取数据时,按照堆栈指针指向的堆栈单元读取堆栈数据,这个过程叫做 ‘弹出’(pop ),每弹出一个数据,SP 即向相反方向做一次调整,如此就实现了后进先出的原则。


在Ubuntu中执行:(注:我编写的led.c和start.S)

 arm-linux-gcc -c -o led.o led.carm-linux-gcc -c -o start.o start.Sarm-linux-ld -Ttext 0 start.o led.o -o led.elfarm-linux-objcopy -O binary -S led.elf led.binarm-linux-objdump -D led.elf > led.dis

至于为什么这样操作(.c文件+.S文件两个文件),原因见下一节。

第7节:几个汇编指令

执行arm-linux-objdump -D led.elf > led.dis得到反汇编文件led.dis并用notepad打开,如下:

1、 add和sub

sub r0 , r1 , #4 意为r0 = r1 – 4
sub r0, r1 , r2 意为r0 = r1 – r2
add r0, r1 , #4 意为 r0 = r1 +4

2、BL:(branch and linlc)(跳转并返回)

注:返回地址就是下一条指令的地址。

3、ldm和stm(操作多个寄存器)


下图中ia、db的意思:
过后增加(Increment After)、预先增加(Increment Before)、过后减少(Decrement After)、预先减少(Decrement Before)。
对下面这两幅图注解:
db表示先减后存,假设sp=4096,则需要先减为4092再存。存的时候规则是高编号寄存器存高地址,即pc(r15)先存,存入内存中的4092~4095。然后依次是lr、ip、fp的存储


下面这两幅图片讲的是ldmid sp,{fp,sp,pc}

第9讲:解剖c程序的内部机制

分析start.S和led.c,剖析其内部机制,把程序的反汇编搞明白就理解了C程序的内部机制:

提出以下五个问题:

先补充一下理论知识:
(1)r0-r3寄存器是传参和传递函数返回值。用于调用者和被调用者之间的参数传递。
(2)r4-r11寄存器,在你的函数中有可能其中的一些会被用到。入口处保存,出口处恢复。

看上面的反汇编,mov sp, #4096,说明这是nand启动,程序(即机器码)拷贝到片内4k内存,从片内内存的0地址开始存放(e3a0da01存放到0地址,依次储存)。
注:反汇编中的00000000<.comment>不存放。comment是注释。

一上电,执行0地址的e3a0da01,即sp指到4096.然后执行eb0000000,即跳转到c地址(去执行main()),并把返回地址8赋予lr寄存器。

现在来分析主函数反汇编语言,看下图。(注意,下图是对主函数反汇编的解释,你需要同时结合着下下一幅图一块看,看主函数在内存上的机制。如stmdb sp!,{fp,ip,lr,pc}在内存上的机制是在下下图从左往右数的第三个内存图)
对于10地址语句stmdb sp!,{fp,ip,lr,pc}进行注解:
(1)pc=当前指令地址+8,所以pc=10+8=0x18;
(2)上图已经说了lr=8;
(3)fp是未定义值。

下图是片内4k内存的分析:
结合上图和下面这幅图,你会看到:机器码存到了内存中的位置,寄存器如何存到内存中,局部变量是如何存到栈中。最重要的是,结合上下两幅图,你会明白你控制led时对端口配置寄存器和端口状态寄存器所进行的操作,在内存中是如何进行的。

从以上可知:所谓栈就是sp寄存器指向的内存。
注:关于第五个问题,怎么从栈中恢复寄存器。反汇编中内存地址54-57、58-61两个语句就是恢复内存的。
还有一个问题是,怎么传参数到被调用函数(main())的?下面写一个程序进行验证。
start.S文件

.text
.global _start_start:/* 设置内存: sp 栈 */ldr sp, =4096  /* nand启动 */
//  ldr sp, =0x40000000+4096  /* nor启动 */mov r0, #4/*把4赋给r0寄存器,也就是把4传入led_on(int which)中的形参*/bl led_onldr r0, =100000/*传参*/bl delaymov r0, #5/*传参*/bl led_onhalt:b halt

led.c文件

void delay(volatile int d)/*volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略*/
{while (d--);
}int led_on(int which)
{unsigned int *pGPFCON = (unsigned int *)0x56000050;unsigned int *pGPFDAT = (unsigned int *)0x56000054;if (which == 4){/* 配置GPF4为输出引脚 */*pGPFCON = 0x100;}else if (which == 5){/* 配置GPF5为输出引脚 */*pGPFCON = 0x400;}/* 设置GPF4/5输出0 */*pGPFDAT = 0;return 0;
}

现在将上面这个start.S和led_on编译完成后,生成一个反汇编文件并查看,如下:

led.elf:     file format elf32-littlearmDisassembly of section .text:00000000 <_start>:0:  e3a0da01    mov sp, #4096   ; 0x10004:  e3a00004    mov r0, #4  ; 0x48: eb000012    bl  58 <led_on>c: e59f000c    ldr r0, [pc, #12]   ; 20 <.text+0x20>/*注:地址20的000186a0转成十进制是10000*/10:    eb000003    bl  24 <delay>14: e3a00005    mov r0, #5  ; 0x518:    eb00000e    bl  58 <led_on>0000001c <halt>:1c:  eafffffe    b   1c <halt>20:  000186a0    andeq   r8, r1, r0, lsr #1300000024 <delay>:24:   e1a0c00d    mov ip, sp28:   e92dd800    stmdb   sp!, {fp, ip, lr, pc}2c:    e24cb004    sub fp, ip, #4  ; 0x430:    e24dd004    sub sp, sp, #4  ; 0x434:    e50b0010    str r0, [fp, #-16]38:   e51b3010    ldr r3, [fp, #-16]3c:   e2433001    sub r3, r3, #1  ; 0x140:    e50b3010    str r3, [fp, #-16]44:   e51b3010    ldr r3, [fp, #-16]48:   e3730001    cmn r3, #1  ; 0x14c:    0a000000    beq 54 <delay+0x30>50:   eafffff8    b   38 <delay+0x14>54:   e89da808    ldmia   sp, {r3, fp, sp, pc}00000058 <led_on>:58: e1a0c00d    mov ip, sp5c:   e92dd800    stmdb   sp!, {fp, ip, lr, pc}60:    e24cb004    sub fp, ip, #4  ; 0x464:    e24dd00c    sub sp, sp, #12 ; 0xc68:    e50b0010    str r0, [fp, #-16]6c:   e3a03456    mov r3, #1442840576 ; 0x5600000070: e2833050    add r3, r3, #80 ; 0x5074:   e50b3014    str r3, [fp, #-20]78:   e3a03456    mov r3, #1442840576 ; 0x560000007c: e2833054    add r3, r3, #84 ; 0x5480:   e50b3018    str r3, [fp, #-24]84:   e51b3010    ldr r3, [fp, #-16]88:   e3530004    cmp r3, #4  ; 0x48c:    1a000003    bne a0 <led_on+0x48>90:  e51b2014    ldr r2, [fp, #-20]94:   e3a03c01    mov r3, #256    ; 0x10098:  e5823000    str r3, [r2]9c: ea000005    b   b8 <led_on+0x60>a0:  e51b3010    ldr r3, [fp, #-16]a4:   e3530005    cmp r3, #5  ; 0x5a8:    1a000002    bne b8 <led_on+0x60>ac:  e51b2014    ldr r2, [fp, #-20]b0:   e3a03b01    mov r3, #1024   ; 0x400b4:  e5823000    str r3, [r2]b8: e51b3018    ldr r3, [fp, #-24]bc:   e3a02000    mov r2, #0  ; 0x0c0:    e5832000    str r2, [r3]c4: e3a03000    mov r3, #0  ; 0x0c8:    e1a00003    mov r0, r3cc:   e24bd00c    sub sp, fp, #12 ; 0xcd0:    e89da800    ldmia   sp, {fp, sp, pc}
Disassembly of section .comment:00000000 <.comment>:0:    43434700    cmpmi   r3, #0  ; 0x04: 4728203a    undefined8: 2029554e    eorcs   r5, r9, lr, asr #10c:   2e342e33    mrccs   14, 1, r2, cr4, cr3, {1}10: Address 0x10 is out of bounds.

第10节:完善LED程序_编写案件程序

1、 看门狗概念:

看门狗定时器(WDT,Watch Dog Timer)是单片机的一个组成部分,它实际上是一个计数器,一般给看门狗一个数字,程序开始运行后看门狗开始从这个数字开始倒计时计数。倒计时到0的时候系统便会复位。

2、 led循环点亮三盏灯程序

start.S文件

.text
.global _start_start:/* 关闭看门狗 */ldr r0, =0x53000000ldr r1, =0str r1, [r0]/* 设置内存: sp 栈 *//* 分辨是nor/nand启动* 写0到0地址, 再读出来* 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动* 否则就是nor启动*/mov r1, #0ldr r0, [r1] /* 读出原来的值备份 */str r1, [r1] /* 0->[0] */ ldr r2, [r1] /* r2=[0] */cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */ldr sp, =0x40000000+4096 /* 先假设是nor启动 */moveq sp, #4096  /* nand启动 */streq r0, [r1]   /* 恢复原来的值 */bl mainhalt:b halt
main.c
void delay(volatile int d)
{while (d--);
}int main(void)
{volatile unsigned int *pGPFCON = (volatile unsigned int *)0x56000050;volatile unsigned int *pGPFDAT = (volatile unsigned int *)0x56000054;int val = 0;  /* val: 0b000, 0b111 */int tmp;/* 设置GPFCON让GPF4/5/6配置为输出引脚 */*pGPFCON &= ~((3<<8) | (3<<10) | (3<<12));//清零*pGPFCON |=  ((1<<8) | (1<<10) | (1<<12));//置一/* 循环点亮 */while (1){tmp = ~val;tmp &= 7;*pGPFDAT &= ~(7<<4);//清零*pGPFDAT |= (tmp<<4);delay(100000);val++;if (val == 8)val = 0;}return 0;
}

对上面的led.c进行改进:把寄存器定义为一个宏,并且把宏直接放到一个头文件中。这样更方便了。
改变如下:

#include "s3c2440_soc.h"/*
s3c2440_soc.h中包含:
#define GPFCON (*((volatile unsigned int *)0x56000050))
#define GPFDAT (*((volatile unsigned int *)0x56000054))
*/void delay(volatile int d)
{while (d--);
}int main(void)
{int val = 0;  /* val: 0b000, 0b111 */int tmp;/* 设置GPFCON让GPF4/5/6配置为输出引脚 */GPFCON &= ~((3<<8) | (3<<10) | (3<<12));GPFCON |=  ((1<<8) | (1<<10) | (1<<12));/* 循环点亮 */while (1){tmp = ~val;tmp &= 7;GPFDAT &= ~(7<<4);GPFDAT |= (tmp<<4);delay(100000);val++;if (val == 8)val =0;}return 0;
}

3、编写按键程序

首先看原理图,找按键对应的端口寄存器,再对该寄存器进行操作。
key_led.c

#include "s3c2440_soc.h"void delay(volatile int d)
{while (d--);
}int main(void)
{int val1, val2;/* 设置GPFCON让GPF4/5/6配置为输出引脚 */GPFCON &= ~((3<<8) | (3<<10) | (3<<12));GPFCON |=  ((1<<8) | (1<<10) | (1<<12));/* 配置3个按键引脚为输入引脚:* GPF0(S2),GPF2(S3),GPG3(S4)* 注:00为input*/GPFCON &= ~((3<<0) | (3<<4));  /* gpf0,2 */GPGCON &= ~((3<<6));  /* gpg3 *//* 循环点亮 */while (1){val1 = GPFDAT;val2 = GPGDAT;if (val1 & (1<<0)) /* s2 --> gpf6 */{/* 松开 */GPFDAT |= (1<<6);}else{/* 按下 */GPFDAT &= ~(1<<6);}if (val1 & (1<<2)) /* s3 --> gpf5 */{/* 松开 */GPFDAT |= (1<<5);}else{/* 按下 */GPFDAT &= ~(1<<5);}if (val2 & (1<<3)) /* s4 --> gpf4 */{/* 松开 */GPFDAT |= (1<<4);}else{/* 按下 */GPFDAT &= ~(1<<4);}}return 0;
}

01-第一个裸机程序led及其引申相关推荐

  1. OpenRisc-14-or1200第一个裸机程序

    经过前面千辛万苦.爬山涉水.纠结了好久才弄好的环境,现在我们终于可以把FPGA当成个单片机使了,稍微比单片机猛一点,但是绝对比单片机贵一个数量级,FPGA现在能完成由CPU做的事,我们就把它当成一个大 ...

  2. OpenRics-14-or1200第一个裸机程序

    经过前面千辛万苦.爬山涉水.纠结了好久才弄好的环境,现在我们终于可以把FPGA当成个单片机使了,稍微比单片机猛一点,但是绝对比单片机贵一个数量级,FPGA现在能完成由CPU做的事,我们就把它当成一个大 ...

  3. 第三章 裸机_第一个裸机程序(上)

    第一章 裸机调试入门知识 1.对于友善之臂Micro2440开发板进行裸机调试时,需要将启动FLASH选项开关拨动到NOR FLASH上.这样做的原因:裸机程序里面会包含很多的初始化,这些初始化一般都 ...

  4. 零起点学算法01——第一个程序Hello World!

    零起点学算法01--第一个程序Hello World! Description 题目很简单 输出"Hello World!"(不含引号),并换行. Input 没有输入 Outpu ...

  5. iar 连接linux开发板,LED裸机程序(IAR)

    LED裸机程序(IAR) 一.实验环境 开发环境:IAR5.30 开发板:UT-S3C6410 开发工具:JLINK V8 二.实验目的 在无操作系统的开发板上,运行程序,掌握裸机程序的开发过程,熟悉 ...

  6. linux开发板led怎么亮,飞凌OK6410开发板(裸板) 第一个点亮LED灯程序

    飞凌OK6410开发板(裸板) 第一个点亮LED灯程序,主要的C程序,完整程序请下载附件. #define rGPMCON          (*(volatile unsigned *)(0x7F0 ...

  7. mini2440开发板学习裸机开发——day1 裸机运行LED灯程序

    开发背景:系统:ubuntu18.04系统 开发板:mini2440 串口连接工具 J-link连接工具 工具:secureCRT J-link 本次学习基于韦东山老师的嵌入式linux应用开发手册书 ...

  8. 4412裸机程序之点亮LED

    4412裸机程序之点亮LED 看一下Tiny4412原理图: 在Tiny4412核心板上有4个可编程控制LED,我们来点亮led1, led1右边接3.3V电源,左边接GPM4_0接口,把GPM4_0 ...

  9. 01火山PC开发网站-我的第一个网页程序

    大家好,我是你们的老师利快云,后续我们将会持续性的更新火山PC开发网站的文章,欢迎大家持续性的关注~ PS:文章正式开始~ 首先我们新建一个火山PCMFC窗口项目,并添加我们所安装的模块,如下图: 添 ...

最新文章

  1. Docker 的优势
  2. Jquery获取参数(解决参数中文乱码问题)
  3. 基于NVIDIA显卡的硬编解码的一点心得 (完结)
  4. RabbitMQ添加用户
  5. 【AI学院】有三AI博士小姐姐带你学深度学习之图像识别下篇,附上篇回顾
  6. Python-统计svn变更代码行数
  7. (转载)java list排序
  8. PortraitFCN算法详解
  9. ux和ui_UI和UX设计师的10种软技能
  10. 云湖共生-释放企业数据价值
  11. virtualbox 命令
  12. 数据结构Java版之基数排序(四)
  13. Dreamweaver 8 jquery 代码提示
  14. PLC控制步进电机在机床自动线中的应用
  15. 阿里云罗庆超:我为什么写《对象存储实战指南》这本书
  16. 汽车软件开发流程及代码提交
  17. 一、软件测试概念和理论
  18. DC-DC升压IC测试及EN脚讲解
  19. 不要再被骗了------QQ盗号原理大揭秘
  20. solidworks背景改为纯白色

热门文章

  1. TM1650+DS3231+STC15LE计数数码管小时钟
  2. Go语言如何自定义 linter(静态检查工具)
  3. 分组密码以及分组密码的模式
  4. Java容器List、Set、Map详解
  5. 为物联网代码安全而生 网易易盾公测IoT安全编译器Maze
  6. ROS(七):移动机器人的导航和SLAM(一)
  7. 试解leetcode算法题--求解方程
  8. Pytorch 安装(CPU)
  9. Qt开发经验小技巧合集
  10. thinkphp使用阿里大鱼短信接口