В предыдущей статье мы рассмотрели преобразователь 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, то нужно использовать файл с буквой m — 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-х байтов в одно число 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. Там все очень хорошо и подробно описано. Все необходимые файлы я аккуратно упаковал в архив и приложил к статье. Так что, дерзайте!
Прикрепленные файлы:
- MCP2210.rar (3457 Кб)