为什么用 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;
}
我需要编写非常简单的程序,使用处理器 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;
}