Использование модуля MCP2210 Breakout Module

В предыдущей статье мы рассмотрели преобразователь USB to SPI на базе MCP2210

Итак, давайте разберемся как же общаться с устройствами подключенными к модулю MCP2210 через SPI (на AliExpress м/с MCP2210 стоит около 2$). Для этого из моего ящика была вытащена микросхема MAX1240, которая представляет собой АЦП с передачей данных по SPI. Довольно интересная микросхема в DIP корпусе, что позволяет собрать всю тестовую схему на беспаечной макетной плате. Собранная схема приведена ниже.

MAX1240 подключена по типовой схеме, питание 3.3 В берется со стабилизатора, находящегося «на борту» модуля MCP2210. У АЦП имеется выход опорного напряжения 2.5 В, подаем его на вход для оцифровки через потенциометр по схеме обычного делителя напряжения, тем самым мы можем менять напряжение на входе от 0 до 2.5 В. На этом мы заканчиваем подготовительные работы.

Скачиваем библиотеку MCP2210 по следующему адресу:

http://ww1.microchip.com/downloads/en/DeviceDoc/MCP2210_DLLv2.zip

Я буду показывать работу с модулем на примере языка C#. На других языках работа с модулем аналогична, пожалуйста внимательно прочитайте документацию! 

Создаем новый консольный проект C# в Visual Studio 2010 (далее VS2010). Для начала необходимо добавить скаченную библиотеку к нашему проекту. Открываем архив и извлекаем все файлы. Теперь во вкладке Обозреватель решений в проекте VS2010 кликаем правой кнопкой на пункте Ссылки, выбираем Добавить ссылку. Переходим на вкладку Обзор и указываем путь до файла mcp2210_dll_m_dotnetv4_x86.dll​ и вот тут важно, во-первых, если вы использует C# или VisualBasic, то нужно использовать файл с буквой — managed. Данная библиотека использует .Net и не будет работать на других языках! Для  других языков в папке unmanaged есть файлы для импорта в ваш проект. Работа на других языках очень похожа, отличия минимальны! Так же в зависимости от версии установленного в системе .Net фрэймворка нужно выбирать netv2 или netv4 соответственно. Ну и последний момент, это разрядность системы. Выбрали библиотеку и нажимаем OK

С этого момента, библиотека добавлена в проект. Вверху проекта дописываем строчку:

 using mcp2210_dll_m;

Следующим шагом станет проверка подключен ли модуль, и далее создаем объект, закидываем ему настройки и передаем! Приведу сразу весь текст программы:

             int error = 0;             ushort chislo = 0;             double znachenie = 0;             //проверяем подключен ли модуль             error = MCP2210.M_Mcp2210_GetConnectedDevCount(0x4D8, 0xDE); //стандартные VID и PID у модуля MCP2210             if (error == 0)             {                     Console.WriteLine("Error! Not connected module!");                         Console.ReadKey();             }             else             {                  Console.WriteLine("Module connected! Let's open!");                  // открываем модуль                 StringBuilder Path = null;                 IntPtr module = MCP2210.M_Mcp2210_OpenByIndex(0x4D8, 0xDE, 0, Path);                  //настраиваем параметры модуля                 //скорость передачи данных                 uint rate = 10000;                 //настройка выводов CS                 uint cs_idle = 0xFFFFFF;                 uint cs_activ = 0xFFFFEF;                 //задержки всякие                 uint cs_to_data_dly = 0;                 uint data_to_data_dly = 0;                 uint data_to_cs_dly = 0;                 //количество байт передачи/приема                 uint numberbyte = 2;                 //режим SPI                 byte spi_mode = (byte)MCP2210.M_MCP2210_SPI_MODE0;                 //создаем массивы, важно, чтобы массивы были не пустыми!                 byte [] Tx = new byte[2];                 byte [] Rx = new byte[2];                  while (true)                 {                     //данная команда сразу и настраивает модуль и запускает передачу/прием пакетов                     error = MCP2210.M_Mcp2210_xferSpiDataEx(module, Tx, Rx, ref rate, ref numberbyte, 0x10, ref cs_idle, ref cs_activ, ref cs_to_data_dly, ref data_to_cs_dly, ref data_to_data_dly, ref spi_mode);                      if (error != 0) { Console.WriteLine("Error! Not reseved data!"); }                     else                     {                         //на данном этапе, в массиве Rx хранятся принятые 2 байта данных с АЦП                         //дальнейшие "пляски" связанны с его обработкой и переводом в вольты                         //исправляем порядок битов, переворачивая их                         Array.Reverse(Rx);                         //сшиваем массив из двух байтов в одно число 2 байтное (важно!)                         chislo = BitConverter.ToChar(Rx, 0);                         //скидываем влево все число пропадает старшая единица, не несущая информации                         chislo = (ushort)(chislo << 1);                         //сдвигаем все байты вправо (данные 12 бит, а принятых 16)                         chislo = (ushort)(chislo >> 4);                         //по формуле из datasheet переводим в вольты                         znachenie = chislo * 0.00061;                         //выводим и радуемся                         Console.WriteLine(znachenie);                     }                      //повторяем это все пока не надоест с такой вот паузой                     System.Threading.Thread.Sleep(100);                 }             }

