spi.cs
来自「This is a Windows CE 6.0 Board Support P」· CS 代码 · 共 357 行
CS
357 行
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Gumstix;
using OpenNETCF.IO;
namespace Gumstix
{
public class SPI : StreamInterfaceDriver
{
#region SPI device IOCTL codes
private const Int32 FILE_DEVICE_BUS_EXTENDER = 0x0000002a;
private const Int32 FILE_ANY_ACCESS = 0x0;
private const Int32 METHOD_BUFFERED = 0x0;
private const Int32 CODE_IOCTL_RESET = 3000; // Reset
private const Int32 CODE_IOCTL_EXCHANGE = 3001; // Exchange data
private const Int32 CODE_IOCTL_SET_MODE = 3002; // Set mode
private const Int32 CODE_IOCTL_GET_MODE = 3003; // Get mode
private const Int32 CODE_IOCTL_ENABLE_LOOPBACK = 3004; // Enable loopback
private const Int32 CODE_IOCTL_DISABLE_LOOPBACK = 3005; // Disable loopback
private const Int32 CODE_IOCTL_SET_BUS_SPEED_MASK = 3006; // Set bus speed
private const Int32 CODE_IOCTL_GET_BUS_SPEED_MASK = 3007; // Get bus speed
private const Int32 IOCTL_RESET =
((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
| ((CODE_IOCTL_RESET) << 2) | (METHOD_BUFFERED);
private const Int32 IOCTL_EXCHANGE =
((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
| ((CODE_IOCTL_EXCHANGE) << 2) | (METHOD_BUFFERED);
private const Int32 IOCTL_SET_MODE =
((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
| ((CODE_IOCTL_SET_MODE) << 2) | (METHOD_BUFFERED);
private const Int32 IOCTL_GET_MODE =
((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
| ((CODE_IOCTL_GET_MODE) << 2) | (METHOD_BUFFERED);
private const Int32 IOCTL_ENABLE_LOOPBACK =
((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
| ((CODE_IOCTL_ENABLE_LOOPBACK) << 2) | (METHOD_BUFFERED);
private const Int32 IOCTL_DISABLE_LOOPBACK =
((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
| ((CODE_IOCTL_DISABLE_LOOPBACK) << 2) | (METHOD_BUFFERED);
private const Int32 IOCTL_SET_BUS_SPEED_MASK =
((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
| ((CODE_IOCTL_SET_BUS_SPEED_MASK) << 2) | (METHOD_BUFFERED);
private const Int32 IOCTL_GET_BUS_SPEED_MASK =
((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
| ((CODE_IOCTL_GET_BUS_SPEED_MASK) << 2) | (METHOD_BUFFERED);
#endregion
#region Native interface structures
[StructLayout(LayoutKind.Sequential)]
private struct BusConfig
{
public bool pol;
public bool pha;
public UInt32 bitcount;
public UInt32 rsvd1;
public UInt32 rsvd2;
public BusConfig(bool pol, bool pha, UInt32 bitcount)
{
this.pol = pol;
this.pha = pha;
this.bitcount = bitcount;
this.rsvd1 = 0;
this.rsvd2 = 0;
}
}
[StructLayout(LayoutKind.Sequential)]
private struct Packet
{
public IntPtr busConfig;
public IntPtr txBuffer;
public IntPtr rxBuffer;
public UInt32 length;
public IntPtr completeHandle;
public Packet(IntPtr busConfig, IntPtr txData, IntPtr rxData, UInt32 dataLength, IntPtr handle)
{
this.busConfig = busConfig;
this.txBuffer = txData;
this.rxBuffer = rxData;
this.length = dataLength;
this.completeHandle = handle;
}
}
#endregion
#region ctor / dtor
/// <summary>
/// Provides access to the SPI #2 bus on the PXA270.
/// </summary>
public SPI() : base("SPI2:")
{
// open the driver
Open(FileAccess.ReadWrite, FileShare.ReadWrite);
}
~SPI()
{
// close the driver
Close();
}
#endregion
#region loop back test
public bool Loopback
{
set
{
if (value)
{
try
{
this.DeviceIoControl(IOCTL_ENABLE_LOOPBACK, null, null);
}
catch (Exception)
{
throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
}
}
else
{
try
{
this.DeviceIoControl(IOCTL_DISABLE_LOOPBACK, null, null);
}
catch (Exception)
{
throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
}
}
}
}
#endregion
#region transfer
/// <summary>
/// Transfer one byte of data over SPI bus
/// </summary>
/// <param name="data">data</param>
/// <param name="pol">bus clock polarity</param>
/// <param name="pha">bus clock phase</param>
/// <returns>rx data</returns>
public Byte Exchange(byte data, bool pol, bool pha)
{
byte rxdata = 0;
BusConfig busConfig = new BusConfig(pol, pha, 8);
int datasize = Marshal.SizeOf(data);
IntPtr pTxbuffer = Marshal.AllocHGlobal(datasize);
Marshal.StructureToPtr(data, pTxbuffer, false);
IntPtr pRxbuffer = Marshal.AllocHGlobal(datasize);
Marshal.StructureToPtr(rxdata, pRxbuffer, false);
IntPtr pBusConfig = Marshal.AllocHGlobal(Marshal.SizeOf(busConfig));
Marshal.StructureToPtr(busConfig, pBusConfig, false);
Packet packet = new Packet(pBusConfig, pTxbuffer, pRxbuffer, 1, IntPtr.Zero);
try
{
this.DeviceIoControl(IOCTL_EXCHANGE, SerializeToByteArray(packet), null);
rxdata = Marshal.ReadByte(pRxbuffer);
}
catch (Exception)
{
throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
}
finally
{
Marshal.FreeHGlobal(pTxbuffer);
Marshal.FreeHGlobal(pRxbuffer);
Marshal.FreeHGlobal(pBusConfig);
}
return rxdata;
}
/// <summary>
/// Transfer one byte of data over SPI bus
/// defaults pol and pha to false
/// </summary>
/// <param name="data">data</param>
/// <returns>rx data</returns>
public Byte Exchange(byte data)
{
return (Exchange(data, false, false));
}
/// <summary>
/// Transfer two bytes (MSB first) of data over SPI bus
/// </summary>
/// <param name="data">data</param>
/// <param name="pol">bus clock polarity</param>
/// <param name="pha">bus clock phase</param>
/// <returns>rx data</returns>
public UInt16 Exchange(UInt16 data, bool pol, bool pha)
{
UInt16 rxdata = 0;
BusConfig busConfig = new BusConfig(pol, pha, 16);
int datasize = Marshal.SizeOf(data);
IntPtr pTxbuffer = Marshal.AllocHGlobal(datasize);
Marshal.StructureToPtr(data, pTxbuffer, false);
IntPtr pRxbuffer = Marshal.AllocHGlobal(datasize);
Marshal.StructureToPtr(rxdata, pRxbuffer, false);
IntPtr pBusConfig = Marshal.AllocHGlobal(Marshal.SizeOf(busConfig));
Marshal.StructureToPtr(busConfig, pBusConfig, false);
Packet packet = new Packet(pBusConfig, pTxbuffer, pRxbuffer, 1, IntPtr.Zero);
try
{
this.DeviceIoControl(IOCTL_EXCHANGE, SerializeToByteArray(packet), null);
rxdata = (UInt16)Marshal.ReadInt16(pRxbuffer);
}
catch (Exception)
{
throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
}
finally
{
Marshal.FreeHGlobal(pTxbuffer);
Marshal.FreeHGlobal(pRxbuffer);
Marshal.FreeHGlobal(pBusConfig);
}
return rxdata;
}
/// <summary>
/// Transfer two bytes (MSB first) of data over SPI bus
/// defaults pol and pha to false
/// </summary>
/// <param name="data">data</param>
/// <returns>rx data</returns>
public UInt16 Exchange(UInt16 data)
{
return (Exchange(data, false, false));
}
/// <summary>
/// Transfer four bytes (MSB first) of data over SPI bus
/// </summary>
/// <param name="data">data</param>
/// <param name="pol">bus clock polarity</param>
/// <param name="pha">bus clock phase</param>
/// <returns>rx data</returns>
public UInt32 Exchange(UInt32 data, bool pol, bool pha)
{
UInt32 rxdata = 0;
BusConfig busConfig = new BusConfig(pol, pha, 32);
int datasize = Marshal.SizeOf(data);
IntPtr pTxbuffer = Marshal.AllocHGlobal(datasize);
Marshal.StructureToPtr(data, pTxbuffer, false);
IntPtr pRxbuffer = Marshal.AllocHGlobal(datasize);
Marshal.StructureToPtr(rxdata, pRxbuffer, false);
IntPtr pBusConfig = Marshal.AllocHGlobal(Marshal.SizeOf(busConfig));
Marshal.StructureToPtr(busConfig, pBusConfig, false);
Packet packet = new Packet(pBusConfig, pTxbuffer, pRxbuffer, 1, IntPtr.Zero);
try
{
this.DeviceIoControl(IOCTL_EXCHANGE, SerializeToByteArray(packet), null);
rxdata = (UInt32)Marshal.ReadInt32(pRxbuffer);
}
catch (Exception)
{
throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
}
finally
{
Marshal.FreeHGlobal(pTxbuffer);
Marshal.FreeHGlobal(pRxbuffer);
Marshal.FreeHGlobal(pBusConfig);
}
return rxdata;
}
/// <summary>
/// Transfer four bytes (MSB first) of data over SPI bus
/// defaults pol and pha to false
/// </summary>
/// <param name="data">data</param>
/// <returns>rx data</returns>
public UInt32 Exchange(UInt32 data)
{
return (Exchange(data, false, false));
}
#endregion
#region P/Invoke helpers
/// <summary>
/// Byte array serializer
/// </summary>
/// <param name="anything"></param>
/// <returns></returns>
private static byte[] SerializeToByteArray(object anything)
{
int rawsize = Marshal.SizeOf(anything);
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.StructureToPtr(anything, buffer, false);
byte[] rawdatas = new byte[rawsize];
Marshal.Copy(buffer, rawdatas, 0, rawsize);
Marshal.FreeHGlobal(buffer);
return rawdatas;
}
/// <summary>
/// De-serializer from byte array
/// </summary>
/// <param name="rawdatas"></param>
/// <param name="anytype"></param>
/// <returns></returns>
private static object DeserializeFromByteArray(byte[] rawdatas, Type anytype)
{
int rawsize = Marshal.SizeOf(anytype);
if (rawsize > rawdatas.Length)
return null;
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(rawdatas, 0, buffer, rawsize);
object retobj = Marshal.PtrToStructure(buffer, anytype);
Marshal.FreeHGlobal(buffer);
return retobj;
}
#endregion
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?