Доброго времени. Подключил к уно SD и NFC shields. По отдельности всё работает, но вместе - не хочет. Хочу записывать ID карты на флешку. Код (Text): #include "defcard.h" #include <SPI.h> #include <PN532_SPI.h> #include "PN532.h" #include <LiquidCrystal.h> #include <SD.h> #define USED_SERIAL // RS, E, DB5, DB6, DB7, DB8 LiquidCrystal lcd(2, 3, 6, 7, 8, 9); const int SD_pin = 4; const int NFC_pin = 10; int lastSelect_pin = -1; const int init_delay = 2000; char basename[] = "base.dat"; //boolean busy = false; boolean rec_mode = false; PN532_SPI pn532spi( SPI, NFC_pin ); PN532 nfc( pn532spi ); void selectDevice(int pin, boolean init = false ) { if( lastSelect_pin == pin ) return; lastSelect_pin = pin; if( pin == SD_pin ) { digitalWrite( NFC_pin, HIGH ); digitalWrite( SD_pin, LOW ); if( init ) { if(!SD.begin( SD_pin )) { printLCD( 0, 1, "SD Failed"); while(1);// halt; } } } if( pin == NFC_pin ) { digitalWrite( SD_pin, HIGH ); digitalWrite( NFC_pin, LOW ); if( init ) { nfc.begin(); uint32_t versiondata = nfc.getFirmwareVersion(); if( !versiondata ) { printLCD( 0, 1, "NFC Failed");//Didn't find PN53x board while (1); // halt } nfc.SAMConfig(); } } #ifdef USED_SERIAL Serial.print( "selectDevice: " ); if( pin == SD_pin ) Serial.println("SD"); else Serial.println("NFC"); #endif } void printLCD( int x, int y, String str ) { lcd.setCursor( x, y ); lcd.print( str ); #ifdef USED_SERIAL Serial.println( str ); #endif } void RWFile( char * filename ) { File file = SD.open( filename, FILE_WRITE ); if( file ) { file.println("test"); file.close(); printLCD(0,1,"file ok"); }else printLCD(0,1,"file error"); } void setup() { lcd.begin(16, 2); #ifdef USED_SERIAL Serial.begin( 9600 ); #endif pinMode( SD_pin, OUTPUT ); pinMode( NFC_pin, OUTPUT ); printLCD( 1, 0, "Initialization"); selectDevice( SD_pin, true ); printLCD( 0, 1, "SD Ready"); RWFile("setup.txt"); // ЭТА Ф-ИЯ НОРМАЛЬНО РАБОТАЕТ delay( init_delay ); selectDevice( NFC_pin, true ); printLCD( 0, 1, "NFC Ready"); delay( init_delay ); printLCD( 0, 1, "Finish"); delay( init_delay ); lcd.clear(); } void loop(void) { printLCD( 0, 0, "Present the card"); printLCD( 0, 1, " "); CARD card; memset( &card, 0, sizeof(card) ); selectDevice( NFC_pin ); if( nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, card.id, &card.len) ) { String s; for( int i=0; i<8; i++ ) s += String( card.id[i], HEX ); s.toUpperCase(); printLCD( 0,0, s ); //s = String( card.len, DEC ); //printLCD( 0,1, s ); selectDevice( SD_pin ); RWFile("loop.txt"); // А ЗДЕСЬ - НЕТ. SD.open == false } delay( 2000 ); } В коде выполняется одна и та же ф-ия записи на SD 2 раза( в setup и в loop ) RWFile("setup.txt"); RWFile("loop.txt"); соответсвенно. setup - пишет loop - нет. Видимо влияет как-то настройка NFC. Вопрос: что нужно сделать чтобы после настройки NFC работала SD?
Дабы избежать гаданий на кофейной гуще, проще закомментировать код связанный с NFC и проверить записи в loop.txt, и сразу разобраться в вопросе какой код вносит баги. Я с библиотекой SD не знаком, но предположу что функции SD.begin() производят инициализацию требуемых пинов в нужные режимы для работы. SD по своему а NFC по своему, соответственно вызов NFC.begin() перенастраивает их. Таким образом перед записью в loop.txt вам надо вызвать функцию выбора со вторым параметров TRUE чтобы SD снова произвела инициализацию. Попробуйте
Вроде работает: Код (Text): #include "defcard.h" #include <SPI.h> #include <PN532_SPI.h> #include "PN532.h" #include <LiquidCrystal.h> #include <SD.h> #define USED_SERIAL // RS, E, DB5, DB6, DB7, DB8 LiquidCrystal lcd(2, 3, 6, 7, 8, 9); const int SD_pin = 4; const int NFC_pin = 10; int lastSelect_pin = -1; const int init_delay = 2000; char basename[] = "base.dat"; //boolean busy = false; boolean rec_mode = false; PN532_SPI pn532spi( SPI, NFC_pin ); PN532 nfc( pn532spi ); void selectDevice(int pin, boolean init = false ) { if( lastSelect_pin == pin ) return; lastSelect_pin = pin; if( pin == SD_pin ) { digitalWrite( NFC_pin, HIGH ); digitalWrite( SD_pin, LOW ); if( !SD.begin( SD_pin ) && init ) { printLCD( 0, 1, "SD Failed"); while(1);// halt; } } if( pin == NFC_pin ) { digitalWrite( SD_pin, HIGH ); digitalWrite( NFC_pin, LOW ); nfc.begin(); if( init ) { uint32_t versiondata = nfc.getFirmwareVersion(); if( !versiondata ) { printLCD( 0, 1, "NFC Failed");//Didn't find PN53x board while (1); // halt } } nfc.SAMConfig(); } #ifdef USED_SERIAL Serial.print( "selectDevice: " ); if( pin == SD_pin ) Serial.println("SD"); else Serial.println("NFC"); #endif } void printLCD( int x, int y, String str ) { lcd.setCursor( x, y ); lcd.print( str ); #ifdef USED_SERIAL Serial.println( str ); #endif } void RWFile( char * filename ) { File file = SD.open( filename, FILE_WRITE ); if( file ) { file.println("test"); file.close(); printLCD(0,1,"file ok"); }else printLCD(0,1,"file error"); } void setup() { lcd.begin(16, 2); #ifdef USED_SERIAL Serial.begin( 9600 ); #endif pinMode( SD_pin, OUTPUT ); pinMode( NFC_pin, OUTPUT ); printLCD( 1, 0, "Initialization"); selectDevice( NFC_pin, true ); printLCD( 0, 1, "NFC Ready"); delay( init_delay ); selectDevice( SD_pin, true ); printLCD( 0, 1, "SD Ready"); RWFile("setup.txt"); delay( init_delay ); printLCD( 0, 1, "Finish"); delay( init_delay ); lcd.clear(); } void loop(void) { printLCD( 0, 0, "Present the card"); printLCD( 0, 1, " "); CARD card; memset( &card, 0, sizeof(card) ); selectDevice( NFC_pin ); if( nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, card.id, &card.len) ) { String s; for( int i=0; i<8; i++ ) s += String( card.id[i], HEX ); s.toUpperCase(); printLCD( 0,0, s ); //s = String( card.len, DEC ); //printLCD( 0,1, s ); selectDevice( SD_pin ); RWFile("loop.txt"); } delay( 2000 ); } Спасибо!
Не обязательно дергать вручную chip select для SD - библиотека делает это сама когда нужно. Там есть функции: Код (Text): void Sd2Card::chipSelectHigh(void) { digitalWrite(chipSelectPin_, HIGH); } void Sd2Card::chipSelectLow(void) { digitalWrite(chipSelectPin_, LOW); } Насчет nfc не скажу, не смотрел. Но по логике тоже должна. Возможно, библиотеки просто настраивают SPI на разные режимы работы, тогда достаточно оставить только begin в функции выбора устройства, а строчки Код (Text): digitalWrite( NFC_pin, HIGH ); digitalWrite( SD_pin, LOW ); и Код (Text): digitalWrite( SD_pin, HIGH ); digitalWrite( NFC_pin, LOW ); можно убрать. Попробуйте, может получится маленько код сократить.
>> Не обязательно дергать вручную Дёргать всё равно придётся(через метод chipSelect или на прямую digitalWrite) так как одновременно общаться по SPI более чем с одним устройством не получится.
Когда я ковырялся во внутренностях библиотеки SD, видел, что она сама вызывает функции chipSelectHigh и chipSelectLow, когда это необходимо. Если руки дойдут, попробую одновременно с двумя картами поработать, посмотрю, насколько необходимо вручную выбирать чип.