.NET Micro Framework 和.NET Compact Framework不同,并不是.NET Framework的子集,而是更贴近硬件底层,它提供了许多诸如GPIO、PWM、SPI、I2C和OneWire等硬件操作类库。由此可以让普通的软件开发人员相对平滑的过度到硬件开发领域,也足以让以前相对封闭的硬件系统通过二次开发的方式扩展硬件模块成为一种流行(随着物联网技术的深入发展,未来软件不仅需要组态化,硬件其实更需要组态化)。
如下是.NET Micro Framework的I2C接口类库:
public class I2CDevice : IDisposable
{
public I2CDevice.ConfigurationConfig;
protectedbool m_disposed;
publicI2CDevice(I2CDevice.Configurationconfig);
public static I2CDevice.I2CReadTransaction CreateReadTransaction(byte[] buffer);
public static I2CDevice.I2CWriteTransaction CreateWriteTransaction(byte[] buffer);
public void Dispose();
public int Execute(I2CDevice.I2CTransaction[] xActions, int timeout);
public class Configuration
{
publicreadonly ushortAddress;
publicreadonly intClockRateKhz;
publicConfiguration(ushort address, int clockRateKhz);
}
public sealed class I2CReadTransaction : I2CDevice.I2CTransaction{}
public class I2CTransaction
publicreadonly byte[]Buffer;
protectedI2CTransaction(byte[] buffer);
}
public sealed class I2CWriteTransaction : I2CDevice.I2CTransaction{}
}
I2C的读写操作通过定义I2CDevice.I2CTransaction数组,可以实现批量操作。
PCF8591芯片是8位A/D和D/A转换器,4路模拟输入,1路模拟输出。其I2C地址是可以进行硬件编码的(3个地址引脚A0、A1和A2),其地址编码规则如下:
固定部分
编码部分
1
A2
A1
A0
R/W
最高位 最低位
对I2C来说,一般读操作的时候地址的最低位为1,写操作的时候地址的最低位为0。我们选用的模块,看原理图可知,A2、A1和A0管脚都被直接连接到GND,所以这部分都是0,所以对读地址来说是0x91,写地址是0x90。.NET Micro Framework底层I2C驱动实现的时候,地址会自动左移,最低位是不算地址的一部分的(所以才说是7位地址支持),所以我们在填写I2C模块地址的时候,要填写的是读地址(或写地址)右移一位的数字,也就是0x48。
总线频率我们理论上可以选择10K到400K,这里我们选择100K。
下面我们详细介绍一下PCF8591是如何进行AD读取和DA输出的。
读AD操作:
写操作
读操作
地址
控制字
AD数据
写DA操作
DA数据
控制字的定义如下:
X
DA标志
模拟输入模式
自动增量
通道号:0~3
对AD0~AD3通道来说,我们常用的控制字的值为0x0,0x1,0x2,0x3。
对DA来说,我们常用的控制字的值为0x40。
注意:如果我们循环读取AD0至AD3,由于读周期读取的AD转换值,其实是上一次的转换结果,所以我们读取AD1的时候,其实是读取的AD0,依次类推(上电第一次读取的值是0x80)。
有了以上知识,我们就可以进行编程了,核心代码如下:
public static void Main()
{
I2CDeviceI2CBus = new I2CDevice(new I2CDevice.Configuration(0x48, 100));
byte[]bytAD = new byte[4];
bytebytDA = 0;
while(true)
{
for(byte i = 0; i < 4; i++)
{
byte[]bytWData = new byte[1]{ i };
byte[]bytRData = new byte[1];
I2CDevice.I2CTransaction[] i2c = newI2CDevice.I2CTransaction[2];
i2c[0] = I2CDevice.CreateWriteTransaction(bytWData);
i2c[1] = I2CDevice.CreateReadTransaction(bytRData);
I2CBus.Execute(i2c, 100);
bytAD[i - 1 < 0 ? 3 : i- 1] = bytRData[0];
}
Debug.Print("AD0=" + ShowData(bytAD[0]) + " AD1=" + ShowData(bytAD[1]) + " AD2=" + ShowData(bytAD[2]) + " AD3=" + ShowData(bytAD[3]));
byte[]bytWData1 = new byte[2]{ 0x40, bytDA };
I2CDevice.I2CTransaction[] i2c1 = newI2CDevice.I2CTransaction[1];
i2c1[0] = I2CDevice.CreateWriteTransaction(bytWData1);
I2CBus.Execute(i2c1, 100);
Debug.Print("DA0=" + ShowData(bytDA));
bytDA += 10;
Thread.Sleep(1000);
}
通过旋转模块的上的模拟开关,我们会发现AD3的值可以由0向255变化。
----------------------------------------------------
<a href="http://weibo.com/1804832611?s=6uyXnP"></a>