我需要使用同一段代码从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
等...
有谁知道如何实现这一目标? 感谢
答案 0 :(得分:0)
在几乎所有情况下,都不会在程序中间更改PIC引脚的输入/输出功能。通常它们在程序开始时设置一次,从不再次触摸。此外,您如何确保PIC和外部设备不会同时驱动线路并烧掉一些东西?
在伪代码中,您正在读取输入/输出寄存器的状态。我无法想象这样做的原因。你是设置这种状态的人。这种状态不应该改变。所以你已经知道每个引脚的输入/输出值。
我无法告诉您在伪代码中想要做什么,这就是我可以给出的所有建议。尝试使用真实代码来编写它。
答案 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寄存器。