2013-07-19 29 views
0

在一个新的设计中(新的.NET Micro),我有一系列LED 7段显示屏,这些显示屏通过带有Netduino的SPI总线进行控制。为.NET微型框架创建自己的SpiDevice的最佳方式是什么?

现在,我已经看到一个人不必模拟SPI总线的东西,因为.NET Microframework已经有了一个模拟的SPI总线,太棒了。

由于我的“模块”是由SPI控制的,我想通过SPIDevice和SPIBus将其抽象出来,但是我已经搜遍了整个互联网,并且找不到一个如何推出自己的自定义SPIDevice的例子(并控制它)以用于.NET MF DeviceEmulator项目。

基本上在我的SPIDevice中,我将有一系列的控制寄存器加上每个LED的数据,但我迫切需要一个能够引导我们进入正确方向的例子。当我安装.NET MF 4.3时,它没有安装任何示例。

回答

0

一个选项可能是使用聚合来实现您要查找的内容。

例如,您可以创建一个名为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> 
+0

因此,而不是继承自SpiDevice?以及我如何去模拟SPI数据传输?在应用程序端(运行在netduino上)和仿真器端(MF设备模拟器)上都没有看到这样的例子。 –

+1

我有一个SPI闪存模拟设备,我以前做过,当我今天晚上回到家时,我会分享这个代码。希望有帮助。我想知道你的问题,因为你想为SPI设备编写一个托管包装来抽象它在主板上的使用情况,对此很抱歉。 –

+0

谢谢。然后我会提供一个类似于(但是用于我的设备)的代码,但是我不清楚如何在应用程序项目上编写(通过SPI),并且它将由自定义SPI设备在模拟器上获取。举例来说,你将如何(在应用程序而不是仿真器上)写入你的SPI闪存? –

相关问题