На самом деле все очень просто. В видео к статье я продемонстрирую работу этого кода и расскажу как он работает! Но думаю, по комментариям в коде и так, не сложно разобраться. 

В данном примере мы воспользовались функцией xferSpiDataEx, которая упрощает передачу, в ней одновременно задаются и параметры модуля и передача/прием. Но данная функция не совсем подходит, если нам необходимо расширить возможности модуля. И тут я имею ввиду, если мы хотим по полной использовать 9 выводов GPIO. Давайте разберем, что же они могут.

Все 9 выводов GPIO имеют 3 режима работы. В первом режиме GPIO, они используются как обычные цифровые входы/выходы, т.е. программно можно выставить или считать любой уровень на нужном выводе. Во-втором режиме CS, которые используются для передачи данных, выбранный вывод используется как выход разрешения. В этом режиме настраиваются задержки срабатывания CS, уровень CS (инверсный или нет). И наконец третий режим, в котором у каждого вывода есть своя собственная функция. Однако большая часть этих функций может и не пригодиться обычному обывателю, лично я, иногда, использую SPI Transfer Traffic LED. На вывод GPIO3 вешаю светодиод с резистором для наглядного контроля передачи данных. Но как видно, микросхема обладает и прерыванием, честно скажу не придумал когда это может пригодится, но если пригодится я буду знать, что оно есть! А вот в первом режиме выводов — GPIO, я придумал что можно сделать!

Видоизменим нашу схему на макетной плате.

Теперь давайте напишем тот же код что и раньше добавив использование кнопки в качестве старт/стоп измерений, а светодиод пусть загорается для индикации этой кнопки (стоп — не горит/ старт — горит).

