关于#define rGPACON(*(volatile unsigned long *)0x56000000)的理解

本文介绍了在不同计算机体系结构中,如X86、ARM等,设备采用端口映射或内存映射的方式,并重点讲解了内存映射机制下如何使用C语言进行寄存器操作及volatile关键字的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#define rGPACON(*(volatile unsigned long *)0x56000000)
对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的。

X86支持端口映射和内存映射,其余的ARM,MIPS,POWER等只支持内存映射。

端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的“端口”的概念。

内存映射,可以使用以下方法:c语言中不能直接使用地址,必须转换为指针。举个例子,比如像寄存器q(地址假定为0x48000000)写入数据0x01,那么就可以这样设置了。
#define q (*(volatile unsigned long *)0x48000000)
...
     q = 0x01;
...
    这实际上就是内存映射机制的方便性了。其中volatile关键字是嵌入式系统开发的一个重要特点。上述表达式拆开来分析,首先(volatile unsigned long *)0x48000000的意思是把0x48000000这个数强制转换成volatile unsigned long类型的指针,暂记为p,那么就是#define q *p,即q为p指针指向位置的内容了。这里就是通过内存寻址访问到寄存器q,可以读/写操作。
用GCC编译时。volatile所指示的寄存器不进行优化!!!

 

简单的说使用volatile的目的就是:
让对volatile 变量的存取不能缓存到寄存器,每次使用时需要重新从变量地址出存取,防优化。

转载于:http://ccgang1989.blog.163.com/blog/static/49926176201221673438995/

#include "beep_reg.h" void beep_reg_init(void) { unsigned long r = 0; //1.使能GPIOF组的时钟 rRCC_AHB1ENR |= (1<<5); //2.配置功能模式 //PF8 r = rGPIOF_MODER; r &= ~(1<<17); r |= (1<<16); rGPIOF_MODER = r; //3.配置输出类型 r = rGPIOF_OTYPER; r &= (~(1<<8)); rGPIOF_OTYPER = r; //4.配置输出速率 r = rGPIOF_OSPEEDR; r |= (1<<17); r |= (1<<16); rGPIOF_OSPEEDR = r; //5.配置上下拉 r = rGPIOF_PUPDR; r |= (1<<17); r &= ~(1<<16); rGPIOF_PUPDR = r; //6.默认状态(输出0) r = rGPIOF_ODR; r &= ~(1<<8); rGPIOF_ODR = r; } void beep_Ctrl(int status) { status ? BEEP_OFF : BEEP_ON; } 上面是keil中工程文件.c文件 #ifndef __BEEP_REG_H__ #define __BEEP_REG_H__ /*AHB1寄存器*/ #define rRCC_AHB1ENR *((volatile unsigned long *)(0x40023800+0x30)) /*GPIO每组的基址*/ #define GPIOA_BASE 0x40020000 #define GPIOB_BASE 0x40020400 #define GPIOC_BASE 0x40020800 #define GPIOD_BASE 0x40020C00 #define GPIOE_BASE 0x40021000 #define GPIOF_BASE 0x40021400 #define GPIOG_BASE 0x40021800 #define GPIOH_BASE 0x40021C00 #define GPIOI_BASE 0x40022000 /*GPIOF相关的寄存器*/ #define rGPIOF_MODER *((volatile unsigned long *)(GPIOF_BASE+0x00)) #define rGPIOF_OTYPER *((volatile unsigned long *)(GPIOF_BASE+0x04)) #define rGPIOF_OSPEEDR *((volatile unsigned long *)(GPIOF_BASE+0x08)) #define rGPIOF_PUPDR *((volatile unsigned long *)(GPIOF_BASE+0x0C)) #define rGPIOF_IDR *((volatile unsigned long *)(GPIOF_BASE+0x10)) #define rGPIOF_ODR *((volatile unsigned long *)(GPIOF_BASE+0x14)) /*蜂鸣器的状态*/ enum BEEP_STATUS { beep_ON, beep_OFF }; //蜂鸣器的控制 #define BEEP_OFF (rGPIOF_ODR &= ~(1<<8)) #define BEEP_ON (rGPIOF_ODR |= (1<<8)) void beep_reg_init(void); void beep_Ctrl(int status); #endif 上面是keil5工程文件中的.h文件,以上两个文件要在工程文件中同时存在才能烧录实现功能,我怎么样能把这两个文件合二为一,可以理解为是代码融合在一起成为一个文件,可以增减不必要的代码,来实现功能
03-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值