我的工作一些代码,impliments各种特征,诸如PID控制器,信号发生器等
我的硬件提供的各种输入和输出。 刚才我已经switch语句的负载,以确定我的计算的源和目标。
例如用于PID控制器,有一个开关命令每一个决定哪个输入100ms的传递给pid_calculate功能,接着另一个开关来决定如何处理返回值做。 正如我有32个模拟输入,以及CAN,LIN和串行尽可能输入,开关语句是巨大的!
我想参考,或某物可如何被编码为一个独立于硬件的功能(PIC的范围内)的物理实例。 我相信,答案就在指针上,但我是新来的C和真的不知道哪里有指针开始。
我设想的函数原型是类似INT pid_init(*源,*目的地),其中源是一个指针到输入端,例如一个ADC缓冲液,并且目的地可以是例如PWM占空比寄存器。 刚才我到数据切换每个可能的条件,那么加载到寄存器中。
因此,要澄清,我怎么会impliment一个功能,使得它可以输入和输出独立,并且我将如何去参考指针(假设指针是这样做的正确方法)
我希望这是有道理的,在此先感谢。
只要你采取一些照顾你可以实现一种用C的面向对象编程的。 在我做它的方式,我已经使用函数指针以及结构与功能的指针作为成员。
例如有一种数据独立性的,你可能有喜欢的一个功能, 快速排序(快速排序)功能提供的数据长着一个指针,它指向的数据进行操作的功能。 通常用这种方法,你最终会使用各种空指针允许使用指针的任何数据类型。
我已经使用另一种方法是有什么相当于一个抽象的接口,用于各种类型的设备的支持,并再创建一个结构提供了这些操作的函数指针模板中的常用操作。 然后,我将创建这些结构的数组,并通过使用函数指针对实现该操作的特定设备的特定功能填写数组元素。
例如像这样很简单的例子是我用几个不同的设备提供了一个标准接口。 这个接口隐藏通过提供一个标准的接口的设备的差别。
// 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);
}
您仍然需要实现用于各个然而,这提供了一种有一个标准接口,以便与您可以就用你的代码的其余部分中的标准接口,常用的操作多台设备的设备的实际功能。
我已经使用这个提供一个标准的接口输出,输出设备是一个普通文件,打印机和网络服务。 实际的信宿或输出装置是由用户选择。 使用该接口的代码并没有改变。 添加更多的设备是很容易,只要接口并没有改变。 在某些情况下,我有一个不支持特定的操作设备和功能将只返回没有做任何事情。
My personal favorite is to use macros. They are simple and they always work on all compilers.
Say for example you have some function that does something generic (PID in your case) but operates on hardware specific registers and/or memory locations. Just define the hardware specific part as a macro that you put in a hardware specific header file. Then, when you compile the code you can choose which macro to use (if you notice, that's what PIC compilers do anyway with hardware specific register addresses).
Example:
do_something.c
void do_something () {
MY_OUTPUT = complex_operation(MY_INPUT);
}
dev_board_16f877.h
#define MY_INPUT PORTB
#define MY_OUTPUT PORTD
production_board_version_1_0.h (alternative header)
#define MY_INPUT PORTC
#define MY_OUTPUT PORTD
Better yet, you should even abstract out I/O operations away as functions rather than variable assignments because most other CPUs can't do that. Again, this can simply be done in a hardware specific header file or hardware specific C file that you choose during the compile phase.
BTW, this is also how the Linux kernel does it - separate the algorithm from the hardware specific stuff.