B001-Atmega16-PORTA的定义-(ques=1)
来源:互联网 发布:java教务管理系统源码 编辑:程序博客网 时间:2024/04/28 18:34
在iom16.h中定义了PORTA如下:
如果编译器(_SFR_ASM_COMPAT等于1)可以直接使用汇编、那么像PORTA这样的变量,就是一个地址值。
否则、如果只能使用C语言,那么操作PORTA这样的变量,就是一个指针操作的过程。
此时、PORTA的定义展开如下:
到此、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
. 0 0
- B001-Atmega16-PORTA的定义-(ques=1)
- B001-Atmega16-定时器1-(ques=1)
- B001-Atmega16-看门狗WDT-(ques=1)
- B001-Atmega16-定时器2-(ques=4)
- B001-Atmega16-中断(GCC-AVR)-(ques=3)
- B001-Atmega16-位域的汇编实现
- B001-Atmega16-数码管
- B001-Atmega16-SPI Flash
- B001-Atmega16-带电复位后不清0的.noinit变量
- B001-Atmega16-16位寄存器的读写步骤
- B001-Atmega16-TFT-(未开始)
- B001-Atmega16-汇编-地址空间分配
- B001-Atmega16-对齐模式和大小端
- A004-补码-(ques=1)
- B001-Atmega16-公共buffer管理器(静态)-(未开始)
- A003-算法-遗传算法-绘图-(ques=1)
- A004-移位范围超过变量宽度-(ques=1)
- D001-开发工具-数字示波器使用手册(测试)(ques=1)
- UVA 11995 I Can Guess the Data Structure!
- socketserver.py代码阅读笔记
- Android开发中的机型适配和国际化适配的实现;
- acm总结
- HDU - 1698 Just a Hook
- B001-Atmega16-PORTA的定义-(ques=1)
- 路由器、交换机密码破解
- acm课程总结报告
- 将html文件打包成apk
- 读《傅雷家书》乱摘2
- (数据类型-Number直接量前的“-”)JavaScript权威指南笔记4.2
- PHP使用header+Location实现网站301重定向
- 猜字游戏,杨辉三角,二分查找
- 前端奇技淫巧《长期更新》