我正在编写一些代码,这些代码实现了各种功能,如PID控制器、信号发生器等。
我的硬件提供了各种输入和输出。刚才我使用了大量的SWITCH语句来确定我的计算源和目标。
例如,对于PID控制器,每隔100ms就有一个开关命令,它决定将哪个输入传递给pid_calculate函数,然后是另一个开关,它决定如何处理返回值。由于我有32个模拟输入,以及can、lin和serial作为可能的输入,所以switch语句非常庞大!
我想引用一些东西如何被编码为硬件独立(在pic的范围内)的物理示例。我确信答案在于指针,但我是个C新手,不确定从哪里开始使用指针。
我设想的函数原型类似于int pid_init(* source,* destination ),其中源是指向输入的指针,例如模数转换缓冲器,目标可以是脉宽调制占空比寄存器。刚才,我必须切换每个可能的条件,然后将数据加载到寄存器中。
因此,为了澄清,我如何实现一个允许它独立于输入和输出的函数,以及如何解除对指针的引用(假设指针是实现这一点的正确方法)
我希望这是有意义的,提前谢谢。
发布于 2012-08-07 11:59:49
只要你细心一点,你就可以用C实现一种面向对象的编程。在我使用函数指针的方式中,我使用了函数指针以及带有函数指针的结构作为成员。
例如,为了具有某种数据独立性,您可能会有一个函数,就像quick sort (qsort) function一样,它为data long提供了一个指向对数据进行操作的函数的指针。通常,使用这种方法,您最终会使用各种空指针,以允许使用指向任何数据类型的指针。
我使用的另一种方法是为各种类型的设备支持的公共操作提供一个抽象接口,然后创建一个结构,该结构为这些操作提供一个函数指针模板。然后,我将创建这些结构的数组,并通过使用指向特定函数的函数指针来填充数组元素,该函数为特定设备实现该操作。
例如,这个非常简单的例子就是我用来为几种不同的设备提供标准接口的东西。此接口通过提供标准接口来隐藏设备差异。
// I create a struct that specifies what the function
// interface looks like for each of these operations for the
// devices that we are supporting.
typedef struct {
int (*pInput)(int iValue);
char *(*pName) (void);
int (*pDance) (int iTune, char *aszName);
} HardwareInterface;
// next I provide the function prototypes for the various devices.
// we have two different devices, Device_01 and Device_02 which
// have a common set of operations with the same interface.
int Device_01_Input (int iValue);
char *Device_01_Name (void);
int Device_01_Dance (int iTune, char *aszName);
int Device_02_Input (int iValue);
char *Device_02_Name (void);
int Device_02_Dance (int iTune, char *aszName);
// now I define my array of the device operation interfaces.
// this is where I provide the link between a specific operation
// on a specific device. I will number my devices beginning with
// zero to the number of devices supported minus one.
HardwareInterface HardwareList [] = {
{Device_01_Input, Device_01_Name, Device_01_Dance},
{Device_02_Input, Device_02_Name, Device_02_Dance},
};在这一点上,我可以调用一个函数来获取我实际想要使用的设备。此函数用于返回硬件列表中的索引。所以它可能是这样的。
int DeviceStdInput (int iValue)
{
int i = GetDeviceType ();
return HardwareList[i].pInput (iValue);
}或者我可以使用句柄方法,这样我就可以调用一个函数,该函数提供某个设备的句柄,该设备在传递给该函数的某个描述中指定。然后,对我的标准接口的任何调用都将指定句柄。在下面,句柄仅仅是不同设备数组的索引。
{
int iHandle = GetDeviceHandle ("Device_01");
int iXvalue = DeviceStdInput (iHandle, iValue);
}函数DeviceStdInput()将如下所示:
int DeviceStdInput (int iHandle, int iValue)
{
return HardwareList[iHandle].pInput (iValue);
}您仍然需要实现每个设备所使用的实际功能,但是这提供了一种方法,可以使用具有公共操作的多个设备的标准接口,然后只需在其余代码中使用标准接口即可。
我已经使用它为输出提供了一个标准接口,其中的输出设备是文件、打印机和web服务。实际的接收器或输出设备由用户选择。使用该接口的代码没有更改。只要界面不变,添加更多的设备就非常容易。在某些情况下,我会有不支持特定操作的设备,该函数将返回而不执行任何操作。
发布于 2012-08-07 13:05:21
我个人最喜欢的是使用宏。它们很简单,而且总是可以在所有编译器上运行。
比方说,你有一些函数做一些通用的事情(在你的例子中是PID),但是在硬件特定的寄存器和/或内存位置上操作。只需将硬件特定部分定义为放入特定于硬件的头文件中的宏即可。然后,当您编译代码时,您可以选择使用哪个宏(如果您注意到了,这就是PIC编译器对硬件特定寄存器地址所做的任何事情)。
示例:
do_something.c
void do_something () {
MY_OUTPUT = complex_operation(MY_INPUT);
}dev_board_16f877.h
#define MY_INPUT PORTB
#define MY_OUTPUT PORTDproduction_board_version_1_0.h (备用报头)
#define MY_INPUT PORTC
#define MY_OUTPUT PORTD更好的是,您甚至应该将I/O操作抽象为函数,而不是变量赋值,因为大多数其他CPU无法做到这一点。同样,这可以在编译阶段选择的特定于硬件的头文件或特定于硬件的C文件中简单地完成。
顺便说一句,这也是Linux内核如何做到这一点的-将算法与硬件相关的东西分开。
https://stackoverflow.com/questions/11821115
复制相似问题