为什么用 void 关键字调用函数没有效果?

Why no effect of calling functions with void keyword?

我需要编写非常简单的程序,使用处理器 ARM AT91SAM9263 使 LED 二极管闪烁。我需要使用 QEMU 模拟器 运行 这段代码,它安装在我的 Ubuntu 机器上。 我正在尝试编写一个具有 4 个功能的程序,它们正在初始化 LED 端口和按钮端口,它们正在闪烁 LED 二极管并检查按钮状态(是否被拉动)。
我已经定义了基址寄存器,尽管我在制作 LED 二极管来切换它们 on/off 和检查按钮状态时遇到了问题。很简单,什么也没有发生。 下面是我的代码:

#include <stdio.h>
#include "AT91SAM9263-EK.h"
#include "AT91SAM9263.h"
#include "project.h"
#include <stdint.h>
#include <stdbool.h>
#define AT91B_LED1     AT91C_PIO_PB8   /* DS1 */
#define AT91B_LED2    AT91C_PIO_PC29  /* DS2 */
#define AT91B_NB_LEB         2
#define AT91D_BASE_PIO_LED1  (AT91C_BASE_PIOB)
#define AT91D_BASE_PIO_LED2  (AT91C_BASE_PIOC)
#define AT91D_ID_PIO_LED1    (AT91C_ID_PIOB)
#define AT91D_ID_PIO_LED2    (AT91C_ID_PIOC)
#define AT91B_BP1       AT91C_PIO_PC5  // Left click#
#define AT91B_BP2       AT91C_PIO_PC4  // Right click
#define AT91D_BASE_PIO_BP    AT91C_BASE_PIOC
#define AT91D_ID_PIO_BP      AT91C_ID_PIOCDE

void LedPortInit()
{
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOCDE ); // peripheral clock enable register (port C, D, E)/* Set the PIO line as input */
AT91D_BASE_PIO_LED1->PIO_ODR = 0x0000000F;
AT91D_BASE_PIO_LED1->PIO_PER = AT91C_PIO_PB8;
AT91D_BASE_PIO_LED2->PIO_OER = AT91C_PIO_PC29 ;
AT91D_BASE_PIO_LED2->PIO_PER = 0xFFFFFFFF;// 1 – Enable PIO to control the pin
AT91C_BASE_PIOE->PIO_PER = AT91C_PIO_PB31;/* Disable pull-up */
AT91C_BASE_PIOA->PIO_PPUDR = 0xFFFF0000;
}
void ButonPortInit()
{
  AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOCDE ); // peripheral clock enable register (port C, D, E)/* Set the PIO line as input */
  AT91C_BASE_PIOD->PIO_ODR = 0x0000000F;
  AT91C_BASE_PIOD->PIO_PER = AT91C_PIO_PC5;
  AT91C_BASE_PIOB->PIO_OER = AT91C_PIO_PC4 ;
  AT91C_BASE_PIOD->PIO_PER = 0xFFFFFFFF;// 1 – Enable PIO to control the pin
  AT91C_BASE_PIOE->PIO_PER = AT91C_PIO_PB31;/* Disable pull-up */
  AT91C_BASE_PIOA->PIO_PPUDR = 0xFFFF0000;
}
void LedSwitch()
{

while(1)
{
  AT91B_LED1->AT91C_PIO_PB8  ^= 1;
}
AT91C_PIO_PC29  << 29 ;

}
void ButtonTest()
{
AT91C_PIO_PC5  << 5;
AT91C_PIO_PC4  << 4;
}
int main(void)
{
LedPortInit();
void ButonPortInit();
void LedSwitch();
void ButtonTest();

}

这些行被编译器误认为是原型,即没有运行时影响的函数声明:

void ButonPortInit();
void LedSwitch();
void ButtonTest();

将它们变成这样的函数调用:

ButonPortInit();
LedSwitch();
ButtonTest();

