【发布时间】:2009-11-27 19:23:07
【问题描述】:
我正在使用 IC DS1620 读取单行上的 1 位串行数据。我需要使用 ARM 微控制器 (LPC2378) 的端口之一读取这些数据。 ARM 端口是 32 位的。如何将此值转换为 1 位变量?
编辑:换句话说,我需要直接引用端口引脚。
【问题讨论】:
标签: c embedded arm microcontroller
我正在使用 IC DS1620 读取单行上的 1 位串行数据。我需要使用 ARM 微控制器 (LPC2378) 的端口之一读取这些数据。 ARM 端口是 32 位的。如何将此值转换为 1 位变量?
编辑:换句话说,我需要直接引用端口引脚。
【问题讨论】:
标签: c embedded arm microcontroller
没有 1 位变量,但您可以隔离特定位,例如:
uint32_t original_value = whatever();
uint32_t bit15 = (original_value >> 15) & 1; /*bit15 now contains either a 1 or a 0 representing the 15th bit */
注意:我不知道你是从 0 还是 1 开始计算位数,所以 >> 15 可能会差一,但你明白了。
另一种选择是使用位字段,但这会变得很混乱,而且 IMO 不值得这样做,除非值中的每个位都以某种方式有用。如果您只想要一两个位,则可以使用移位和掩码。
总的来说,这个article 可能对你有用。
【讨论】:
in 或 out 指令来读取和写入 I/O 端口。
对于您的 CPU,应该使用 Evan Teran 的答案。我只是想提一下其他一些 ARM CPU 的位带特性,比如 Cortex-M3。对于 RAM/外设的某些区域,所有位都映射到单独的地址以便于访问。
更多信息请参见http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/Behcjiic.html。
【讨论】:
如果您可以直接访问端口寄存器(我对 ARM 没有任何经验),这很简单,只需将其与您想要的位对应的二进制掩码进行按位与:
var = (PORT_REGISTER & 0x00008000);
如果第 15 位为“0”,则现在 var 包含 0,如果第 15 位为“1”,则包含 0x00008000。
另外,如果你想要'0'或'1',你可以改变它:
var = ((PORT_REGISTER & 0x00008000) >> 15);
【讨论】:
(1 << 15),汇编器或编译器将在翻译时而不是运行时计算。
编译器附带的头文件将包含所有微控制器寄存器的声明,以及这些寄存器中的位。
在这篇具体的文章中,我们假设端口输入寄存器名为PORTA,而您想要的位有一个为其定义的掩码,名为PORTA15。
然后读取该引脚的状态:
PinIsSet = (PORTA & PORTA15) == PORTA15;
或者等效地,使用ternary operator:
PinIsSet = (PORTA & PORTA15) ? 1 : 0;
一般来说,请参阅参考手册了解所有寄存器和位的作用。另外,看看一些例子。 (This page on the Keil website 包含两者,网上还有很多其他示例。)
【讨论】:
在 LPC2378(与其他 LPC2xxxx 微控制器系列一样)中,I/O 端口位于系统内存中,因此您需要声明一些变量,如下所示:
#define DALLAS_PIN (*(volatile unsigned long int *)(0xE0028000)) /* Port 0 data register */
#define DALLAS_DDR (*(volatile unsigned long int *)(0xE0028008)) /* Port 0 data direction reg */
#define DALLAS_PIN (1<<15)
请注意0xE0028000是port0的数据寄存器地址,0xE0028008是port0的数据方向寄存器地址。您需要根据应用程序中使用的端口和位来修改它。 之后,在您的代码函数中,写 1、写 0 和读的代码或宏必须是这样的:
#define set_dqout() (DALLAS_DDR&=~DALLAS_PIN) /* Let the pull-up force one, putting I/O pin in input mode */
#define reset_dqout() (DALLAS_DDR|=DALLAS_PIN,DALLAS_PORT&=~DALLAS_PIN) /* force zero putting the I/O in output mode and writing zero on it */
#define read_dqin() (DALLAS_DDR&=~DALLAS_PIN,((DALLAS_PORT & DALLAS_PIN)!= 0)) /* put i/o in input mode and test the state of the i/o pin */
我希望这会有所帮助。
问候!
【讨论】:
如果测试位,最好记住 C 的运算符评估顺序,例如
if( port & 0x80 && whatever() )
可能会导致意想不到的行为,就像你刚才写的那样
if( port & (0x80 && whatever()) )
但可能会提醒
if( (port & 0x80) && whatever() )
【讨论】: