设置变量以访问pic端口

时间:2013-10-15 07:54:14

标签: port pic microchip

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

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

function readDevice(deviceNumber)

variableType myPortControlVariable;

variableType myPortVariable;

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

如果(deviceNumber == 1)

myPortControlVariable = TRISA0;

myPortVariable = RA0;

如果(deviceNumber == 2)

myPortControlVariable = TRISA1;

myPortVariable = RA1;

等...

...在功能代码中

myPortControlVariable = 0; //设置为输出

myPortVariable = 1; //写一个

暂停   myPortVariable = 0; //写一个0

等...

有谁知道如何实现这一目标? 感谢

5 个答案:

答案 0 :(得分:0)

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

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

  3. 我无法告诉您在伪代码中想要做什么,这就是我可以给出的所有建议。尝试使用真实代码来编写它。

答案 1 :(得分:0)

听起来您的外设使用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文件,您可以看到微芯片如何使用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数据线。此提醒将写入示例代码的注释中 - 这样您就不会忘记!我认为这是因为I2C驱动程序(不是软件,而是处理器引脚后面的电子设备)是“开放式集电极”设计。

苹果和橘子:如果你是Arduino Uno的粉丝并且认为这太复杂了,那么考虑一下Arduino Uno简单的黑暗面:你完全被Arduino Uno所困扰。

答案 2 :(得分:0)

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

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

如果您只想在硬件上对其进行抽象,那么只需要编写I / O代码。你改变,设置或清除一个引脚,你可以调用一个方法,用一个正式的参数来描述你正在与之交谈的设备。然后,在该方法中,您将硬编码您想要操作的PIN。听起来你想要像select / case语句那样对许多引脚进行硬编码。

专门解决你的伪代码......我想我们需要看看如何定义TRISA0(这个特定的代码段来自p24HJ128GP204.h文件 - 还有很多其他文件可能来自哪个PIC取决于哪个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”。

答案 3 :(得分:0)

不幸的是,您无法在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线设备通信的正确方法是将输出引脚硬编码为0,并在输出模式(发送0)和输入模式(发送1)之间切换TRIS位。

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

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

答案 4 :(得分:0)

您可以设置一个指向LAT寄存器的易失性指针数组,并使用要设置的位的信息维护数组。我在

上写了16位PIC控制器

请参阅http://www.microchip.com/forums/m794597.aspx

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