在 iom16.h中定义了 PORTA如下:
#define PORTA _SFR_IO8(0x1B)
接着在sfr_defs.h中定义了_SFR_IO8()如下:
#if _SFR_ASM_COMPAT
......
#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
#define _SFR_IO16(io_addr) ((io_addr) + __SFR_OFFSET)
......
#else /* !_SFR_ASM_COMPAT */
......
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
#define _SFR_IO16(io_addr) _MMIO_WORD((io_addr) + __SFR_OFFSET)
......
#endif /* !_SFR_ASM_COMPAT */
这个定义表示:
如果编译器( _SFR_ASM_COMPAT等于1)可以直接使用汇编、那么像 PORTA这样的变量,就是一个地址值。
此时、__SFR_OFFSET是IO寄存器的基地址,其值等于0x00,所以PORTA展开如下:
#define PORTA _SFR_IO8(0x1B)
= ((io_addr) + __SFR_OFFSET)
= ((0x1B) + 0x00)
= 0x1B
在汇编中操作 PORTA时,就是直接操作 PORTA的地址:
否则、如果只能使用C语言,那么操作 PORTA这样的变量,就是一个指针操作的过程。
此时、 PORTA的定义展开如下:
#define PORTA _SFR_IO8(0x1B)
= _MMIO_BYTE((io_addr) + __SFR_OFFSET)
_MMIO_BYTE()的定义如下:
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
这就是用指针的方式去操作一个内存地址,此时 __SFR_OFFSET等于 0x20。
到此、 PORTA的定义进一步展开如下:
#define PORTA _SFR_IO8(0x1B)
= _MMIO_BYTE((io_addr) + __SFR_OFFSET)
= (*(volatile uint8_t *)((io_addr) + __SFR_OFFSET))
= (*(volatile uint8_t *)((0x1B) + __SFR_OFFSET))
= (*(volatile uint8_t *)(0x3B))
__SFR_OFFSET是IO寄存器的基地址,0x1B是PORTA在寄存器文件中的偏移量,加在一起就是PORTA的真实的物理地址(端口地址)。
所以我们对PORTA赋值的时候,就是将数值写入上面这个地址处的寄存器中。
参考avr-libc的介绍:http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr__notes.html
-------------------------------------------------------------------------------------------------------------------------------------
因此、我们可以将PORTA重命名如下:
uint8_t *LED = (uint8_t *)(&PORTA);
然后就可以直接对 LED进行操作,来点亮 LED:
*LED = 0x55;
如果以后更换了 LED的 IO口,只需要修改 LED这个变量的定义即可。
这样对 代码的移植是很有好处的。
也可以进一步打包成这样来隐藏指针操作符:
#define LED (*(volatile uint8_t *)(&PORTA))
最后、如果可以不用#define的定义来隐藏指针操作符就更好了,因为#define定义的部分阅读起来不方便
<还在继续...>
|<----question-001
上一篇:B001-Atmega16-带电复位后不清0的.noinit变量
下一篇:B001-Atmega16-汇编-地址空间分配
推荐阅读




推荐帖子
- 用SD储存卡读写单片机
- 我现在想用DS卡读写单片机,但是我不知道怎么开始,不知道卡座什么要不要的,需要哪些硬件啊用SD储存卡读写单片机
-
ylf175300
51单片机
- TA75074 求助
- 各位工程师: 请问TA75074可以用2个upc4558d替换吗,谢谢TA75074求助
-
sfg1988
模拟电子
- MSP430F149测电源电压
- 请问有谁知道如何用MSP430F149来测自身的供电电压啊?紧急求助,谢谢!MSP430F149测电源电压
-
472283165
微控制器 MCU
- C中使用汇编访问寄存器结构体
- 在CCS下,使用的C文件中嵌入汇编语言,在访问寄存器结构体时提示没有定义。如: asm("MOVACC,@_AdcResult.ADCRESULT0<<12"); 编译时提示:Thefollowingsymbolsareundefined: 2AssemblyErrors,NoAssemblyWarnings ADCRESULT0 这是什么原因?怎么解决呢?------不使用绝对地址访问C中使用汇编访问寄存器结构体
-
dontium
微控制器 MCU
- 以HID的SETREPORT为例说明如何使用STM32的USB库支持控制端点0
- 首先我们先回顾一下控制端点的传输方式:控制端点的传输有三个阶段,SETUP阶段、数据阶段和状态阶段;数据阶段又分为数据入(DATAIN)和数据出(DATAOUT),控制端点传输可以没有数据阶段;状态阶段有状态入(STATUSIN)和状态出(STATUSOUT)。总结起来,控制端点有如下三种可能的传输过程(以下括号中的0或1表示DATA0或DATA1传输):一、SETUPDATA_IN(0)DATA_IN(1)DATA_IN(0)......STATUS_OUT(1)二、SETUPDATA_
-
chnyuan
stm32/stm8
- 逻辑信号
- 请问取一次反和取多次反有啥区别看到一个机器逻辑芯片是多次对信号取反不明白。 逻辑信号
-
tangwei8802429
模拟电子