【问题标题】:Set variable to access pic port设置变量以访问 pic 端口
【发布时间】:2013-10-15 07:54:14
【问题描述】:

我需要使用同一段代码来读取图片上不同引脚上的各种设备。 函数调用确定设备,即 设备 1 - 端口 A0 设备 2 - 端口 A1 等等

在我的代码中,我需要将端口更改为输入/输出、发送数据和接收数据。 所以,在伪代码中我需要这样做:

函数 readDevice(deviceNumber)

variableType myPortControlVariable;

variableType myPortVariable;

//选择我们要使用的设备端口和控件

如果(设备编号==1)

myPortControlVariable = TRISA0;

myPortVariable = RA0;

如果(设备编号==2)

myPortControlVariable = TRISA1;

myPortVariable = RA1;

等等……

...在函数代码中

myPortControlVariable = 0; //设置为输出

myPortVariable = 1; //写一个1

暂停 我的端口变量 = 0; //写一个0

等等……

有谁知道如何做到这一点? 谢谢

【问题讨论】:

    标签: port pic microchip


    【解决方案1】:
    1. 在几乎所有情况下,都不会在程序中间更改 PIC 引脚的输入/输出功能。通常,它们在程序开始时设置一次,并且再也不会被触及。此外,您如何确保 PIC 和外部设备不会同时驱动线路并烧毁某些东西?

    2. 在您的伪代码中,您正在读取输入/输出寄存器的状态。我无法想象这样做的原因。你是设置这种状态的人。而且这种状态不应该改变。所以你已经知道每个引脚的输入/输出值了。

    我不知道你想在你的伪代码中做什么,所以这就是我能给出的所有建议。试着用真实的代码来写。

    【讨论】:

    • 我会尝试更好地解释:我有 2 个单线传感器,一个连接到 A0,一个连接到 A1。我想使用相同的代码来读取每个传感器。我不想为两个传感器复制相同的代码,所以我希望能够根据我要访问的传感器确定要访问的端口。而不是很多: if device == 1 then A0 = 1 else A1 = 1 构造我想这样做一次以选择端口,将其分配给一个变量,然后使用该变量访问该端口。此外,要使用 1 线设备,您肯定必须更改引脚的输入/输出功能。
    • 啊,好多了。听起来您的外围设备使用 I2C 接口。你是对的,你可以切换针的方向来做到这一点。您也可以使用 PIC 上绑在一起的 2 个引脚。一组作为集电极开路驱动器,另一组用于感测线路。然后,您将使用一个电阻将该节点连接到高电平并将其连接到您的 I2C 外围设备的数据端口。或者,根据您的资源(即您使用的 PIC 处理器、您使用的编译器等),更好的解决方案是使用 PIC 的硬件和编译器目录中的 i2c.h 库。
    • 他说的是单线,而不是 I-squared-C。大概是指达拉斯 1-wire 协议,它与 I2C 完全不同
    • 我以为 i2c 是......哦,我明白了 - 你是说时钟和数据在一条线上......好吧,我们将不得不等待并从他那里找出......跨度>
    • 是的,我使用的是 Dallas 1 线 DS18B20。我最终复制了代码(我讨厌这样做,太浪费了),但没有看到一个干净的选项。在 if/then 构造中的函数开头设置一个变量然后使用该变量会容易得多。
    【解决方案2】:

    听起来您的外围设备使用 I2C 接口。

    让我们来看看 Microchip.com 可以提供什么。如果我们去这里: http://www.microchip.com/CodeExamplesByFunc.aspx

    我们可以搜索几个 I2C 代码示例。我们必须确切知道您使用哪个 PIC 才能找到最匹配的应用笔记。除非我们找到完全匹配的(PIC、编译器、库和您的物理设计),否则您将不得不进行调整。

    我选择了这个应用笔记: http://ww1.microchip.com/downloads/en/DeviceDoc/CE337%20I2C_MASTER.zip

    如果您下载、解压缩此包并打开 i2c_master.c 文件,您可以看到 microchip 如何使用 PIC 24Fxxxx 系列处理器和 C30 编译器文件中的 i2c 库进行通信。如果您最近将您的 PIC SDK 放在一起,您可能正在使用更新的 XC18 编译器。这也取决于您使用的是哪个 PIC(因此了解这一点很重要。否则,您只需对这些建议保持开放的心态。)。至于从 C30 切换到更新的 XC18 编译器,我认为代码仍然可以工作。但是,正如我所说,您可能需要做出调整。

    如果您仔细观察,您会发现程序中没有任何代码可以更改 PIC 的 I2C 数据线的方向。这是因为这是 xc18 编译器文件中的 i2c.h 库从您那里抽象出来的。此外,大多数 PIC 24Fxxxx 类芯片都有多个 I2C 模块。 PIC 中设计用于处理 I2C 接口和生成中断的硬件。使用内置硬件将允许您的代码在缓慢的 I2C 事务期间执行其他操作。

    总结:是的,您可以手动完成所有这些(我认为这就是您要去的地方)。但是,根据您使用的 PIC,它可以在大多数 PIC 处理器内置的硬件中更快地完成。

    注意:此示例(来自我正在谈论的 microchip.com)要求您使用 4.7K 电阻将在 PIC 和 I2C 外设之间运行的 I2C 时钟和 I2C 数据线拉高。此提醒已写入示例代码的 cmets - 只是为了您不会忘记!我认为这是因为 I2C 驱动程序(不是软件,而是处理器引脚后面的电子设备)属于“集电极开路”设计。

    苹果和橙子:如果您是 Arduino Uno 的粉丝,并且认为这太复杂了,请考虑一下 Arduino Uno 简单性的阴暗面:您会被 Arduino Uno 的本质所困扰。

    【讨论】:

      【解决方案3】:

      如果您使用在一条双向线路上集成时钟和数据的外设,那么我在此页面上看不到 microchip.com 示例: http://www.microchip.com/CodeExamplesByFunc.aspx

      但是如果你在网上搜索一下,你可能会找到很多例子。

      如果您只想在需要将 I/O 代码从硬件中抽象出来时编写它。无论您在哪里更改、设置或清除一个引脚,您都可以调用一个带有正式参数的方法,该参数描述您正在与哪个设备通话。然后,在该方法中,您将硬编码您想要操作的 PIN。听起来您想在 select/case 语句之类的东西中硬编码许多引脚。

      要专门解决您的伪代码...我认为我们需要查看 TRISA0 是如何定义的(此特定代码段来自 p24HJ128GP204.h 文件 - 还有许多其他文件可能来自哪个 PIC你正在使用):

      extern volatile unsigned int  TRISA __attribute__((__sfr__));
      typedef struct tagTRISABITS {
        unsigned TRISA0:1;
        unsigned TRISA1:1;
        unsigned TRISA2:1;
        unsigned TRISA3:1;
        unsigned TRISA4:1;
        unsigned :2;
        unsigned TRISA7:1;
        unsigned TRISA8:1;
        unsigned TRISA9:1;
        unsigned TRISA10:1;
      } TRISABITS;
      

      看来TRISA0是一个结构的一部分。不仅仅是可以分配给变量的值。它会出现在同一文件中的这一行:

      #define _TRISA0 TRISAbits.TRISA0
      

      您必须将引脚称为“_TRISA0”而不是“TRISA0”。

      【讨论】:

        【解决方案4】:

        很遗憾,您无法在 C 中传递位。请查看此常见问题解答以获取更多信息:http://www.xargs.com/pic/c-faq.html#pinarray

        因此,解决方法是将标志传递给 I/O 函数,以在最低级别触发开关或 if-else:

        void send_bit (char device,char value) {
            switch (device) {
                case DEVICE_1:
                    // output bit value to correct port
                    break;
                case DEVICE_2:
                    // output bit value to correct port
                    break;
            }
        }
        

        现在消除了丑陋,我们可以在它之上构建更简洁的代码:

        // The following is just a generic example, change bit order etc
        // to fit the protocol you're using.
        
        void send_byte (char device, char value) {
            char i;
            for (i=0;i<8;i++) {
                send_bit(device,(value >> i)&0x01);
            }
        }
        
        void send_message (char device, char address, char *buffer, char length) {
            char i;
            send_byte(device,address);
            for (i=0;i<length;i++) {
                send_byte(device,buffer[i]);
            }
        }
        

        关键是将丑陋只包含在一个地方 - 最低级别的 I/O 功能。然后在它之上构建更清晰的抽象。


        其他注意事项:

        如果您使用双向信号,则永远不应将输出位设置为 1。如果高值发生冲突,这样做可能会损坏 PIC 的输出缓冲区或其他设备的输出缓冲区。

        相反,双向信号通常通过连接上拉电阻的集电极开路电路实现。这样,设备通过拉低电压来传输 0,通过将输出设置为高阻抗来传输 1。因此,与 1-wire 设备通信的正确方法是将输出引脚硬编码为 0,并在输出模式(发送 0)和输入模式(发送 1)之间切换 TRIS 位。

        在某些设备上,少数 I/O 引脚可能内置弱上拉。如果您不想使用外部上拉电阻,您可以启用它,但根据我的经验,最好使用小型(4.7k?)外部上拉电阻,特别是如果两个芯片之间的距离很长(任何长于0.5 厘米?)。

        另一件需要考虑的事情是,您可以只使用一个引脚与两个设备进行通信,因为只有具有正确地址的设备才会响应您的 PIC。唯一的问题是大多数 1-wire 设备都有硬编码地址,所以如果您尝试与两个相同的设备通信,那么是的,您需要使用上述技巧在运行时切换引脚。

        【讨论】:

          【解决方案5】:

          您可以设置指向 LAT 寄存器的易失性指针数组,并使用要设置的位信息维护数组。我在 16 位 PIC 控制器上编写了这个

          http://www.microchip.com/forums/m794597.aspx

          这也可以应用于 TRIS 寄存器。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-08-04
            • 2012-07-21
            • 1970-01-01
            • 2017-02-20
            • 2012-04-16
            • 1970-01-01
            相关资源
            最近更新 更多