为什么将这些宏函数转换为函数不能正常工作?
Why turning these macro-functions to functions didn't work correctly?
我正在使用一些初始化和写入和读取端口或端口引脚的宏:
(而且效果很好)
/* GPIO port operations */
#define GPIO_InitPort(CONTROL, DIRECTION) ((CONTROL) = ((DIRECTION)? (~GPIO_OUT):(GPIO_OUT)))
#define GPIO_WritePort(PORT, DATA) ((PORT) = (DATA))
#define GPIO_ReadPort(PORT) (PORT)
/* GPIO port pin operations */
#define GPIO_InitPortPin(CONTROL, PIN, DIRECTION) ((CONTROL) = (CONTROL & (~(1 << PIN)))|(DIRECTION << PIN))
#define GPIO_WritePortPin(PORT, PIN, DATA) ((PORT) = (PORT & (~(1 << PIN)))|(DATA << PIN))
#define GPIO_ReadPortPin(PORT, PIN) (((PORT) & (1 << PIN)) >> (PIN))
然后,我想做一个GPIO模块,其功能实现如下:
void GPIO_InitPort(uint8 PortControl, uint8 PortDir){
PortControl = ((PortDir) ? (~GPIO_OUT) : (GPIO_OUT));
}
void GPIO_WritePort(uint8 PortData, uint8 PortLevel){
PortData = PortLevel;
}
uint8 GPIO_ReadPort(uint8 PortData){
return PortData;
}
void GPIO_InitPortPin(uint8 PortControl, uint8 Pin, uint8 PinDir){
PortControl &= ( ~(1<<Pin) | (PinDir<<Pin) );
}
uint8 GPIO_ReadPortPin(uint8 PortData, uint8 PinLevel){
return (( PortData & (1<<PinLevel) ) >> PinLevel);
}
void GPIO_WritePortPin(uint8 PortData, uint8 Pin, uint8 PinLevel){
PortData &= ( ~(1<<Pin) | (PinLevel<<Pin) );
}
不幸的是,这不起作用,尽管使用了相同的逻辑。
你需要了解指针。
示例:
void changeVar(int *var, int source)
{
*var = source;
}
int main()
{
int foobar;
changeVar(&foobar, 5);
return 0;
}
请记住,宏只是文本替换 - 宏参数不会求值,它们只是在原地展开。如果你写类似
GPIO_InitPort( foo, bar );
预处理器将其扩展为
((foo) = ((bar) ? (~GPIO_OUT) : (GPIO_OUT)));
函数参数,OTOH, 被 评估,评估的结果被传递给函数。请记住,C 使用按值传递语义 - 形式参数在内存中是与实际参数不同的对象,因此更新一个对另一个没有影响。如果调用 函数
GPIO_InitPort( foo, bar );
正式参数PortControl
在内存中与实际参数foo
是不同的对象,并且类似地,PortDir
是一个独立于 bar
的对象。写入 PortControl
对 foo
完全没有影响。
如果你想让一个函数写入调用者的实际参数,那么你必须传递一个指向那个参数的指针。所以 GPIO_InitPort
需要写成
void GPIO_InitPort( uint8 *PortControl, uint8 PortDir )
{
*PortControl = PortDir ? ~GPIO_OUT : GPIO_OUT;
}
并称为
GPIO_InitPort( &foo, bar );
我正在使用一些初始化和写入和读取端口或端口引脚的宏: (而且效果很好)
/* GPIO port operations */
#define GPIO_InitPort(CONTROL, DIRECTION) ((CONTROL) = ((DIRECTION)? (~GPIO_OUT):(GPIO_OUT)))
#define GPIO_WritePort(PORT, DATA) ((PORT) = (DATA))
#define GPIO_ReadPort(PORT) (PORT)
/* GPIO port pin operations */
#define GPIO_InitPortPin(CONTROL, PIN, DIRECTION) ((CONTROL) = (CONTROL & (~(1 << PIN)))|(DIRECTION << PIN))
#define GPIO_WritePortPin(PORT, PIN, DATA) ((PORT) = (PORT & (~(1 << PIN)))|(DATA << PIN))
#define GPIO_ReadPortPin(PORT, PIN) (((PORT) & (1 << PIN)) >> (PIN))
然后,我想做一个GPIO模块,其功能实现如下:
void GPIO_InitPort(uint8 PortControl, uint8 PortDir){
PortControl = ((PortDir) ? (~GPIO_OUT) : (GPIO_OUT));
}
void GPIO_WritePort(uint8 PortData, uint8 PortLevel){
PortData = PortLevel;
}
uint8 GPIO_ReadPort(uint8 PortData){
return PortData;
}
void GPIO_InitPortPin(uint8 PortControl, uint8 Pin, uint8 PinDir){
PortControl &= ( ~(1<<Pin) | (PinDir<<Pin) );
}
uint8 GPIO_ReadPortPin(uint8 PortData, uint8 PinLevel){
return (( PortData & (1<<PinLevel) ) >> PinLevel);
}
void GPIO_WritePortPin(uint8 PortData, uint8 Pin, uint8 PinLevel){
PortData &= ( ~(1<<Pin) | (PinLevel<<Pin) );
}
不幸的是,这不起作用,尽管使用了相同的逻辑。
你需要了解指针。
示例:
void changeVar(int *var, int source)
{
*var = source;
}
int main()
{
int foobar;
changeVar(&foobar, 5);
return 0;
}
请记住,宏只是文本替换 - 宏参数不会求值,它们只是在原地展开。如果你写类似
GPIO_InitPort( foo, bar );
预处理器将其扩展为
((foo) = ((bar) ? (~GPIO_OUT) : (GPIO_OUT)));
函数参数,OTOH, 被 评估,评估的结果被传递给函数。请记住,C 使用按值传递语义 - 形式参数在内存中是与实际参数不同的对象,因此更新一个对另一个没有影响。如果调用 函数
GPIO_InitPort( foo, bar );
正式参数PortControl
在内存中与实际参数foo
是不同的对象,并且类似地,PortDir
是一个独立于 bar
的对象。写入 PortControl
对 foo
完全没有影响。
如果你想让一个函数写入调用者的实际参数,那么你必须传递一个指向那个参数的指针。所以 GPIO_InitPort
需要写成
void GPIO_InitPort( uint8 *PortControl, uint8 PortDir )
{
*PortControl = PortDir ? ~GPIO_OUT : GPIO_OUT;
}
并称为
GPIO_InitPort( &foo, bar );