这里我们使用的开发板是4412,开发板4412上有4个LED灯,我们这里可以利用其来做流水灯实验。下面是4个LED的原理图:

查看原理图,4412开发板的LED由CPX2_7 CPX1_0 GPF3_4 GPF3_5 四个寄存器来控制,观察电路图,我们需要在IO 口输出高电平才能使LED点亮。

一、利用汇编编写程序

以GPX2为例,通过修改GPX2CON、GPX2DAT 的值来控制LED的亮灭

1、GPX2CON

其地址为0x11000C40:
 

GPX2CON可以控制8个IO口,LED2是由GPX2_7控制的,所以我们只要设置GPX2CON[7]即可

可以看到该4个bit 为0x1 时IO口为输出功能,则我们可以这样设置:

[cpp] view plaincopy
  1. LDR R0,=0x11000C40
  2. LDR R1,[R0]
  3. BIC R1,R1,#0xf0000000
  4. ORR R1,R1,#0x10000000
  5. STR R1,[R0]

现将[31:28]位清零再置一,则该端口被设置为输出引脚,而至于输出高电平还是低电平,则由GPX2DAT来控制。

2、 GPX2DAT

其地址为0x110000C44


GPX2DAT低8位有效,每1个bit控制一个端口输出电平的高低,该位置1,则输出高电平,置0,则输出低电平,为点亮LED,我们可以这样设置:

[cpp] view plaincopy
  1. LDR R0,=0x11000C44
  2. LDR R1,[R0]
  3. ORR R1,R1,#0x80
  4. STR R1,[R0]

第[7]位置1即可,此时LED被点亮;

同样,该位置0,则LED熄灭:

[cpp] view plaincopy
  1. LDR R1,[R0]
  2. BIC R1,R1,#0x01
  3. STR R1,[R0]

下面是一个完整的汇编程序,实现LED灯的闪烁(这里以LED3为例):

[cpp] view plaincopy
  1. .globl _start
  2. .arm
  3. _start:
  4. LDR R0,=0x11000C20
  5. LDR R1,[R0]
  6. BIC R1,R1,#0x0000000f
  7. ORR R1,R1,#0x00000001
  8. STR R1,[R0]
  9. loop:
  10. LDR R0,=0x11000C24
  11. LDR R1,[R0]
  12. ORR R1,R1,#0x01
  13. STR R1,[R0]
  14. BL delay
  15. LDR R1,[R0]
  16. BIC R1,R1,#0x01
  17. STR R1,[R0]
  18. BL delay
  19. B loop
  20. delay:
  21. LDR R2,=0xfffffff
  22. loop1:
  23. SUB R2,R2,#0x1
  24. CMP R2,#0x0
  25. BNE loop1
  26. MOV PC,LR
  27. .end

其实这里我们可以看到,汇编程序的缺点,就是非常繁琐,而且辨识度差,这段代码,我们看其中一段,根本看不出其实现了什么功能,ARM 裸机程序,我们同样可以用C来编写。

二、用C 实现流水灯

ARM裸机开发中最重要的就是寄存器的控制,我们如何配置寄存器呢?这里以GPX2为例,我们在头文件里定义下面这个结构体:

[cpp] view plaincopy
  1. /* GPX2 */
  2. typedef struct {
  3. unsigned int CON;
  4. unsigned int DAT;
  5. unsigned int PUD;
  6. unsigned int DRV;
  7. }gpx2;
  8. #define GPX2 (* (volatile gpx2 *)0x11000C40 )

这里将GPX2所用到的寄存器放到一个结构体内,我们看这句

#define GPX2 (* (volatile gpx2 *)0x11000C40 )

该宏定义是什么意思呢?将0x11000C40 强转成 gpx2 * 类型的地址,并取出该地址里面的值。 则我们可以直接向GPX2.CON里写入数据,便可控制该寄存器

[cpp] view plaincopy
  1. GPX2.CON = GPX2.CON & (~(0xf0000000)) | (0x10000000)

等价于

[cpp] view plaincopy
  1. LDR R0,=0x11000C40
  2. LDR R1,[R0]
  3. BIC R1,R1,#0xf0000000
  4. ORR R1,R1,#0x10000000
  5. STR R1,[R0]

可以看出大大加快了我们的开发效率。

下面是开发实例:
led.c

