PIClist RUS
микроконтроллеры PIC и интерфейсы
техническая документация
статьи и разработки на русском языке

64-мегабитная MMC-карта и PIC-микроконтроллер

« назад на главную страницу

Оригинал: M. Dworkin, "64MB MMC und PIC-Mikrocontroller"

Скачать "64-мегабитная MMC-карта и PIC-микроконтроллер" в формате PDF

Перевод с немецкого © PIClist-RUS (piclist.ru)



Здесь рассматривается запись-чтение карты памяти MMC с помощью PIC16F877 по SPI-интерфейсу (64-мегабайтная MMC и PIC-микроконтроллер). Программная реализация SPI-интерфейса даёт возможность подключить одну карту MMC к любому PIC-микроконтроллеру.

В статье приводятся электрическая схема, теория по интерфейсу SPI, теория по MMC, сигнальные диаграммы, программа на Си (компилятор CC5X).

+

Характеристики MMC-карты на 64 Мб:
- огромная FLASH-память
- очень быстрая
- 300 000 циклов записи
- чтение без ограничений
- связь с PIC по 4 линиям
 Характеристики PIC16F877:
- SPI-интерфейс
- RS232-интерфейс
- 8 входов для АЦП (10 бит)

ВыводОбозначениеФункцияВыводОбозначениеФункция
1/CSВыбор микросхемы18RC2Цифровой выход
2Data INВход данных24SDOВыход данных SPI
3GNDОбщий минус-- 
4VddПитающее напряжение-- 
5CLKСинхронизация18SCLСинхронизация SPI
6GNDОбщий минус-- 
7Data OUTВыход данных23SDIВход данных SPI


Схема включения и электрическая схема

Для MMC необходимо питающее напряжение в диапазоне 2.7 – 3.6 В. В любом случае мы должны использовать стабилизатор напряжения для 3.3 В, например, CS5203. PIC-микроконтроллер может работать в диапазоне напряжений от 2 до 5.5 В. Таким образом, можно сойтись на снабжении обеих микросхем питанием 3.3 В. В этом случае можно подключить MMC непосредственно к микроконтроллеру.

Исходя из соображений, что АЦП и последовательная связь при 5 В функционируют более стабильно, PIC16F877 всё-таки питается в этой схеме от 5 В. Выходы микроконтроллера SDO, SCL, /CS подключены через делители напряжения, так что на входы MMC подаётся напряжение не более 3.2 В. Входы микроконтроллера не нуждаются в каком-либо усилении с 3.3 до 5 В, так как PIC всё равно понимает 3.3 В как логическую «1».

Увеличить рисунок

Рис. 1. Схема электрическая

MAX232 используется для обеспечения последовательной связи с компьютером (на скорости 115200 бод).

Для подключения к MMC в качестве переходника прекрасно подходит старый разъём от флоппи-дисковода (см. Рис. 2 ниже), либо можно использовать предлагаемый http://www.segor.de так называемый «MMC-разъём» ("MMC-Connector") за 4.90 евро.

Рис. 2. Разъём для MMC из разъёма для флоппи-дисковода


Как, собственно, функционирует SPI?

SPI - это последовательный синхронный интерфейс. Синхронным он называется потому что каждый бит принимается /передаётся во время тактового импульса.

Рис. 3.Приём и передача байта по интерфейсу SPI

На Рис. 3 мы видим регистр, через который передаётся и принимается каждый байт. Здесь изображён момент, когда уже произошли два тактовых импульса, и биты 7 и 6 выданы на линию OUT. Одновременно принимаются 2 бита (также 7 и 6) нового байта. После 8 тактовых импульсов посылаемый байт окажется полностью «снаружи», а принимаемый байт будет полностью загружен в регистр. Если PIC работает как мастер (ведущий), он сам генерирует тактовые импульсы, в которых нуждается ведомое устройство, чтобы своевременно сдвигать регистр и таким образом быть в состоянии принимать/передавать правильные биты. В PIC-микроконтроллере таким регистром является регистр SSPBUF, в который и помещается один байт, чтобы он начал его передавать, а новый принимать. Однако, нельзя слишком рано считывать SSPBUF (пока данные сдвигаются). Поэтому мы проверяем флаг BF, который установлен во время процесса передачи.

