一个选项可能是使用聚合来实现您要查找的内容。
例如,您可以创建一个名为SevenSegmentDisplay的类,它公开与7段LED模块交互的方法/属性并封装一个专用SPI实例。这些方法在内部调用私有SPI实例以实际与物理设备进行通信。
对于仿真器,这里是我为具有SPI接口的闪存芯片写的代码+配置。这在等待物理设备时用于内部测试。
using System;
using Microsoft.SPOT.Emulator;
using Microsoft.SPOT.Emulator.Spi;
using System.Diagnostics;
namespace dotnetwarrior.Emulator.Hardware
{
class MX25l3206FlashMemory : SpiDevice
{
private byte[] _memory;
public int MemorySize { get; set; }
public int SectorSize { get; set; }
public int PageSize { get; set; }
private Status _status;
[Flags]
enum Status
{
Wip = 1,
Wel = 2,
Bp0 = 4,
Bp1 = 8,
Bp2 = 16,
E_Err = 32,
P_Err = 64,
SRWD = 128
}
public MX25l3206FlashMemory()
{
}
public byte GetByte(int address)
{
return _memory[address];
}
public override void SetupComponent()
{
base.SetupComponent();
_memory = new byte[MemorySize];
}
protected override byte[] Write(byte[] data)
{
switch (data[0])
{
case 0x03: return Read(data);
case 0x9f: return ReadIdentification(data);
case 0x90: return ReadManufacturer(data);
case 0x06: return WriteEnable(data);
case 0x04: return WriteDisable(data);
case 0x20: return Erase4K(data);
case 0x40: return Erase8K(data);
case 0xd8: return EraseSector(data);
case 0x60:
case 0xC7: return EraseDevice(data);
case 0x02: return PagePrograme(data);
case 0x05: return ReadStatus(data);
case 0x01: return WriteStatus(data);
case 0x35: return ReadConfig(data);
}
throw new NotImplementedException("Unexpected Flash command : " + data[0].ToString());
}
private int GetAddress(byte[] data)
{
byte[] address = new byte[4];
Buffer.BlockCopy(data, 1, address, 1, 3);
Array.Reverse(address);
return (BitConverter.ToInt32(address, 0) % MemorySize);
}
private byte[] Read(byte[] data)
{
int address = GetAddress(data);
Buffer.BlockCopy(_memory, address, data, 4, data.Length - 4);
return data;
}
private byte[] ReadIdentification(byte[] data)
{
return new byte[]{0x01, 0x02, 0x15, 0x4d};
}
private byte[] ReadManufacturer(byte[] data)
{
return new byte[]{0x01, 0x02};
}
private byte[] WriteEnable(byte[] data)
{
_status |= Status.Wel;
return new byte[]{};
}
private byte[] WriteDisable(byte[] data)
{
_status &= ~Status.Wel;
return new byte[]{};
}
private byte[] ReadStatus(byte[] data)
{
return new byte[] { (byte)_status, (byte)_status };
}
private byte[] WriteStatus(byte[] data)
{
_status = (Status)data[1];
return new byte[] { };
}
private byte[] Erase4K(byte[] data)
{
if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
try
{
_status |= Status.Wip;
}
finally
{
_status &= ~(Status.Wel | Status.Wip);
}
return new byte[] { };
}
private byte[] Erase8K(byte[] data)
{
if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
_status |= Status.Wip;
try
{
}
finally
{
_status &= ~(Status.Wel | Status.Wip);
}
return new byte[] { };
}
private byte[] EraseSector(byte[] data)
{
if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
_status |= Status.Wip;
try
{
int address = GetAddress(data);
int sector = address/SectorSize;
int sectorStartAddress = sector * SectorSize;
for (int i = 0; i < SectorSize; i++)
{
_memory[sectorStartAddress + i] = 0xff;
}
}
finally
{
_status &= ~(Status.Wel | Status.Wip);
}
return new byte[] { };
}
private byte[] EraseDevice(byte[] data)
{
if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
_status |= Status.Wip;
try
{
for (int i = 0; i < MemorySize; i++)
{
_memory[i] = 0xff;
}
}
finally
{
_status &= ~(Status.Wel | Status.Wip);
}
return new byte[] { };
}
private byte[] PagePrograme(byte[] data)
{
if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
_status |= Status.Wip;
try
{
int address = GetAddress(data);
int offset = address % PageSize;
for (int i = 0; i < data.Length - 4; i++)
{
_memory[address + ((offset + i) % PageSize)] &= (byte)data[i + 4];
}
}
finally
{
_status &= ~(Status.Wel | Status.Wip);
}
return new byte[] { };
}
private byte[] ReadConfig(byte[] data)
{
return new byte[] { };
}
}
}
将闪存配置到仿真器中的相应配置如下(注意这是在自定义仿真器中使用的)。
<Types>
<MX25l3206>dotnetwarrior.Emulator.Hardware.MX25l3206FlashMemory, dotnetwarrior.Emulator</MX25l3206>
<AccessIndicator>dotnetwarrior.Emulator.Hardware.AccessIndicator, dotnetwarrior.Emulator</AccessIndicator>
</Types>
<EmulatorComponents>
<MX25l3206 id="myFlash">
<MemorySize>4194304</MemorySize>
<SectorSize>65536</SectorSize>
<PageSize>256</PageSize>
<ChipSelectPin>10</ChipSelectPin>
<!--SPI-->
<ChipSelectActiveState>false</ChipSelectActiveState>
<ChipSelectSetupTime>1</ChipSelectSetupTime>
<ChipSelectHoldTime>1</ChipSelectHoldTime>
<ClockRateKHz>36000</ClockRateKHz>
<ClockIdleState>false</ClockIdleState>
<ClockEdge>false</ClockEdge>
<SpiModule>Spi1</SpiModule>
<!--Hardware Provider-->
<Mask>1</Mask>
<Mosi>2</Mosi>
<Miso>3</Miso>
</MX25l3206>
因此,而不是继承自SpiDevice?以及我如何去模拟SPI数据传输?在应用程序端(运行在netduino上)和仿真器端(MF设备模拟器)上都没有看到这样的例子。 –
我有一个SPI闪存模拟设备,我以前做过,当我今天晚上回到家时,我会分享这个代码。希望有帮助。我想知道你的问题,因为你想为SPI设备编写一个托管包装来抽象它在主板上的使用情况,对此很抱歉。 –
谢谢。然后我会提供一个类似于(但是用于我的设备)的代码,但是我不清楚如何在应用程序项目上编写(通过SPI),并且它将由自定义SPI设备在模拟器上获取。举例来说,你将如何(在应用程序而不是仿真器上)写入你的SPI闪存? –