从点亮一个LED开始,Cortex-A9裸机程序设计
电路原理图:
如何点亮一个LED?
通过对原理图进行分析,我们能够发现给三极管的基极加上一个高点平时,三级管be结导通构成通路,此时二极管就点亮了。若要将LED熄灭只需取消高电平输出。
如何使三级管基极获得一个高电平?
控制三极管基极的其实是exynos4412的一个引脚(忽略具体是怎么连接的),因此我们要做的就是:
- 配置相关寄存器使引脚变为输出功能(这里配置为输出功能 0x1)
- 配置上下拉(若需要)
- 操作寄存器改变引脚电平变化
- 配置带负载能力(若需要)
相关寄存器
配置引脚功能
获取或设置引脚状态
配置引脚内部上下拉
配置带负载能力
一个简单流水灯的实现:
#include "exynos_4412.h" /* LED点亮、熄灭以及状态反转操作 */ #define LED_ON(LED_x) ( *(LED_x.port) |= (1 << LED_x.pin) ) #define LED_OFF(LED_x) ( *(LED_x.port) &= (~(1 << LED_x.pin)) ) #define LED_REV(LED_x) ( *(LED_x.port) ^= (1 << LED_x.pin) ) /* 存放一个LED的端口信息以及引脚信息 */ typedef struct { unsigned int *port; /* LED端口状态寄存器地址 */ int pin; /* 端口中的第几pin */ }led_t; /* 定义并初始化4个LED,方便接下来操作 */ led_t LED_2 = {(unsigned int *)0x11000C44, 7}; /*GPX2DAT, bit[7]*/ led_t LED_3 = {(unsigned int *)0x11000C24, 0}; /*GPX0DAT, bit[0]*/ led_t LED_4 = {(unsigned int *)0x114001E4, 4}; /*GPF3DAT, bit[4]*/ led_t LED_5 = {(unsigned int *)0x114001E4, 5}; /*GPF3DAT, bit[5]*/ /* 简单延时函数 */ void delay_ms(unsigned int time); int main() { /*配置引脚作为输出*/ GPX2.CON = GPX2.CON & ~(0xf << 28) | (0x1 << 28); GPX1.CON = GPX1.CON & ~0xf | 0x1; GPF3.CON = GPF3.CON & ~(0xff << 16) | (0x11 << 16); /*实现简单流水灯*/ while(1) { LED_ON(LED_2); LED_OFF(LED_3); LED_OFF(LED_4); LED_OFF(LED_5); delay_ms(500); LED_OFF(LED_2); LED_ON(LED_3); LED_OFF(LED_4); LED_OFF(LED_5); delay_ms(500); LED_OFF(LED_2); LED_OFF(LED_3); LED_ON(LED_4); LED_OFF(LED_5); delay_ms(500); LED_OFF(LED_2); LED_OFF(LED_3); LED_OFF(LED_4); LED_ON(LED_5); delay_ms(500); } return 0; } void delay_ms(unsigned int time) { int i, j; while(time--) { for(i = 0; i < 5; i++) for(j = 0; j < 610; j++); //do nothing } }
ARM汇编代码实现LED闪烁
.globl _start .arm _start: LDR R0,=0x11000C20 LDR R1,[R0] BIC R1,R1,#0x0000000f ORR R1,R1,#0x00000001 STR R1,[R0] loop: LDR R0,=0x11000C24 LDR R1,[R0] ORR R1,R1,#0x01 STR R1,[R0] BL delay LDR R1,[R0] BIC R1,R1,#0x01 STR R1,[R0] BL delay B loop delay: LDR R2,=0xfffffff loop1: SUB R2,R2,#0x1 CMP R2,#0x0 BNE loop1 MOV PC,LR .end