[cpp] view plaincopy
  1. #include "exynos_4412.h"
  2. #include "led.h"
  3. void led_init(void)
  4. {
  5. GPX2.CON = GPX2.CON & (~(0xf0000000)) | 0x10000000;
  6. GPX1.CON = GPX1.CON & (~(0x0000000f)) | 0x00000001;
  7. GPF3.CON = GPF3.CON & (~(0x000f0000)) | 0x00010000;
  8. GPF3.CON = GPF3.CON & (~(0x00f00000)) | 0x00100000;
  9. }
  10. void led_on(int n)
  11. {
  12. switch(n)
  13. {
  14. case 0:
  15. GPX2.DAT = GPX2.DAT|0x80;
  16. break;
  17. case 1:
  18. GPX1.DAT = GPX1.DAT|0x01;
  19. break;
  20. case 2:
  21. GPF3.DAT = GPF3.DAT|0x10;
  22. break;
  23. case 3:
  24. GPF3.DAT = GPF3.DAT|0x20;
  25. break;
  26. }
  27. }
  28. void led_off(int n)
  29. {
  30. switch(n)
  31. {
  32. case 0:
  33. GPX2.DAT = GPX2.DAT&(~(0x80));
  34. break;
  35. case 1:
  36. GPX1.DAT = GPX1.DAT&(~(0x01));
  37. break;
  38. case 2:
  39. GPF3.DAT = GPF3.DAT&(~(0x10));
  40. break;
  41. case 3:
  42. GPF3.DAT = GPF3.DAT&(~(0x20));
  43. break;
  44. }
  45. }

main.c

[cpp] view plaincopy
  1. #include "exynos_4412.h"
  2. #include "led.h"
  3. void  delay_ms(unsigned int num)
  4. {
  5. int i,j;
  6. for(i=num; i>0;i--)
  7. for(j=1000;j>0;j--)
  8. ;
  9. }
  10. int main (void)
  11. {
  12. int i = 0;
  13. led_init ();
  14. while (1) {
  15. led_on(i%4);
  16. led_off((i-1+4)%4);
  17. i++;
  18. delay_ms(500);
  19. }
  20. return 0;
  21. }

同时注意的是,这里我们使用的makefile:

[cpp] view plaincopy
  1. #=============================================================================#
  2. CROSS_COMPILE = arm-none-eabi-
  3. NAME =pwm
  4. #CFLAGS += -g   -O0  -mabi=apcs-gnu -mfpu=neon -mfloat-abi=softfp  -fno-builtin \
  5. #           -nostdinc  -I ./include -I ./lib
  6. CFLAGS=-mfloat-abi=softfp -mfpu=vfpv3 -mabi=apcs-gnu -fno-builtin  -fno-builtin-function -g -O0 -c  -I ./include -I ./lib
  7. LD  = $(CROSS_COMPILE)ld
  8. CC  = $(CROSS_COMPILE)gcc
  9. OBJCOPY = $(CROSS_COMPILE)objcopy
  10. OBJDUMP = $(CROSS_COMPILE)objdump
  11. OBJS=./cpu/start.o ./driver/uart.o ./driver/_modsi3.o ./driver/_divsi3.o \
  12. ./driver/_udivsi3.o ./driver/_umodsi3.o main.o ./lib/printf.o
  13. #=============================================================================#
  14. all:clean  $(OBJS)
  15. $(LD)  $(OBJS) -T map.lds -o $(NAME).elf
  16. $(OBJCOPY)  -O binary  $(NAME).elf $(NAME).bin
  17. $(OBJDUMP) -D $(NAME).elf > $(NAME).dis
  18. %.o: %.S
  19. $(CC) $(CFLAGS) -c -o  $@ $<
  20. %.o: %.s
  21. $(CC) $(CFLAGS) -c -o  $@ $<
  22. %.o: %.c
  23. $(CC) $(CFLAGS) -c -o  $@ $<
  24. clean:
  25. rm -rf $(OBJS) *.elf *.bin *.dis *.o
  26. #============================================================================#

将生成的led.bin 文件烧入开发板 0x40008000处,使用命令 go 0x40008000,则可看到开发板上的LED闪烁了。