MMC-карты могут работать на тактовой частоте до 20 МГц (CLK). Интерфейс SPI PIC-микроконтроллера может настраиваться максимально на 5 МГц. Однако, если PIC соединяется с MMC длинными проводниками, то тактовую частоту следует снизить, иначе форма сигнала исказится, и это приведёт к ошибкам. (У меня провода длиной 15 см.)

Временная диаграмма на Рис. 4 показывает возможности настройки интерфейса SPI на PIC (красным цветом подчёркнуты значения битов CKP, CKE и SMP, которые нужно установить в PIC-микроконтроллере для работы по SPI с MMC, и соответствующие им временные диаграммы).

Рис. 4.Временные диаграммы различных режимов SPI


Инициализация MMC в режиме SPI

Примечание: на схемах, приведённых ниже, ТИ – тактовый импульс, N – неопределённое количество.

Сброс (CMD0)


0. Подача напряжения
1. Посылка 80 тактовых импульсов
2. Активация сигнала /CS, т.е. /CS=0 (так как активным уровнем является 0)
3. Посылка команды CMD0
4. Байт ответа = 0x01? Если нет – ОШИБКА, если да – шаг 5
5. Посылка 8 тактовых импульсов

Инициализация (CMD1)


6. Посылка команды CMD1
7. Байт ответа = 0x00? Если нет – вернуться на шаг 6, если да – перейти к шагу 8.
8. Посылка 8 тактовых импульсов.

Инициализация MMC в режиме SPI завершена.

Рабочая программа, функциональное описание

SerString("Hallo Welt")Эта функция служит для выдачи сообщений.
while(!TXIF); //Проверка, пуст ли регистр TXREG
TXREG ='W'; //Последовательная передача буквы "W"
Эти команды используются для последовательной передачи символов.
a=SPI(b);Функция передаёт символ b и принимает символ в переменную a.
Command(0x49,0,512,0xFF );Передаёт в MMC команду и адрес.
MMC_Init()Здесь настраивается SPI, выполняется сброс MMC и инициализация MMC в режиме SPI.

#include 
// Speicherschutz 12-13-4-5=выкл., Debug 11=выкл.,
//ProgrammFlash 9=вкл., EEpromRead 8=вкл., NiederVoltProgr 7=выкл.
// NiederVoltReset 6=вкл., EinschaltTimer 3=вкл., WachDogTimer 2=выкл., Oszilator 01=XC
#pragma config |= 0b.11.111101.11.00.10

#pragma bit CS @ PORTC.2        //Выход для выбора микросхемы (сигнала CS)

#pragma origin 100              //С адреса 100 в программной памяти
//*********************************************************************

void InitUSART()
{
BRGH=1;                 // Высокая скорость передачи данных
//SPBRG=129;            // (9600 бод при входной тактовой частоте 20 МГц)
//SPBRG=64;             // (19200 бод при входной тактовой частоте 20 МГц)
//SPBRG=32;             // (38400 бод при входной тактовой частоте 20 МГц)
SPBRG=10;               // (115200 бод при входной тактовой частоте 20 МГц)
SPEN = 1;               // Set_Serial_Pins;
SYNC = 0;               // Set_Async_Mode;
TX9 = 0;                // Set_8bit_Tx;
RX9 = 0;                // Set_8bit_Rx;
CREN = 1;               // Enable_Rx;
TXEN = 1;               // Enable_Tx;
RCIE=0;                 // Выключить прерывание от Rx
}
//**********************************************************************

void SerString(const char *str) // Последовательная передача строки
{
char ps;
ps = *str;              // Указатель на начало строки в ps
while(ps>0)             // Проверка, не достигнут ли конец строки
        {
        str++;                  // Увеличение указателя для доступа к следующему символу
        if (ps== 0) break;      // Проверка, не достигнут ли конец строки
        while(!TXIF);           // Проверка, свободен ли регистр TXREG
        TXREG =ps ;             // Передача байта данных
        ps = *str;              // Запоминаем содержание указателя в ps
        }
}
//********************************************************************

