maurosmartins Posted April 19, 2013 at 02:30 PM Report #504012 Posted April 19, 2013 at 02:30 PM Viva pessoal, Para um projecto recente estou a usar um chip que converte de USB para SPI (MCP2210) que por sua vez irá controlar um módulo de comunicações sem fios (NRF24L01+). O conversor MCP2210 é fornecido com um DLL que permite enviar e receber os dados por SPI bem como controlar alguns pinos de utilização genérica (GPIO). Agora gostaria de criar em cima disto outra DLL que contenha as funções para controlar o NRF24L01+ e que utiliza as funções continas na DLL do MCP2210. Estou a usar C#, podem dar-me algumas indicações de como proceder para obter este resultado? Cumprimentos, Mauro.
kalin Posted April 19, 2013 at 05:20 PM Report #504068 Posted April 19, 2013 at 05:20 PM Se estiveres a utilizar o visual studio, podes criar um novo projecto, para uma dll o template "Class Library". Para referênciar a dll que queres utilizar, basta clicar com o botão direito do rato sobre as References do project e podes fazer browse para a dll. Quando terminares, deves fazer um build ao projecto e verificar se existem erros, deves abrir as references e verificar se existe algum sinal de aviso, podes ter que alterar a versão do .net para ser equivalente a da dll que estás a referenciar. Deves verificar ainda que nas propriedades da referencia a dll que adicionaste, a propriedade "Copy Local" está a true, isto porque a dll que criaste deve ter uma cópia da dll que estás a referênciar na mesma pasta, caso contrário vais ter excepções ao excecutar a tua dll.
maurosmartins Posted April 20, 2013 at 05:26 PM Author Report #504174 Posted April 20, 2013 at 05:26 PM Olá a todos, @kalin, muito obrigado pela resposta detalhada! Tenho mais algumas questões a colocar, para aceder ao MCP2210 tenho de instanciar um objecto do tipo DevIO, como proceder para que na nova DLL só o tenha de fazer uma vez, ou seja ser global ao programa? isto porque no programa final gostaria que fosse qq coisa do género: using System; using usb2nrf24l01p; namespace programa { class Program { public static void Main(string[] args) { string resposta; nrf24l01p nrf=new nrf24l01p(); nrf.init(); nrf.send("texto"); resposta=nrf.receive(); console.write(resposta); } } } Este é um exemplo (resumido) do que quero conseguir fazer. Cumprimentos, Mauro.
kalin Posted April 27, 2013 at 09:09 PM Report #505019 Posted April 27, 2013 at 09:09 PM Para teres uma variável "global" podes usar uma variável auxiliar privada que guarde o estado da propriedade que queres que seja global, ou seja: public class GlobalProperties { private DevIO device; public DevIO Device { get { return device ?? new DevIO(); } set { device = value; } } } Isto é o mais simples, o problema é que se precisares de aceder a esta propriedade em vários sítios diferentes, vais instanciar várias vezes a classe GlobalProperties e o teu problema mantém-se, para resolver isto precisa que esta classe seja um Singleton, ou seja: public class GlobalProperties { private static volatile GlobalProperties instance; private static object syncRoot = new Object(); private GlobalProperties() { } public static GlobalProperties Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) instance = new GlobalProperties(); } } return instance; } } private DevIO device; public DevIO Device { get { return device ?? new DevIO(); } set { device = value; } } } Podes ver mais informações sobre singletons aqui
maurosmartins Posted May 3, 2013 at 02:39 PM Author Report #505718 Posted May 3, 2013 at 02:39 PM (edited) Olá pessoal, Kalin, obrigado pela resposta! o meu código de momento está assim (dividido em dois ficheiros/classes): using System; using Usb2Nrf; namespace usbspi{ class Program{ public static void Main(string[] args) { byte StatusReg; byte [] payload =new Byte[10]; nrf24l01p nrf = new nrf24l01p(); //nrf.DefaultTx(); nrf.DefaultRx(); while (true) { StatusReg=nrf.ReadStatusRegister(); //Console.Write(StatusReg.ToString()+"\n"); if((StatusReg&0x40)!=0x00){ nrf.RxData(payload); Console.Write("{0}, {1}, {2}, {3}\n",payload[1],payload[2],payload[3],payload[4]); } System.Threading.Thread.Sleep(100); } // // for (int i = 0; i < 100000; i++) { // // // nrf.TxData(); // // //nrf.tdata(); // // System.Threading.Thread.Sleep(1000); // // Console.Write("ite {0}\n",i); // Console.Write("status register = {0}\n",(nrf.ReadRegister(0x00)).ToString("x")); // // } } } } e: using System; using MCP2210; namespace Usb2Nrf{ class nrf24l01p{ private const uint MCP2210_VID = 0x04D8; // VID for Microchip Technology Inc. private const uint MCP2210_PID = 0x00DE; // PID for MCP2210 private MCP2210.DevIO UsbSpi; public byte ReadStatusRegister(){ byte[] datatx = new Byte[1]; byte[] datarx = new Byte[1]; UsbSpi.Settings.SetSpiTxferSize(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,1); //so transfere 1 byte de cada vez UsbSpi.Functions.TxferSpiData(datatx,datarx); //ler return datarx[0]; } public byte ReadRegister(byte register){ byte[] datatx = new Byte[2]; byte[] datarx = new Byte[2]; UsbSpi.Settings.SetSpiTxferSize(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,2); datatx[0]=register; datatx[1]=register; //dummy UsbSpi.Functions.TxferSpiData(datatx,datarx); return datarx[1]; } public void FlushTxFifo(){ byte[] datatx = new Byte[1]; byte[] datarx = new Byte[1]; UsbSpi.Settings.SetSpiTxferSize(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,1); datatx[0]=0xE1; UsbSpi.Functions.TxferSpiData(datatx,datarx); } public void WriteRegister(byte register,byte value){ byte[] datatx = new Byte[2]; byte[] datarx = new Byte[2]; UsbSpi.Settings.SetSpiTxferSize(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,2); datatx[0]=(byte)((0x20)|register); datatx[1]=value; UsbSpi.Functions.TxferSpiData(datatx,datarx); } public void LoadTx(ref byte[] payload, ushort n){ byte[] datatx = new Byte[10]; byte[] datarx = new Byte[10]; UsbSpi.Settings.SetSpiTxferSize(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,(ushort)(n+1)); datatx[0]=0xA0; for (int i = 1; i < (n+1); i++) { datatx[i]=payload[i-1]; } UsbSpi.Functions.TxferSpiData(datatx,datarx); UsbSpi.Functions.SetGpioPinVal(0xFFFF); System.Threading.Thread.Sleep(0); UsbSpi.Functions.SetGpioPinVal(0x0000); } public void SetAddress(){ byte[] datatx = new Byte[10]; byte[] datarx = new Byte[10]; UsbSpi.Settings.SetSpiTxferSize(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,6); datatx[0]=0x30; datatx[1]=0xE7; datatx[2]=0xE7; datatx[3]=0xE7; datatx[4]=0xE7; datatx[5]=0xE7; UsbSpi.Functions.TxferSpiData(datatx,datarx); } public void RxData(byte [] buffer){ byte [] dummy =new Byte[10]; UsbSpi.Settings.SetSpiTxferSize(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,5); dummy[0]=0x61; UsbSpi.Functions.TxferSpiData(dummy,buffer); UsbSpi.Settings.SetSpiTxferSize(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,1); dummy[0]=0xE2; UsbSpi.Functions.TxferSpiData(dummy,dummy); WriteRegister(0x07,0x40); //Console.Write("{0}, {1}, {2}, {3}\n",buffer[0],buffer[1],buffer[2],buffer[3]); } public void TxData(){ byte [] payload =new Byte[10]; payload[0]=0x01; payload[1]=0x02; payload[2]=0x03; payload[3]=0x04; WriteRegister(0x07,0x7E); WriteRegister(0x00,0x3A); FlushTxFifo(); LoadTx(ref payload,4); } public void DefaultTx(){ WriteRegister(0x00,0x38); //mask ints WriteRegister(0x04,0x00); //mask ints WriteRegister(0x03,0x03); //mask ints WriteRegister(0x06,0x27); //mask ints WriteRegister(0x05,0x02); //mask ints SetAddress(); WriteRegister(0x01,0x00); //mask ints } public void DefaultRx(){ WriteRegister(0x00,0x39); //mask ints WriteRegister(0x01,0x00); //mask ints WriteRegister(0x03,0x03); //mask ints WriteRegister(0x06,0x27); //mask ints WriteRegister(0x11,0x04); //mask ints WriteRegister(0x05,0x02); //mask ints SetAddress(); WriteRegister(0x00,0x3B); //mask ints UsbSpi.Functions.SetGpioPinVal(0xFFFF); } public nrf24l01p(){ UsbSpi = new DevIO(MCP2210_VID, MCP2210_PID); bool isConnected = false; // Connection status variable for MCP2210 isConnected = UsbSpi.Settings.GetConnectionStatus(); if (isConnected==true) { Console.WriteLine("Ligacao com sucesso!"); } else{ Console.Write("Ligacao falhou!"); Console.ReadKey(true); return; } byte[] gpiopindes=new Byte[9]; for (int i = 0; i < 9; i++) { gpiopindes[i]=0;//GPIO } gpiopindes[4]=1; //CS gpiopindes[6]=2; //IRQ UsbSpi.Settings.SetAllChipSettings(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,gpiopindes,0x0000,0x20,false,0,false); UsbSpi.Settings.SetInterruptPinMode(MCP2210.DllConstants.CURRENT_SETTINGS_ONLY,2); UsbSpi.Functions.SetGpioPinVal(0x0000); System.Threading.Thread.Sleep(1); } } } Coloco aqui o código pois pode ajudar alguém...! Com isto deparo-me agora com outra duvida, Inicialmente pensei que o conversor de USB para SPI tinha um pino dedicado a interrupções que me iria despoletar um evento cada vez que o fosse a "0" ou a "1" (indicando por exemplo que o módulo de comunicação sem fios recebeu um novo pacote). Vejo afinal que isto não acontece e que preciso de estar constantemente a fazer polling ao modulo de comunicação sem fios para saber se chegou um novo pacote de dados. Para ultrapassar esta situação gostaria de criar uma thread dedicada a fazer o polling do modulo de comunicação sem fios e caso haja um novo pacote de dados lançar um evento para o programa principal. Podem-me dar uma orientação de como fazer? Cumprimentos, Mauro. Edited May 3, 2013 at 02:40 PM by maurosmartins
kalin Posted May 3, 2013 at 07:12 PM Report #505757 Posted May 3, 2013 at 07:12 PM Eu sempre que preciso que trabalho assíncrono uso BackgroundWorker, é muito fácil de utilizar. Podes iniciar um ciclo infinito dentro do evento DoWork e sempre que precisares podes utilizar o método ReportProgress para enviar dados para a thread do teu programa. Quando precisares de terminar existe também um evento CancelAsync. Podes encontrar mais detalhes e exemplos na documentação: http://msdn.microsoft.com/en-us/library/4852et58.aspx
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now