【问题标题】:How can I write hardware independent functions in C for the PIC24如何在 C 中为 PIC24 编写独立于硬件的函数
【发布时间】:2012-08-05 23:51:55
【问题描述】:

我正在编写一些代码来实现各种功能,例如 PID 控制器、信号发生器等。

我的硬件提供各种输入和输出。刚才我有一个 SWITCH 语句来确定我的计算的来源和目的地。

例如对于 PID 控制器,每 100 毫秒有一个 switch 命令来决定将哪个输入传递给 pid_calculate 函数,然后是另一个 switch 来决定如何处理返回值。由于我有 32 个模拟输入,以及可能的输入,can、lin 和 serial,switch 语句是巨大的!

我想参考一个物理示例,说明如何将某些东西编码为独立于硬件(在图片范围内)的功能。我确信答案在于指针,但我是 C 新手,不太确定从哪里开始使用指针。

我设想函数原型类似于 int pid_init(*源,*目的地) 其中源是指向输入的指针,例如 ADC 缓冲器,而目标可以是例如 pwm 占空比寄存器。刚才我必须切换每个可能的条件,然后将数据加载到寄存器中。

所以要澄清一下,我将如何实现一个允许它独立输入和输出的函数,以及我将如何取消引用指针(假设指针是这样做的正确方法)

我希望这是有道理的,在此先感谢。

【问题讨论】:

  • 两个开关的条件是什么?你能把这些语句的代码贴出来吗(只是少数情况,不是全部)
  • 你不需要学习 C 技术,你需要学习面向对象编程,然后学习如何在 C 中实现这样的范例。
  • 嗨 claudix,我目前在我的 ipad 上,所以代码格式无法正常工作,但我会尝试
  • 嗨 claudix,我目前在我的 ipad 上,所以代码格式无法正常工作,但我会尝试。 Switch(input){case 0: // 模拟 pid_out=pid_calculate(adc[0])break;....case 41: // from canpid_out=pid_calculate(can_position)break;....}
  • 我已经使用 oop 10 年了,我只是不是一个 c 程序员,我收到了一个需要使用 c30 编写并在指定硬件中运行的项目。如果我可以选择环境,这将不是问题。

标签: c function pic microchip


【解决方案1】:

只要你小心一点,你就可以用 C 实现一种面向对象的编程。在我所做的方式中,我使用了函数指针以及以函数指针作为成员的结构。

例如,为了具有一种数据独立性,您可能有一个函数,如quick sort (qsort) function,它提供了一个长数据,并带有一个指向对数据进行操作的函数的指针。通常使用这种方法,您最终会使用各种类型的 void 指针来允许使用指向任何数据类型的指针。

我使用的另一种方法是为各种类型的设备支持的常见操作创建一个抽象接口,然后创建一个为这些操作提供函数指针模板的结构。然后,我将创建一个由这些结构组成的数组,并通过使用指向为特定设备实现该操作的特定函数的函数指针填充数组元素。

例如,像这个非常简单的例子是我用来为几种不同设备提供标准接口的东西。该接口通过提供标准接口隐藏了设备差异。

// 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 服务。实际的接收器或输出设备由用户选择。使用接口的代码没有改变。只要界面没有改变,添加更多设备就很容易了。在某些情况下,我的设备不支持特定操作,并且该功能会直接返回而无需执行任何操作。

【讨论】:

    【解决方案2】:

    我个人最喜欢的是使用宏。它们很简单,并且始终适用于所有编译器。

    例如,假设您有一些功能可以做一些通用的事情(在您的情况下是 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 PORTD
    

    production_board_version_1_0.h(替代标题)

    #define MY_INPUT  PORTC
    #define MY_OUTPUT PORTD
    

    更好的是,您甚至应该将 I/O 操作抽象为函数而不是变量赋值,因为大多数其他 CPU 无法做到这一点。同样,这可以简单地在您在编译阶段选择的硬件特定头文件或硬件特定 C 文件中完成。

    顺便说一句,这也是 Linux 内核的做法 - 将算法与硬件特定的东西分开。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-10
      • 2010-10-01
      • 2013-09-27
      • 1970-01-01
      相关资源
      最近更新 更多