Can anyone help me out with MC23S17, ive adapted this example but its not working for me.
this is my code:
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.Spi;
using GHIElectronics.TinyCLR.Pins;
using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using System.Threading;
namespace PWMExpander
{
class Program
{
static SpiDevice device;
static void Main()
{
SpiConnectionSettings settings = new SpiConnectionSettings()
{
ChipSelectType = SpiChipSelectType.Gpio,
ChipSelectLine = G30.GpioPin.PC12,
Mode = SpiMode.Mode0,
ClockFrequency = 4 * 1000 * 1000, //4Mhz
DataBitLength = 8,
};
SpiController controller = SpiController.FromName(G30.SpiBus.Spi2);
device = controller.GetDevice(settings);
WriteRegister8(Register.IOCONA, HAEN); // enable the hardware address incase there is more than one chip
WriteRegister16(Register.IODIRA, pinMode); // Set the default or current pin mode
SetPinMode(5);
while (true)
{
WritePin(0, 1);
for (byte i = 0; i < 15; i++)
{
Debug.WriteLine(ReadPin(i).ToString());
}
Thread.Sleep(2000);
}
}
public enum Register : byte
{
/// <summary>I/O Direction A - controls the direction of the data I/O.</summary>
IODIRA = 0x00,
/// <summary>I/O Direction B - controls the direction of the data I/O.</summary>
IODIRB = 0x01,
/// <summary>Input Polarity A - allows the user to configure the polarity on the corresponding GPIO port bits.</summary>
IPOLA = 0x02,
/// <summary>Input Polarity B - allows the user to configure the polarity on the corresponding GPIO port bits.</summary>
IPOLB = 0x03,
/// <summary>Interrupt on change control A - controls the interrupt-on-change feature for each pin.</summary>
GPINTENA = 0x04,
/// <summary>Interrupt on change control B - controls the interrupt-on-change feature for each pin.</summary>
GPINTENB = 0x05,
/// <summary>Default compare for interrupt on change A</summary>
DEFVALA = 0x06,
/// <summary>Default compare for interrupt on change B</summary>
DEFVALB = 0x06,
/// <summary>Interrupt Control A - controls how the associated pin value is compared for the interrupt-on-change feature.</summary>
INTCONA = 0x08,
/// <summary>Interrupt Control B - controls how the associated pin value is compared for the interrupt-on-change feature.</summary>
INTCONB = 0x09,
/// <summary>I/O Expander Configuration A - contains several bits for configuring the device.</summary>
IOCONA = 0x0A,
/// <summary>I/O Expander Configuration B - contains several bits for configuring the device.</summary>
IOCONB = 0x0B,
/// <summary>Pull Up resistor configuration register A - controls the pull-up resistors for the port pins.</summary>
GPPUA = 0x0C,
/// <summary>Pull Up resistor configuration B - controls the pull-up resistors for the port pins.</summary>
GPPUB = 0x0D,
/// <summary>Interrupt Flag A - reflects the interrupt condition on the port pins of any pin that is enabled for interrupts via the GPINTEN register.</summary>
INTFA = 0x0E,
/// <summary>Interrupt Flag B - reflects the interrupt condition on the port pins of any pin that is enabled for interrupts via the GPINTEN register.</summary>
INTFB = 0x0F,
/// <summary>Interrupt Capture A - captures the GPIO port value at the time the interrupt occurred.</summary>
INTCAPA = 0x10,
/// <summary>Interrupt Capture B - captures the GPIO port value at the time the interrupt occurred.</summary>
INTCAPB = 0x11,
/// <summary>GPIO A - reflects the value on the port.</summary>
GPIOA = 0x12,
/// <summary>GPIO B - reflects the value on the port.</summary>
GPIOB = 0x13,
/// <summary>Output Latch A - provides access to the output latches.</summary>
OLATA = 0x14,
/// <summary>Output Latch B - provides access to the output latches.</summary>
OLATB = 0x15
}
/// <summary>Represents an On state</summary>
public const byte On = 1;
/// <summary>Represents an Off state</summary>
public const byte Off = 0;
/// <summary>Represents the Output state.</summary>
public const byte Output = 0;
/// <summary>Represents the Input state.</summary>
public const byte Input = 1;
private const byte Address = 0x00; // offset address if hardware addressing is on and is 0 - 7 (A0 - A2)
private const byte BaseAddW = 0x40; // MCP23S17 Write base address
private const byte BaseAddR = 0x41; // MCP23S17 Read Base Address
/// <summary>IOCON register for MCP23S17, x08 enables hardware address so sent address must match hardware pins A0-A2</summary>
private const byte HAEN = 0x08;
/// <summary>default Pinmode for the MXP23S17 set to inputs</summary>
private static ushort pinMode = 0XFFFF;
/// <summary>default pullups for the MXP23S17 set to weak pullup</summary>
private static ushort pullUpMode = 0XFFFF;
/// <summary>Holds output data</summary>
private static readonly byte[] ReadBuffer3 = new byte[3];
/// <summary>Holds output data</summary>
private static readonly byte[] ReadBuffer4 = new byte[4];
/// <summary>Register, then 16 bit value</summary>
private static readonly byte[] WriteBuffer3 = new byte[3];
/// <summary>Register, then 16 bit value</summary>
private static readonly byte[] WriteBuffer4 = new byte[4];
/// <summary>The state of the pins</summary>
public static ushort PinState { get; set; }
/// <summary>The inversion mode used for each pin</summary>
public static ushort InversionMode { get; set; }
/// <summary>Read the value of a given pin</summary>
public static ushort ReadPin(byte pin)
{
if (pin > 15)
{
return 0x00; // If the pin value is not valid (1-16) return, do nothing and return
}
ushort value = ReadRegister16(); // Initialize a variable to hold the read values to be returned
ushort pinmask = (ushort)(1 << pin); // Initialize a variable to hold the read values to be returned
return ((value & pinmask) > 0) ? On : Off;
// Call the word reading function, extract HIGH/LOW information from the requested pin
}
/// <summary>Read the values of <see cref="Register.GPIOA" />
public static ushort ReadRegister16()
{
WriteBuffer4[0] = (BaseAddR | (Address << 1));
WriteBuffer4[1] = (byte)Register.GPIOA;
WriteBuffer4[2] = 0;
WriteBuffer4[3] = 0;
device.TransferFullDuplex(WriteBuffer4, ReadBuffer4);
return ConvertToUnsignedShort(ReadBuffer4); // Return the constructed word, the format is 0x(register value)
}
/// <summary>Reads a <see langword="byte" /> from the given <paramref name="register" />
public static byte ReadRegister8(byte register)
{
WriteBuffer3[0] = (BaseAddR | (Address << 1)); // Send the MCP23S17 opcode, chip address, and read bit
WriteBuffer3[1] = register;
device.TransferFullDuplex(WriteBuffer3, ReadBuffer3);
return ReadBuffer4[2];
// convertToInt(readBuffer); // Return the constructed word, the format is 0x(register value)
}
/// <summary>Set the inversion of input polarity a pin at a time.</summary>
public static void SetInversionMode(byte pin, byte mode)
{
if (pin > 15)
{
return;
}
if (mode == On)
{
InversionMode |= (ushort)(1 << (pin - 1));
}
else
{
InversionMode &= (ushort)(~(1 << (pin - 1)));
}
WriteRegister16(Register.IPOLA, InversionMode);
}
/// <summary>Set the inversion of input polarity for all pins.</summary>
public static void SetInversionMode(ushort mode)
{
WriteRegister16(Register.IPOLA, mode);
InversionMode = mode;
}
/// <summary>Sets the given <paramref name="pin" /> to the given <paramref name="mode" />.</summary>
public static void SetPinMode(byte pin, byte mode)
{
if (pin > 15)
{
return; // only a 16bit port so do a bounds check, it cant be less than zero as this is a byte value
}
if (mode == Input)
{
pinMode |= (ushort)(1 << (pin)); // update the pinMode register with new direction
}
else
{
pinMode &= (ushort)(~(1 << (pin))); // update the pinMode register with new direction
}
WriteRegister16(Register.IODIRA, pinMode);
// Call the generic word writer with start register and the mode cache
}
/// <summary>Sets all pins to the given <paramref name="mode" />.</summary>
public static void SetPinMode(ushort mode)
{
WriteRegister16(Register.IODIRA, mode);
pinMode = mode;
}
/// <summary>Set the pull up mode</summary>
public static void SetPullUpMode(byte pin, byte mode)
{
if (pin > 15)
{
return;
}
if (mode == On)
{
pullUpMode |= (ushort)(1 << (pin));
}
else
{
pullUpMode &= (ushort)(~(1 << (pin)));
}
WriteRegister16(Register.GPPUA, pullUpMode);
}
/// <summary>Set the pull up mode</summary>
public static void SetPullUpMode(ushort mode)
{
WriteRegister16(Register.GPPUA, mode);
pullUpMode = mode;
}
/// <summary>Write a value to the pin and record it's state in PinState</summary>
public static void WritePin(byte pin, byte value)
{
if (pin > 15)
{
return;
}
if (value > 1)
{
return;
}
if (value == 1)
{
PinState |= (ushort)(1 << pin);
}
else
{
PinState &= (ushort)(~(1 << pin));
}
WriteRegister16(Register.GPIOA, PinState);
}
/// <summary>Write the given <paramref name="value" /> to the given register</summary>
public static void WriteRegister16(byte register, ushort value)
{
WriteBuffer4[0] = (BaseAddW | (Address << 1));
WriteBuffer4[1] = register;
WriteBuffer4[2] = (byte)(value >> 8);
WriteBuffer4[3] = (byte)(value & 0XFF);
device.Write(WriteBuffer4);
}
/// <summary>Writes the supplied <paramref name="word" /> to the given <paramref name="register" />
public static void WriteRegister16(Register register, ushort word)
{
WriteRegister16((byte)register, word);
}
/// <summary>Write the given <paramref name="value" /> to the given register</summary>
public static void WriteRegister8(byte register, byte value)
{
// Direct port manipulation speeds taking Slave Select LOW before SPI action
WriteBuffer3[0] = (BaseAddW | (Address << 1));
WriteBuffer3[1] = register;
WriteBuffer3[2] = value;
device.Write(WriteBuffer3);
}
/// <summary>Writes the supplied <paramref name="value" /> to the given <paramref name="register" />
public static void WriteRegister8(Register register, byte value)
{
WriteRegister8((byte)register, value);
}
/// <summary>Write a <paramref name="value" /> to the device record it's state in <see cref="PinState" />.</summary>
public static void WriteWord(ushort value)
{
WriteRegister16(Register.GPIOA, value);
PinState = value;
}
private static ushort ConvertToUnsignedShort(byte[] data)
{
// byte[0] = command, byte[1] register, byte[2] = data high, byte[3] = data low
ushort result = (ushort)(data[2] & 0xFF);
result <<= 8;
result += data[3];
return result;
}
}
}