--------------------------------------以下为原文---------------------------------------------
关于:“
#define AT91C_BASE_PIOA (AT91_CAST(AT91PS_PIO) 0xFFFFF400)
#define AT91C_PIO_PA0 (1 << 0)
#define PIO_PER (AT91_CAST(AT91_REG *) 0x00000000)
”的说明,比较多的废话,幸运的是不费吐沫(费爪子,嘿嘿)
这些都是符号定义,目的是为了以后用“符号”而不是“具体的地址”来使用ARM的内部资源(这些内部资源当然都是有地址的寄存器啦!)
比如#define AT91C_BASE_PIOA (AT91_CAST(AT91PS_PIO) 0xFFFFF400)这一句,以后当你要使用通用IO端口A的相关寄存器时,使用AT91C_BASE_PIOA这个符号就可以了,就不必使用从0xFFFFF400开始的一系列地址了。
注意使用通用IO端口时,涉及到的寄存器可不仅仅是端口本身的一个地址,而是好几个地址,比如:输出/输入设置寄存器,输出0寄存器,输出1寄存器,中断许可寄存器,中断禁止寄存器,中断屏蔽寄存器,.....,等等等等。所以要使用的不止0xFFFFF400这一个地址,而是一组连续的地址,于是,把这些连续的地址对应的、功能上相关的(都与端口A相关)寄存器组合到一个结构里,用指针AT91PS_PIO指向这个结构,你可以看看AT91PS_PIO是不是就是这么定义的。
以后要使用端口A,一般来说,你必须首先按手册的说明,设置这个结构里的某一个或某几个的寄存器的值(初始化),然后才可以使用它。
基本的使用形式是:AT91C_BASE_PIOA->XXXX = YYYY;
例如:
AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA0;//设置端口A的最低位为输出状态,PIO_OER是端口A的输出能寄存器。
AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA0;//端口A的最低位输出高电平,PIO_SODR是端口A的置1寄存器,如果要使最低位输出0,就必须使用寄存器PIO_CODR,即端口A的清0寄存器。
AT91C_PIO_PA0也是一个符号定义,说穿了就是1。“#define AT91C_PIO_PA0 (1 << 0)”这个定义看起来似乎有点怪怪的感觉,但因为端口A可能是32位的,对每一位都有类似的定义:
AT91C_PIO_PA0 (1 << 0)
AT91C_PIO_PA1 (1 << 1)
AT91C_PIO_PA2 (1 << 2)
AT91C_PIO_PA3 (1 << 3)
....
AT91C_PIO_PA30 (1 << 30)
AT91C_PIO_PA31 (1 << 31)
假定你要使用端口A的B0~B3位以及B17~B19位为输出,并且让B0=1,B1=0,B2=0,B3=1,B17=0,B18=0,B19=1,就可以这样写代码:
AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA0 | AT91C_PIO_PA1 | AT91C_PIO_PA2 | AT91C_PIO_PA3 | AT91C_PIO_PA17 | AT91C_PIO_PA18 | AT91C_PIO_PA19;//初始化时设置端口A的B0,B1,B2,B3,B17,B18,B19位为输出状态。
.....
AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA0 | AT91C_PIO_PA3 | AT91C_PIO_PA19;//端口A的B0,B3,B19位输出高电平
AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA1 | AT91C_PIO_PA2 | AT91C_PIO_PA17 | AT91C_PIO_PA18;//端口A的B1,B2,B17,B18位输出低电平
由于有了前面的符号定义,就一个地址也看不见了,全用的符号。
端口做通用输入/输出,是端口的最简单应用,如果要使用端口的第二功能或者要启动端口的中断,需要的设置当然会更复杂一些,建议找对应的样例代码仔细看看,就没什么问题了。
文章评论(0条评论)
登录后参与讨论