上一章,我们只是简简单单的点亮了一个LED小灯,我们就看了好几遍数据手册,而且每次需要查好多页,那如果读者以后需要开发大量的外设,例如定时器、串口、SDRAM等外设时,是不是需要查阅N 多倍的资料?如果读者是在校学生,时间充足,而且是为了学习,这样是完全可以的。一来不用考虑项目带来的压力,二来还可以深入原理的学习。但是如果读者走上了社会,需要参与某一个项目的研发,同时开发周期比较紧张时,这样势必会浪费太多的时间,那有没有更好的办法呢?答案当然是肯定的。 5.1库函数的基础——宏定义这时,我们再回过头去,看看上节的点灯代码,便于读者查阅,直接贴到这里,源码如下,核心源码就两句话。 1. int main() 2. { 3. *(volatile unsigned long *)0x40000008 |= 1 << 21; // 使能P口的时钟 4. *(volatile unsigned long *)0x40018004 |= 1 << 22; // P口的第22位为输出端口 5. 6. while(1) 7. { 8. } 9. } 如果将寄存器做一个定义,源码如下: 10. #define AHB_BASE 0x40000000 // AHB总线的基地址 11. #define SYS_BASE (AHB_BASE + 0x00000) //SYS寄存器的基地址 12. #define CLKEN 0x08 //偏移地址 13. #define GPIOP_CLKEN *(volatile unsigned long*)(SYS_BASE + CLKEN) 14. 15. #define APB_BASE 0x40010000 16. #define GPIOP_BASE (APB_BASE + 0x08000) 17. #define DIR 0x08 18. #define GPIOP_OUTEN *(volatileunsigned long *)(GPIOP_BASE + DIR) 这样一来,上面的代码就可以变为如下所示的源码。 GPIOP_CLKEN |= 1 << 21; //使能P口的时钟 GPIOP_OUTEN |= 1 << 22; //P口的第22位为输出端口 以上程序的改进,虽然基地址通过宏是得以简化,但是如果要把全部的寄存器都以宏定义的方式列举,那工作量还是很大,操作同意很麻烦,看来我们的改进还是不到位,那我们接着再来深入研究。
|