Опять же, приведу сразу весь текст программы.

             int error = 0;             ushort chislo = 0;             double znachenie = 0;             uint work = 0;             //проверяем подключен ли модуль             error = MCP2210.M_Mcp2210_GetConnectedDevCount(0x4D8, 0xDE); //стандартные VID и PID у модуля MCP2210             if (error == 0)             {                 Console.WriteLine("Error! Not connected module!");                 Console.ReadKey();             }             else             {                  Console.WriteLine("Module connected! Let's open!");                  // открываем модуль                 StringBuilder Path = null;                 IntPtr module = MCP2210.M_Mcp2210_OpenByIndex(0x4D8, 0xDE, 0, Path);                  //настраиваем параметры модуля                 //скорость передачи данных                 uint rate = 10000;                 //настройка выводов CS                 uint cs_idle = 0xFFFFFF;                 uint cs_activ = 0xFFFFEF;                 //задержки всякие                 uint cs_to_data_dly = 0;                 uint data_to_data_dly = 0;                 uint data_to_cs_dly = 0;                 //количество байт передачи/приема                 uint numberbyte = 2;                 //режим SPI                 byte spi_mode = (byte)MCP2210.M_MCP2210_SPI_MODE0;                 //создаем массивы, важно, чтобы массивы были не пустыми!                 byte[] Tx = new byte[2];                 byte[] Rx = new byte[2];                 //переменная светодиода                 uint svetik = 1;                 //создаем переменную, в которой хранится состояние GPIO                 uint resvet = 0;                 //настраиваем GIPO все выводы GPIO, кроме GPIO4, который CS                 byte [] gpio = {0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00};                  //настраиваем GPIO                 MCP2210.M_Mcp2210_SetGpioConfig(module, (byte)MCP2210.M_MCP2210_VM_CONFIG, gpio, 0, 0, (byte)MCP2210.M_MCP2210_REMOTE_WAKEUP_DISABLED, (byte)MCP2210.M_MCP2210_INT_MD_CNT_NONE, (byte)MCP2210.M_MCP2210_SPI_BUS_RELEASE_DISABLED);                 MCP2210.M_Mcp2210_SetSpiConfig(module, (byte)MCP2210.M_MCP2210_VM_CONFIG, ref rate, ref cs_idle, ref cs_activ, ref cs_to_data_dly, ref data_to_cs_dly, ref data_to_data_dly, ref numberbyte, ref spi_mode);                                 while (true)                 {                     //считываем значение кнопки                     MCP2210.M_Mcp2210_GetGpioPinVal(module, ref resvet);                      if ((resvet & 0x01) == 1) Сhange(ref work, ref svetik);//функция просто меняет 0 на 1 и наоборот                      if (work == 1)                     {                         error = MCP2210.M_Mcp2210_xferSpiData(module, Tx, Rx, ref rate, ref numberbyte, 0x10);                          if (error != 0) { Console.WriteLine("Error! Not reseved data!"); }                         else                         {                              //на данном этапе, в массиве Rx хранятся принятые 2 байта данных с АЦП                             //дальнейшие "пляски" связанны с его обработкой и переводом в вольты                             //исправляем порядок битов, переворачивая их                             Array.Reverse(Rx);                             //сшиваем массив из 2 байтов в одно число 2 байтное (важно!)                             chislo = BitConverter.ToChar(Rx, 0);                             //скидываем влево все число пропадает старшая единица, не несущая информации                             chislo = (ushort)(chislo << 1);                             //сдвигаем все байты вправо (данные 12 бит, а принятых 16)                             chislo = (ushort)(chislo >> 4);                             //по формуле из datasheet переводим в вольты                             znachenie = chislo * 0.00061;                             //выводим и радуемся                             Console.WriteLine(znachenie);                                                     }                     }                      //включаем или выключаем светодиод                     if (svetik == 0) { MCP2210.M_Mcp2210_SetGpioPinVal(module, 128, ref resvet); }                     else { MCP2210.M_Mcp2210_SetGpioPinVal(module, 0, ref resvet); }                     //повторяем это все пока не надоест с такой вот паузой                     System.Threading.Thread.Sleep(100);                 }             }

Демонстрация работы данного кода в видео! 

В коде видно, что появились функции SetGpioConfig и SetSpiConfig. Именно эти функции настраивают модуль, после чего простенькой функцией xferSpiData происходит обмен данными. Да, функция Change выглядит следующим образом:

         static void Сhange(ref uint work, ref uint svetik)         {             if (work == 0)             {                 work = 1;                 svetik = 0;             }             else             {                 work = 0;                 svetik = 1;             }         }

Итак, вот собственно и все! Работать с модулем MCP2210 Breakout Module не так уж и сложно! Если у вас появились вопросы задавайте или читайте datasheet на MCP2210. Там все очень хорошо и подробно описано. Все необходимые файлы я аккуратно упаковал в архив и приложил к статье. Так что, дерзайте!