char SPI(char d)                // Передача по SPI-интерфейсу
{
SSPBUF=d;
while(!BF);                    // Ожидание окончания передачи
return SSPBUF;                  // и одновременно принимаем
}
//**********************************************************************

char Command(char befF,uns16 AdrH,uns16 AdrL,char befH )
{                               // Передача команды в MMC
char a;
SPI(0xFF);
SPI(befF);
SPI(AdrH.high8);
SPI(AdrH.low8);
SPI(AdrL.high8);
SPI(AdrL.low8);
SPI(befH);
SPI(0xFF);
return SPI(0xFF);               // Возвращаем ответ
}
//**************************************************************************

bit MMC_Init()
{
// Инициализация SPI
SMP=0;          // Вход действителен в середине синхроимпульса
CKE=0;          // Приём данных по переднему фронту
CKP=1;          // Высокий уровень – это пассивное состояние
SSPM1=1;        // Скорость f/64(312kHz), Мастер
//SSPM0=1;      // Скорость f/16(1,25MHz), Мастер
SSPEN=1;        // Включить SPI

CS=1;           // MMC отключена

char i;         // Переменные

//MMC стартует в режиме SPI, сброс
for(i=0; i < 10; i++)SPI(0xFF);         // 10*8=80 тактовых импульсов
CS=0;                                   // Включить MMC

// CMD0
if (Command(0x40,0,0,0x95) !=1)goto Fehler ;    // Сброс

st:                                             // Если MMC не существует, остаётся
// CMD1                                         // Здесь находится программа
if (Command(0x41,0,0,0xFF) !=0) goto st ;       // Повторять CMD1 до тех пор, пока
/*
// Считваем CID
if (Command(0x4A,0,0,0xFF) !=0) goto Fehler;    // Идентификационный номер карты
for(i=0; i < 20; i++)
{
while(!TXIF);
TXREG =SPI(0xFF);
}

// Считываем CSD	                              // Специфические данные карты (свойства карты)
if (Command(0x49,0,0,0xFF) !=0) goto Fehler;
for(i=0; i < 20; i++)
{
while(!TXIF);
TXREG =SPI(0xFF);
}
*/
// Установить длину (по умолчанию 512 байтов)
//if (Command(0x50,0,16,0xFF) !=0) goto Fehler; // 16-байтовый режим для чтения

return 1;
Fehler:
return 0;
}
//**************************************************************************

