c - 使用 C 中的宏控制 AVR 芯片中某个端口上的单个位
问题描述
我有使用 CodeVisionAVR 进行 AVR 编程的经验。最近我改用 Atmel Studio,发现了一个小而烦人的问题:我无法像在 CodeVisionAVR 中那样轻松控制每个 PIN/PORT。
首先,让我们初始化一个特定的端口:
// Initialzing one port, for example PORT D:
// Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out
DDRD=0x01;
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=1
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (1<<PORTD0);
// After initializing, Port D bit 0 should be the only pin set to out.
在 CodeVisionAVR 中,我可以这样做:
PORTD.0 = 0; // Set Port D bit 0 to low
PORTD.0 = 1; // Or to high
但是在 Atmel Studio 中,将端口 D 位 0 寻址为 PORTD.0 会给我一个错误。我必须这样做:
PORTD = (1<<PORTD0); // Set Port D bit 0 to high
PORTD = (0<<PORTD0); // and low
正如你所看到的,通过移位寻址更不干净,更难读/写。我以为CVAVR使用了类似结构的东西来模仿点(。)寻址方法(在C中我们没有类),或者一些重载的运算符,或者一些宏,但是在挖掘了CVAVR中包含的头文件之后,我只能找到这个:
sfrb PORTD=0x12;
// ... other ports ...
sfrb PIND=0x10;
我的问题是,我可以在 Atmel Studio 中模仿 CVAVR 的位寻址方法吗?如果是,如何?还是那是 IDE 独有的功能?
解决方案
您对 CodeVisionAVR 的评价
PORTD.0 = 0; // Set Port D bit 0 to low
PORTD.0 = 1; // Or to high
不是有效的 C 语义,因此如果您没有在谓词上犯错误,则它必须是 codevision 编译器扩展。
C 中的这种赋值表示结构访问,但您不能声明以数字开头的结构成员(或任何其他标识符),因此 PORTD.0 会产生错误。
当你这样做时:
PORTD = (1<<PORTD0); // Set Port D bit 0 to low
PORTD = (0<<PORTD0); // and high
你没有做你评论的事情,你在第一个表达式中分配(假设 PORTD0==1)0x1 给 PORTD,在第二个表达式中分配 0x0。如果您的意图是只操作一位,那么您应该这样做:
PORTD |= (1<<PORTD0); //sets bit PORTD0 high in PORTD
PORTD &= ~(1<<PORTD0); //sets bit PORTD0 low in PORTD
PORTD ^= (1<<PORTD0); //toggles PORTD0 in PORTD
您应该阅读 C 中的位操作,这里有一个包含更多示例的帖子
有时这些动作被封装在一个宏中,这是你如何做到这一点的一个例子:
#define BitSet(Port,Bit) (Port|=(1<<Bit))
#define BitClear(Port,Bit) (Port&=~(1<<Bit))
#define BitToggle(Port,Bit) (Port^=(1<<Bit))
#define SetBits(Port,BitMask) (Port|=BitMask)
#define ClearBits(Port,BitMask) (Port&=~BitMask)
#define ToggleBits(Port,BitMask) (Port^=BitMask)
//then you can use it
BitSet(PORTD,0) ; //Sets the bit0
BitSet(PORTD,1) ; //Sets the bit1
BitSet(PORTD,2) ; //Sets the bit2
// or
BitSet(PORTD,PORTD0) ; //Sets the bit0
BitSet(PORTD,PORTD1) ; //Sets the bit1
BitSet(PORTD,PORTD2) ; //Sets the bit2
...
SetBits(PORTD,0x55) ; //Sets the bits 0,2,4, and 6. Leaves the other unchanged
ClearBits(PORTD,0x55) ; //Clear the bits 0,2,4, and 6. Leaves the other unchanged
推荐阅读
- kubernetes - Kubernetes REST API - 使用适当的示例(java 或 groovy)在容器中执行命令
- python - Qt5 - 在全屏期间强制停留在顶部
- python - 数据应该一次性发送,还是在 WHOIS 协议中一个一个发送?
- c# - 部分视图中的 Html Helper,仅添加我的脚本一次
- sql-server - 如何使 Apache NiFi 同步/镜像数据库源和目标
- r - 有关 R 中 str_extract 中语义的信息?(举个例子)
- jenkins - 通过具有更多磁盘空间的从机构建 Jenkins 作业
- arrays - 在反应状态下更改嵌套数组对象
- bash - makefile 中的条件构造中出现意外的 EOF
- excel - vba 将复制的值粘贴到变量中(application.onkey)