GPIO
2016-09
睿丰德RFID软件系统集成商
#define A (*(volatile unsigned long *)0x48000000)
...
A = 0x01;
...
#define CTL_REG_WRITE(addr, val) (*(volatile unsigned long *)(addr)=(var)) 二、S3C2410的GPIO的特点 首先看看introduction。
· 117-bit general purpose I/O ports / 24-ch external interrupt source
The S3C2410X has 117 multi-functional input/output port pins. The ports are:
— Port A (GPA): 23-output port
— Port B (GPB): 11-input/output port
— Port C (GPC): 16-input/output port
— Port D (GPD): 16-input/output port
— Port E (GPE): 16-input/output port
— Port F (GPF): 8-input/output port
— Port G (GPG): 16-input/output port
— Port H (GPH): 11-input/output port
.equ WTCON, 0x53000000
.equ GPFCON, 0x56000050 @ offset value
.equ oGPFDAT, 0x04 @ macro defination LED_ON
@ you should initial IO pins about leds in order to use this macro
.macro LED_ON led_value //注意 在这里定义了一段宏,相当于函数,在下面可以直接通过宏名+参数值来调用该宏
ldr r1, =/led_value
str r1, [r0, #oGPFDAT] //将r1中的值赋给0x5300000054寄存器中,也就是GPFDAT寄存器
bl delay //调用延时子程序
.endm .text
.global _start @ specified by GNU ld. Here is
@ ultimately 0x00000000,and you
@ can fine this in Makefile. _start:
@ disable watch dog timer
@ otherwise mcu will reset at fixed interval, and
@ you will find led on and off in abnormal way.
mov r0, #WTCON
mov r1, #0x00
str r1, [r0] @ initial IO pins: GPF[7:4]
@ please read datasheet //开始初始化pin对应的Port控制寄存器和上拉寄存器
ldr r0, =GPFCON
ldr r1, =0x5500 //为什么要将GPFCON寄存器设置为0x5500就要一位位的来分析GPFCON寄存器,因为4个LED灯与IO口的对应关系为:GPF[7:4]----LED[4:1],我们知道在Port F中每两位来控制一个引脚,而且要将引脚设置为输出才能控制LED,所以GPF7也就是[15:14]=01,GPF6也就是[13:12]=01,同理GPF5也就是[11:10]=01,GPF4也就是[9:8]=01,所以GPFCON要被设置为0x5500
str r1, [r0] @ start to light the leds
@ led on when low voltage
1: //循环的依次点亮4个LED灯,也就是依次将下面的值设置给GPFDAT寄存器,通过下面的0xd0,0x70,0xe0,0xb0可以知道在GPFDAT寄存器中的[7:4]来控制LED的亮灭。
LED_ON 0xd0
LED_ON 0x70
LED_ON 0xe0
LED_ON 0xb0
b 1b @ meaningless but readable
stop:
b stop @
@ SUB Routine
@ @ not accurately, but good effect
delay:
mov r2, #0x10000
2:
subs r2, r2, #0x1
bne 2b mov pc, lr .end (1)我采用了延时子程序,但是上电复位后,WDT默认是打开的。所以在程序的开始要禁用WDT。 (2)关于ARM的跳转指令B、BL、BX要区分开。B一般用于本段内的指令跳转,而BL用于子程序调用,BX用于ARM和THUMB状态的切换。特别地说,BL指令会将下一条指令的地址拷贝到LR中,然后跳转到指定的地址运行程序。所以,子程序调用的模型为: bl delay ... delay: ... mov pc, lr 明确了这两条,程序就不难理解了。源代码见上传的附件。 C语言版本: (1)软件架构仿照了vivi,也可以说是Linux Kernel。当然,仅仅写这么小的程序用不到这么麻烦,但是可以训练这种架构,为写中型大型程序打好基础。 (2)注意C语言下实现寄存器读写的(*(volatile unsigned long *)(addr))。其实就是要掌握volatile和指针的用法,明白在嵌入式环境中,为什么要这样操作。 (3)写c时,要注意头文件如何处理。写Makefile时,要注意是否采用隐含规则,如果不采用,就要自己定义明确规则,就像vivi里面的Rules.make。在这里,因为只是涉及到.s的编译不采用隐含规则,所以没有把Rules.make单独拿出,事实上可以单独写为Rules.make,然后在Makefile后加入include Rules.make就可以了。 (4)要调用C子程序,必须分配堆栈空间。因为子程序调用时,要进行入栈出栈处理。又因为从nand flash启动,而nand flash在S3C2410下的特点规定堆栈不能超过4K。 先来看看利用C语言时对寄存器的操作: #define GPIO_CTL_BASE 0x56000000 //定义GPIO控制寄存器的起始地址也就是GPACON的地址
#define bGPIO(p, o) CTL_REG_READ(GPIO_CTL_BASE + (p) + (o)) /* offset */
#define oGPIO_CON 0x0
#define oGPIO_DAT 0x4
#define oGPIO_UP 0x8
#define oGPIO_F 0x50 //GPFCON寄存器相对应与GPADAT的偏移 /* registers */
#define GPFCON bGPIO(oGPIO_F, oGPIO_CON)
#define GPFDAT bGPIO(oGPIO_F, oGPIO_DAT)
#define GPFUP bGPIO(oGPIO_F, oGPIO_UP) 然后来看看C代码: #define DELAYTIME 0x5000 void delay(unsigned long n); int main(void)
{
unsigned char i;
unsigned long led[4] = {0xd0, 0x70, 0xe0, 0xb0}; GPFCON = vGPFCON; //同样vGPFCON已经初始化为0x00005500,将这个值赋值给GPFCON while (1) {
for (i=0; i<4; i++) {
GPFDAT = led[i];
delay(DELAYTIME);
}
} return 0;
} /* delay some time */
void delay(unsigned long n)
{
while (n--) {
;
}
} RFID管理系统集成商 RFID中间件 条码系统中间层 物联网软件集成