void main(void)
{
INTCON=0;                               // Отключить прерывания
ADCON1=0x6;                             // PortA как цифровые выходы
TRISC=0b.1101.0011;                     // sck rc3-0, sdo rc5-0, CS rc2-0.
TRISB=0b.0000.0010;                     // RB2>TX, RB1>RX
uns16 i;                                // Переменная 0...65535
InitUSART();                            // Инициализация последовательной передачи данных
SerString("Ich bin ON ");               // Стартовое сообщение
if (MMC_Init()) SerString("MMC ON ");   // Инициализация MMC и сообщение, если всё нормально!
//******************************************************************************

// 512-байтовый режим чтения
if (Command(0x51,0,512,0xFF) !=0) SerString("Lese_resp_Fehler ");
while(SPI(0xFF) != 0xFE);                       // Ожидание 0xFE – начала каждой передачи данных
for(i=0; i < 512; i++)
        {
        while(!TXIF);                           // Проверка, пуст ли регистр TXREG
        TXREG =SPI(0xFF);                       // Передача байта данных
        }
SPI(0xFF);                             // В конце два незначимых байта
SPI(0xFF);
//************************************************************************

// 512-байтовый режим записи
if (Command(0x58,0,512,0xFF) !=0) SerString("Schreib_resp_Fehler ");
SPI(0xFF);
SPI(0xFF);
SPI(0xFE);
for(i=0; i < 512; i++)
        {
        SPI('M');
        }
SPI(255);                               // в конце передаём два незначимых байта
SPI(255);
i=SPI(0xFF);
i &=0b.0001.1111;
if (i != 0b.0000.0101) SerString("Schreib_Fehler");
while(SPI(0xFF) !=0xFF);                // ожидаем окончание состояния занятости.

//**********************************************************************
while(1);                              //здесь программа заканчивается

Выполнение программы

Сначала настраиваются порты.

Затем инициализируется последовательный интерфейс для работы на скорости 115200 бод, без бита паритета, с 1 стоп-битом, и выдаётся сообщение "Ich bin ON".

Затем выполняется инициализация MMC; если она успешна, выдаётся сообщение "MMC ON".

Далее 512 байтов считываются и передаются по последовательной связи в ПК.

Затем записываются 512 байтов с буквой "М".

Запись и чтение выполняются с адреса 512. С адреса 512 начинается зарезервированная область, отформатированная под FAT16, так что сохраняются даже данные и файловая система на вашей карте MMC.

При ошибках могут выдаваться следующие сообщения:

- Lese_resp_Fehler - нет ответа на команду чтения.

- Schreib_resp_Fehler – нет ответа на команду записи.

- Schreib_Fehler – нет подтверждения после записи.

С этой программой можно читать и записывать данные по любому адресу. Можно устанавливать любую величину блока чтения.

Ниже приведены временные диаграммы процесса чтения и процесса записи.

Чтение

Запись

Скачать: Электрическую схему + Исходный код + HEX-файл (с сайта автора).

Программный интерфейс SPI

Не все типы PIC имеют интерфейс SPI, поэтому я написал подпрограмму, которая делает возможной связь по SPI с любым PIC-микроконтроллером. В программе можно свободно выбирать выводы для подключения MMC.

Этот выбор происходит в начале программы:

#pragma bit CS @ PORTC.2                // Выход для выбора микросхемы (CS)
#pragma bit SCK @ PORTC.3               // Выход синхронизации
#pragma bit SDO @ PORTC.5               // Выход выходящих данных
#pragma bit SDI @ PORTC.4               // Вход входящих данных

Не забудьте настроить входы/выходы соответствующим образом!

TRISC=0b.1101.0011;             // SCK rc3-0, SDO rc5-0, CS rc2-0

Конечно, можно взять любой порт и выводы!

Функция char SPI(char d) заменяется на:

char SPI(char out)              // Частота программного SPI примерно 620 КГц
{
char in,i;
for (i=0;i<8;i++)
        {
        nop2();
        SCK=0;                  // Задний фрон синхроимпульса
        nop();
        SDO=out.7;              // Подготавливаются данные
        nop();
        out=out<<1;
        nop2();                 // Задержка, чтобы дать ведомому возможность подготовить данные
        in=in<<1;
        SCK=1;                  // Передний фрон синхроимпульса
        nop();
        in.0=SDI;               // Считывание данных
        }
return in;
}

При более низких тактовых частотах программа тоже работает, только медленнее.

MMC можно подключить к: PIC16F870, PIC16F871, PIC16F872, PIC16F873, PIC16F874, PIC16F876, PIC16F877, PIC16F84, PIC12F675, PIC12F629.

Здесь находится программа для тестирования: программный SPI-интерфейс в MMC (с сайта автора). Она приспособлена для PIC16F877, так как я не хотел менять аппаратную часть.

Открытые вопросы

- MMC может записывать только блоки по 512 байтов, где я должен буферизовать их?

- Как могу я использовать FAT-таблицу, чтобы считать собранный файл из MMC-кард-ридера?

Я ищу прямой ответ на эти вопросы. Если что-то придёт мне на ум, я помещу это здесь, в рамках моей Web-страницы.

Нужна ли промежуточная буферизация?

Это не нужно, так как каждый байт можно передавать в MMC с любой скорость, даже 1 байт в час. Только они будут записаны в память лишь после 512 байтов.

FAT

Описание системы FAT, чтения MMC с системой FAT16, программа-пример (на сайте автора).



© PIClist-RUS (piclist.ru), 2007 г.

PIClist RUS (piclist.ru) © 2008
все права сохранены. перепечатка статей и переводов с данного сайта запрещена.