为了演示,我为这个 MRE 提供了更少的环境特定和嵌入式内容。问题和解决方法一样。

#include <stdio.h>

void test1()
{   printf("test 1!\n");}
void test2()
{   printf("test 2!\n");}

int main()
{
    printf("Hello, World!\n");
    
    void test1();
    test2();

    return 0;
}

输出:

Hello, World!
test 2!

您可以在问题描述中看到,“很简单,没有任何反应。”对于 void test1(); 但是 test2();.

有一个输出

请注意,函数名称后面使用的关键字指的是 return 值类型。

但是这里你只想调用函数,这个操作不属于 return 值类型(我的意思只是调用)。

所以只需使用:

ButonPortInit(); LedSwitch(); ButtonTest();

Why no effect of calling functions with void keyword?

void ButonPortInit();
void LedSwitch();
void ButtonTest();

因为这些不是函数调用。这种形式的表达式是函数原型。要将它们变成函数调用,您需要删除 void 关键字。

然而,

(void) ButonPortInit();

是一个有效的函数调用。 (void) 在这种情况下不是 return 类型,而是类型转换运算符。意思是将ButtonPortInit()的return值转换为void。它通常用于明确指定应丢弃函数的 return 值。

extern void x ( unsigned int );
void one ( void )
{
    x(1);
}
void two ( void )
{
    x(2);
}
int test0 ( void )
{
    void one();
    void two();
    return(0);
}
int test1 ( void )
{
    one();
    two();
    return(0);
}


Disassembly of section .text:

00000000 <one>:
   0:   e92d4010    push    {r4, lr}
   4:   e3a00001    mov r0, #1
   8:   ebfffffe    bl  0 <x>
   c:   e8bd4010    pop {r4, lr}
  10:   e12fff1e    bx  lr

00000014 <two>:
  14:   e92d4010    push    {r4, lr}
  18:   e3a00002    mov r0, #2
  1c:   ebfffffe    bl  0 <x>
  20:   e8bd4010    pop {r4, lr}
  24:   e12fff1e    bx  lr

00000028 <test0>:
  28:   e3a00000    mov r0, #0
  2c:   e12fff1e    bx  lr

00000030 <test1>:
  30:   e92d4010    push    {r4, lr}
  34:   e3a00001    mov r0, #1
  38:   ebfffffe    bl  0 <x>
  3c:   e3a00002    mov r0, #2
  40:   ebfffffe    bl  0 <x>
  44:   e3a00000    mov r0, #0
  48:   e8bd4010    pop {r4, lr}
  4c:   e12fff1e    bx  lr

我找到了完整的解决方案,我只需要激活额外的寄存器 PIO_SODR 和 PIO_CODR,如下所示:

void LED1_SwitchOn(){
    *PIOB_CODR = AT91B_LED1;
}

void LED2_SwitchOn(){
    *PIOC_CODR = AT91B_LED2;
}

void LED1_SwitchOff(){
    *PIOB_SODR = AT91B_LED1;
}

void LED2_SwitchOff(){
    *PIOC_SODR = AT91B_LED2;
}

int BP1_Status(){
    return  (((*PIOC_PDSR) >> BP1 ) & 1);
}

int BP2_Status(){
    return  (((*PIOC_PDSR) >> BP2 ) & 1);
}

void delay(long long int time_delay){
    for (volatile long long int i = 0; i < 100000 * time_delay; i++);
}

int main(void) {
    LED1Port_Init();
    LED2Port_Init();
    enable_PMC();
    Button1Port_Init();
    Button2Port_Init();
  long long int time_delay=0;
    while (1)
    {

        LED1_SwitchOn();

        for (volatile long long int i = 0; i < DELAY; i++)
        {

            if (BP1_Status() == 0) //button1 switches on diode
                LED2_SwitchOn();
        delay(time_delay);
            if (BP2_Status() == 0) //button2 switches off diode
                LED2_SwitchOff();

        }

        LED1_SwitchOff();
    }


    return 0;
}