Exynos4412 裸机开发—— 流水灯相关推荐

  1. ARM裸机——FS2410 流水灯

    一.开发环境 1.硬件平台:FS2410(s3c2410) 2.主机:Ubuntu 10.10 二.LED的原理图: 三.有关LED的GPIO口的配置信息: 1.配置GPFCON寄存器,设置GPF4- ...

  2. 利用汇编和C语言实现Exynos4412裸机开发系列之实现LED跑马灯(含源码)

    一.前言 本篇使用华清远见的FS4412开发板,对开发板的LED进行操作,来实现流水灯的效果,知识包含GPIO寄存器介绍.与ubuntu下linux操作系统通过进行交叉编译生成开发板可执行代码,通过本 ...

  3. Exynos4412裸机开发——中断处理

    以KEY2控制LED3亮灭为例: 一.轮询方式 [0]检测按键k2,按键k2按下一次,灯LED2闪一次. [1]查看原理图,连接引脚和控制逻辑 (1)按键k2 连接在GPX1_1引脚 (2)控制逻辑 ...

  4. Exynos4412 裸机开发 —— IIC总线

    前言: I2C(Inter-Integrated Circuit)总线(也称 IIC 或 I2C) 是有PHILIPS公司开发的两线式串行总线,用于连接微控制器及外围设备,是微电子通信控制领域广泛采用 ...

  5. Exynos4412裸机开发 —— UART

    一.Exynos4412 UART 的特性 Exynos4412 中UART,有4 个独立的通道,每个通道都可以工作于中断模式或DMA 模式,即 UART 可以发出中断或 DMA 请求以便在UART ...

  6. Exynos4412裸机开发 —— A/D转换器

    一.Exynos4412 A/D转换器概述 1.简述 10位或12位CMOS再循环式模拟数字转换器,它具有10通道输入,并可将模拟量转换至10位或12位二进制数.5Mhz A/D 转换时钟时,最大1M ...

  7. Exynos4412裸机开发综合练习

    下面是一个案例需求: 1.编写一段程序,该程序的主要功能是监控电路板上的电压值,若电压值超过当前的电压限制则通过蜂鸣器报警,通过按键解除报警; 2.其具体要求如下; a) 程序下载20s后,进入电压采 ...

  8. 树莓派Pico开发----流水灯

    最近参加工作一直在和C.C#打交道,一年多前自学的Python似乎都无用武之地,偶然看到树莓派Pico(双核Cortex-M0+)支持MicroPython,而且价格也只有4$,树莓派基金会还提供了一 ...

  9. Exynos4412裸机开发 —— RTC 实时时钟单元

    RTC(Real-Time Clock) 实时时钟.RTC是集成电路,通常称为时钟芯片.在一个嵌入式系统中,通常采用RTC来提供可靠的系统时间,包括时分秒和年月日等,而且要求在系统处于关机状态下它也能 ...

最新文章

  1. 一张图读懂“云栖大会·南京峰会”重磅发布产品
  2. cordova入门——cordova环境配置
  3. java 静态方法覆盖_Java中方法的覆盖和静态方法的隐藏
  4. python安装pandas模块-python安装numpy和pandas的方法步骤
  5. 喜报丨神策数据再获北京市广播电视局优秀推荐项目
  6. XCTF-MISC-新手区:give_you_flag
  7. JS高级:事件冒泡和事件捕获;
  8. 解决方案:如何防止数据重复插入
  9. tecplot脚本在Linux系统下运行,Linux系统下安装Tecplot的步骤
  10. centos7 ies4linux,Ubuntu 7.10中通过IEs4linux安装IE6
  11. python中 for in 用法_python中for in的用法详解
  12. 戴尔服务器怎么u盘安装win7系统教程,戴尔电脑怎么用u盘装win7系统教程
  13. 你手写过堵塞队列吗?
  14. css中导入自定义字体库
  15. linux 7.5安装教程,如何在CentOS Linux 7.5上安装 Pip
  16. 关于个人网站的盈利模式,可能你还不知道?
  17. BUG一词是如何来的?
  18. webshell多种方法免杀
  19. echart 广州3d_echarts绘制3D城市地图
  20. [机器学习] --- 红楼梦后四十回到底是谁写的?机器学习分析法

热门文章

  1. 解决SQL命令行回退的问题
  2. 一,彻底理解第一个C语言程序 Hello World
  3. KVM虚拟机IO处理过程(二) ----QEMU/KVM I/O 处理过程
  4. JSF 2.0/2.1 生命周期简介
  5. 每个人都应该使用的Python 3中被忽略的3个功能
  6. 绘制基础知识-canvas paint
  7. 673. 最长递增子序列的个数
  8. leetcode 674. 最长连续递增序列
  9. leetcode35. 搜索插入位置(二分搜索)
  10. 共享语义 unix语义_语义UI按钮