3

我在嵌入式世界中相对较新,所以我可能是一个小新手问这个问题。

我无法理解 C 中示例程序的语法,该程序检查是否按下按钮,如果按下则打开 LED。我正在使用 STM32F207VCT6 (Cortex-M3) 微控制器。

我无法理解的程序部分如下:

if(!(GPIOA->IDR & (1<<4)))
  Key=1;

端口 4 fromGPIOA设置为带上拉寄存器的输入。一旦按下按钮,来自按钮的信号就会进入 GND。IDR是输入数据寄存器。

所以我的问题是:

我不明白这段代码为什么需要语句中的 NOT 符号!, 。if而且我不知道在 内部进行了什么比较if,因为没有相等的符号。有人可以帮我吗?

PS:我已经知道这(1<<4)是将位 1 左移四次的按位操作。

4

3 回答 3

6

STM32F207VCT6 中每个端口有 16 个引脚。此操作试图确定端口 A 的单个引脚(4 号)的状态。让我们扩展每个部分以更好地了解发生了什么。

我们从表达式开始:

if(!(GPIOA->IDR & (1<<4)))

我们正在使用 16 位数字来计算 16 个引脚。扩展这个我们得到:

if(!(GPIOA->IDR & ((0000 0000 0000 0001) << 4)))

您已经知道这<<是按位左移。应用这个我们得到:

if(!(GPIOA->IDR & (0000 0000 0001 0000)))

扩展IDR,我将X's 用于我们不关心的位和 a?用于我们正在测试的未知位:

if(!((XXXX XXXX XXX? XXXX) & (0000 0000 0001 0000)))

接下来我们有一个&按位与运算符。如果你还记得你的 AND 真值表:

&   0 1
    - -
0 | 0 0
1 | 0 1

所以我们有操作:

  XXXX XXXX XXX? XXXX
& 0000 0000 0001 0000
---------------------
  0000 0000 000? 0000

如果端口 A 中的第 4 位是 a 0,则结果将是0000 0000 0000 0000。如果端口 A 中的第 4 位是 a 1,则结果将是0000 0000 0001 0000

如果按下开关,输入将被拉至 GND,位 4 将设置为0。如果开关未按下,则内部上拉电阻会将输入拉高,位 4 将设置为1

所以我们有两种可能:

//Button is pressed
if(!(0000 0000 0000 0000))

或者:

//Button is not pressed
if(!(0000 0000 0001 0000))

现在重要的是要了解它!逻辑非运算符。在条件语句中反转true和。在C 语言false中理解这一点也很重要:

逻辑运算符(&&, ||,!等)和条件测试语句(if, while)假定零为假,所有其他值为真

强调我的

所以我们真正拥有的是:

//Button is pressed
if(!(false))

或者:

//Button is not pressed
if(!(true))

应用NOT:

//Button is pressed
if(true)
    Key=1;

或者:

//Button is not pressed
if(false)
    Key=1;
于 2013-11-07T14:27:46.660 回答
4
if(!(GPIOA->IDR & (1<<4))) Key=1;

相当于

if((GPIOA->IDR & (1<<4)) == 0) Key=1;

在 C 中,!E等价于E == 0

所以这里基本上,Key = 1;如果第 4 位的值为 ,则执行GPIOA->IDR语句0

于 2013-11-06T19:05:01.760 回答
1

假设 GPIOA->IDR 是一个字节。

[1111 1111] would infer that no GIPOA->IDR bits are cleared (grounded)
[1111 1111] & [0000 1000] = 0000 1000 => != 0
If the button was pressed...
[1111 0111] & [0000 1000] = 0000 0000 => == 0

鲍勃是你的叔叔。

于 2013-11-06T19:08:22.620 回答