【问题标题】:Why no effect of calling functions with void keyword?为什么用 void 关键字调用函数没有效果?
【发布时间】:2021-04-02 08:38:26
【问题描述】:

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

#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();

}

【问题讨论】:

    标签: c ubuntu arm qemu atmel


    【解决方案1】:

    我找到了完整的解决方案,我只需要激活额外的寄存器 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;
    }
    

    【讨论】:

      【解决方案2】:
      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
      

      【讨论】:

        【解决方案3】:

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

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

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

        然而,

        (void) ButonPortInit();
        

        是一个有效的函数调用。 (void) 在这种情况下不是返回类型,而是类型转换运算符。这意味着将ButtonPortInit()的返回值转换为void。它通常用于显式指定函数的返回值应该被丢弃。

        【讨论】:

          【解决方案4】:

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

          但是这里你只是想调用函数,这个操作与返回值类型无关(我的意思是调用)。

          所以只需使用:

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

          【讨论】:

            【解决方案5】:

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

            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(); 的输出。

            【讨论】:

            • 感谢您注意到这个简单的错误,但我的问题更多的是关于 '''LedSwitch();''' 和 ''' ButtonTest();''' 函数。我正在尝试打开/关闭 LED 并检查按钮状态,但我不确定我是否做得对。
            • 我相信您尝试做的事情会失败,因为您的代码没有调用函数 'LedSwitch();ButtonTest(); 并且它没有这样做是因为 void 在每种情况下都会阻止它。删除 void 会更改代码,以便它真正调用函数。我展示的代码证明了这一点。 test1() 没有被调用,因为之前的 voidtest2() 被调用,因为它没有 void。请尝试使用我的代码。在实验中添加和删除void。然后将您学到的知识应用到您自己的代码中。然后报告发生了什么。
            • 是的,我在我的代码中改变了那个错误,两个第一个函数正在工作,期待'LedSwitch();'和 'ButtonTest();'因为它们里面有问题
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-15
            • 1970-01-01
            • 2019-07-21
            • 2015-08-05
            • 2013-02-16
            • 2011-08-28
            相关资源
            最近更新 更多