Giao tiếp card MMC ?

Collapse
X
 
  • Giờ
  • Show
Clear All
new posts
  • doianhve
    Đệ tử 2 túi
    • Feb 2006
    • 43

    #1

    Giao tiếp card MMC ?

    Xin chào các cao thủ.Tôi đang nghiên cứu giao tiếp card MMC thông qua chuẩn truyền SPI mà thấy khó ghê.Ai có tài liệu hay kinh nghiệm gì share tôi với.Thanks.
    đã cháy đến con PIC thứ 100. Oh my god !

  • falleaf
    PIC Bang chủ
    • May 2005
    • 2627

    #2
    Card đó tên tuổi là gì? SPI thì cơ bản phải xem nó mắc dây như thế nào, và nó cho phép chuẩn như thế nào. Còn mọi thứ thì oki thôi, nên phải có cái datasheet về cái card thì mới biết được.

    Chúc vui
    Công ty TNHH Thương mại và Giao nhận R&P
    store.hn@rpc.vn - store.hcm@rpc.vn

    Học PIC như thế nào?

    Comment

    • doianhve
      Đệ tử 2 túi
      • Feb 2006
      • 43

      #3
      Xin chào mội người.Tôi dùng thẻ MMC64MB của Samung.Giao Tiếp SPI.Data Sheet thi tìm trên mạng .Nhiều lắm.
      đã cháy đến con PIC thứ 100. Oh my god !

      Comment

      • doianhve
        Đệ tử 2 túi
        • Feb 2006
        • 43

        #4
        code tham khảo

        Để cho việc thảo luận sôi nổi tôi xin đưa ra kết quả sơ bộ cho mọ người tham khảo.Đây là mã code tôi dùng để xử lý Card.Xin nói qua là code dùng một phần thư viện có sẵn LCD.c của CCS để kiểm tra dữ liệu.Tôi dùng Proteus nhưng chưa mô phỏng được.bạn cần mạch thật.
        Cần chú ý:
        +LCD sử dụng bit:
        // D0 enable
        // D1 rs
        // D2 rw
        // D4 D4
        // D5 D5
        // D6 D6
        // D7 D7
        +MMC nối dúng chuẩn SPI có sẵn trên PIC và chon Pin_C2 làm chân CE
        Mọi nguoi Down ve và cho ý kiến nhé.Tôi dùng code của Microchip và đã sửa lỗi chạy thử.
        đã cháy đến con PIC thứ 100. Oh my god !

        Comment

        • doianhve
          Đệ tử 2 túi
          • Feb 2006
          • 43

          #5
          -----file chinh-----------
          Code:
          #include <E:\Read_Card\16F877.h> // da doi thu tu PortD de phu hop mach in
          #fuses HS,NOWDT,NOPROTECT,NOLVP
          #use delay(clock=20000000)
          #use rs232(baud=9600, xmit=PIN_A3, rcv=PIN_A2)  // Jumpers: 11 to 17, 12 to 18
          #include <E:\Read_Card\lcd_driver.c>
          #include <E:\Read_Card\spi.c>
          void main() {
             int Kiem_Tra;
             kiem_tra=1;
             lcd_init();
             //setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);
             //F la khoi xoa man hinh va ghi tu dong 1
             //n la xuong dong
             while(true)
             {
                kiem_tra=mmc_init();
                lcd_putc("\fChan doi qua 456\n");
                if (!kiem_tra)
                {
                      lcd_putc("Wait...\n");
                      mmc_write_block(100);
                      mmc_read_block(100);
                }
          
                 delay_ms(2000);
             }
          
          }
          Last edited by bien_van_khat; 08-07-2007, 11:11 PM.
          đã cháy đến con PIC thứ 100. Oh my god !

          Comment

          • doianhve
            Đệ tử 2 túi
            • Feb 2006
            • 43

            #6
            Code:
            -----------------------lcd_driver.c---------------
            
            // As defined in the following structure the pin connection is as follows:
            //     D0  enable
            //     D1  rs
            //     D2  rw
            //     D4  D4
            //     D5  D5
            //     D6  D6
            //     D7  D7
            //
            //   LCD pins D0-D3 are not used and PIC D3 is not used.
            
            // Un-comment the following define to use port B
            // #define use_portb_lcd TRUE
            struct lcd_pin_map {                 // This structure is overlayed
                       BOOLEAN enable;           // on to an I/O port to gain
                       BOOLEAN rs;               // access to the LCD pins.
                       BOOLEAN rw;               // The bits are allocated from
                       BOOLEAN unused;           // low order up.  ENABLE will
                       int     data : 4;         // be pin B0.
                    } lcd;
            
            
            #if defined(__PCH__)
            #if defined use_portb_lcd
               #byte lcd = 0xF81                   // This puts the entire structure
            #else
               #byte lcd = 0xF83                   // This puts the entire structure
            #endif
            #else
            #if defined use_portb_lcd
               #byte lcd = 6                  // on to port B (at address 6)
            #else
               #byte lcd = 8                 // on to port D (at address 8)
            #endif
            #endif
            
            #if defined use_portb_lcd
               #define set_tris_lcd(x) set_tris_b(x)
            #else
               #define set_tris_lcd(x) set_tris_d(x)
            #endif
            
            
            #define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
            #define lcd_line_two 0x40    // LCD RAM address for the second line
            
            
            BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
                                         // These bytes need to be sent to the LCD
                                         // to start it up.
            
            
                                         // The following are used for setting
                                         // the I/O port direction register.
            
            struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
            struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in
            
            
            
            BYTE lcd_read_byte() {
                  BYTE low,high;
                  set_tris_lcd(LCD_READ);
                  lcd.rw = 1;
                  delay_cycles(1);
                  lcd.enable = 1;
                  delay_cycles(1);
                  high = lcd.data;
                  lcd.enable = 0;
                  delay_cycles(1);
                  lcd.enable = 1;
                  delay_us(1);
                  low = lcd.data;
                  lcd.enable = 0;
                  set_tris_lcd(LCD_WRITE);
                  return( (high<<4) | low);
            }
            
            
            void lcd_send_nibble( BYTE n ) {
                  lcd.data = n;
                  delay_cycles(1);
                  lcd.enable = 1;
                  delay_us(2);
                  lcd.enable = 0;
            }
            
            
            void lcd_send_byte( BYTE address, BYTE n ) {
            
                  lcd.rs = 0;
                  while ( bit_test(lcd_read_byte(),7) ) ;
                  lcd.rs = address;
                  delay_cycles(1);
                  lcd.rw = 0;
                  delay_cycles(1);
                  lcd.enable = 0;
                  lcd_send_nibble(n >> 4);
                  lcd_send_nibble(n & 0xf);
            }
            
            
            void lcd_init() {
                BYTE i;
                set_tris_lcd(LCD_WRITE);
                lcd.rs = 0;
                lcd.rw = 0;
                lcd.enable = 0;
                delay_ms(15);
                for(i=1;i<=3;++i) {
                   lcd_send_nibble(3);
                   delay_ms(5);
                }
                lcd_send_nibble(2);
                for(i=0;i<=3;++i)
                   lcd_send_byte(0,LCD_INIT_STRING[i]);
            }
            
            
            void lcd_gotoxy( BYTE x, BYTE y) {
               BYTE address;
            
               if(y!=1)
                 address=lcd_line_two;
               else
                 address=0;
               address+=x-1;
               lcd_send_byte(0,0x80|address);
            }
            
            void lcd_putc( char c) {
               switch (c) {
                 case '\f'   : lcd_send_byte(0,1);
                               delay_ms(2);
                                                       break;
                 case '\n'   : lcd_gotoxy(1,2);        break;
                 case '\b'   : lcd_send_byte(0,0x10);  break;
                 default     : lcd_send_byte(1,c);     break;
               }
            }
            
            char lcd_getc( BYTE x, BYTE y) {
               char value;
            
                lcd_gotoxy(x,y);
                while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
                lcd.rs=1;
                value = lcd_read_byte();
                lcd.rs=0;
                return(value);
            }
            Last edited by bien_van_khat; 08-07-2007, 11:10 PM.
            đã cháy đến con PIC thứ 100. Oh my god !

            Comment

            • doianhve
              Đệ tử 2 túi
              • Feb 2006
              • 43

              #7
              Code:
              -------------------------------SPI.c-------------------------
              // for the original source, and hundreds more examples of PIC C code, see:
              // [url]http://www.microchipc.com/sourcecode/#mmc[/url]
              int8 Nhay_dong;
              char str[80];
              int mmc_init();
              int mmc_response(unsigned char response);
              int mmc_read_block(unsigned long block_number);
              int mmc_write_block(unsigned long block_number);
              int mmc_get_status();
              
              
              /************************** MMC Init **************************************/
              /* Initialises the MMC into SPI mode and sets block size, returns 0 on success */
              
              int mmc_init()
              {
              int i;
              
              SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_SS_DISABLED);
              
              *0x94 |= 0x40;                          // set CKE = 1 - clock idle low
              *0x14 &= 0xEF;                          // set CKP = 0 - data valid on rising edge
              
              OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
              
              for(i=0;i<10;i++)                       // initialise the MMC card into SPI mode by sending clks on
              {
                      SPI_WRITE(0xFF);
              }
              
              OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on) tells card to go to spi mode when it receives reset
              
              SPI_WRITE(0x40);                        // send reset command
              SPI_WRITE(0x00);                        // all the arguments are 0x00 for the reset command
              SPI_WRITE(0x00);
              SPI_WRITE(0x00);
              SPI_WRITE(0x00);
              SPI_WRITE(0x95);                        // precalculated checksum as we are still in MMC mode
              
              lcd_putc("\fSent go to SPI\n\r");
              
              if(mmc_response(0x01)==1) return 1;     // if = 1 then there was a timeout waiting for 0x01 from the mmc
              
              lcd_putc("Got response from MMC\n\r");
              
              i = 0;
              
              while((i < 255) && (mmc_response(0x00)==1))     // must keep sending command if response
              {
                      SPI_WRITE(0x41);                // send mmc command one to bring out of idle state
                      SPI_WRITE(0x00);                // all the arguments are 0x00 for command one
                      SPI_WRITE(0x00);
                      SPI_WRITE(0x00);
                      SPI_WRITE(0x00);
                      SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
                      i++;
              }
              if(i >= 254) return 1;                   // if >= 254 then there was a timeout waiting for 0x00 from the mmc
              
              lcd_putc("\fGot out of idle response from MMC\n\r");
              
              OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
              
              SPI_WRITE(0xFF);                        // extra clocks to allow mmc to finish off what it is doing
              
              OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)
              
                      SPI_WRITE(0x50);                // send mmc command one to bring out of idle state
                      SPI_WRITE(0x00);
                      SPI_WRITE(0x00);
                      SPI_WRITE(0x02);                // high block length bits - 512 bytes
                      SPI_WRITE(0x00);                // low block length bits
                      SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
              
              if((mmc_response(0x00))==1) return 1;
              OUTPUT_HIGH(PIN_C2);            // set SS = 1 (off)
              lcd_putc("\fGot set block length response from MMC\n\r");
              return 0;
              }
              
              /************************** MMC Get Status **************************************/
              /* Get the status register of the MMC, for debugging purposes */
              
              int mmc_get_status()
              {
              
              OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)
              
                      SPI_WRITE(0x58);                // send mmc command one to bring out of idle state
                      SPI_WRITE(0x00);
                      SPI_WRITE(0x00);
                      SPI_WRITE(0x00);                //
                      SPI_WRITE(0x00);                // always zero as mulitples of 512
                      SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
              
              OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
              return 0;
              }
              
              /************************** MMC Write Block **************************************/
              int mmc_write_block(unsigned long block_number)
              {
              unsigned long i;
              unsigned long varh,varl;
              
              varl=((block_number&0x003F)<<9);
              varh=((block_number&0xFFC0)>>7);
              
              puts("Write block\n\r");                // block size has been set in mmc_init()
              
              OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)
              
                      SPI_WRITE(0x58);                // send mmc write block
                       /*
                      SPI_WRITE(HIGH(varh));
                      SPI_WRITE(LOW(varh));
                      SPI_WRITE(HIGH(varl));
                      */
                      SPI_WRITE(0x1001);      // arguments are address
                      SPI_WRITE(0x1011);
                      SPI_WRITE(0x100);
                      SPI_WRITE(0x00);                // always zero as mulitples of 512
                      SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
              
              if((mmc_response(0x00))==1) return 1;
              puts("Got response to write block\n\r");
              
              SPI_WRITE(0xFE);                        // send data token
              //----------------Ghi du lieu vao MMC-----------------
                    strcpy(str,"Nguyen Duc Hung_Dl1_K47_DHBKHN");   ///Ghi vao the nho
                    nhay_dong=0;
                    for(i=0;i<512;i++)
                    {
                          ++nhay_dong;
                          SPI_WRITE(str[Nhay_Dong]);     // send data
                          if (nhay_dong>=32)
                          {
                             nhay_dong=0;
                          }
                    }
              
              SPI_WRITE(0xFF);                        // dummy CRC
              SPI_WRITE(0xFF);
              
              if((SPI_READ(0xFF)&0x0F)!=0x05) return 1;
              
              puts("Got data response to write block\n\r");
              
              OUTPUT_HIGH(PIN_C2);                    // set SS = 1 (off)
              return 0;
              }
              
              
              
              /************************** MMC Read Block **************************************/
              /**** Reads a 512 Byte block from the MMC and outputs each byte to RS232 ****/
              int mmc_read_block(unsigned long block_number)
              {
              unsigned long i;
              unsigned long varh,varl;
              
              varl=((block_number&0x003F)<<9);
              varh=((block_number&0xFFC0)>>7);
              
              OUTPUT_LOW(PIN_C2);                     // set SS = 0 (on)
              
                      SPI_WRITE(0x51);                // send mmc read single block command
                      SPI_WRITE(0x1001);      // arguments are address
                      SPI_WRITE(0x1011);
                      SPI_WRITE(0x100);
                      SPI_WRITE(0x00);
                      SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
              
              if((mmc_response(0x00))==1) return 1;   // if mmc_response returns 1 then we failed to get a 0x00 response (affirmative)
              
              lcd_putc("Got response to read block command\n\r");
              
              if((mmc_response(0xFE))==1) return 1;   // wait for data token
              
              //---------------------------------------doc tu the len-------------------
                       nhay_dong=0;
                      lcd_putc("\fGot data token\n\r");
                      lcd_putc("\f");   //Xoa Man Hinh
                      for(i=0;i<512;i++)
                      {
                              ++nhay_dong;
                              lcd_putc(SPI_READ(0xFF));               // we should now receive 512 bytes
              
                               if (nhay_dong==16)
                              {
                                    lcd_putc("\n");
                                    lcd_putc(SPI_READ(0xFF));               // we should now receive 512 bytes
                              }
                                  if (nhay_dong>=31)
                              {
                                    lcd_putc("\n");
                                    nhay_dong=0;
                                    lcd_putc("\f");
                              }
                              delay_ms(100);
                      }
              
              SPI_READ(0xFF);                 // CRC bytes that are not needed
              SPI_READ(0xFF);
              
              OUTPUT_HIGH(PIN_C2);            // set SS = 1 (off)
              SPI_WRITE(0xFF);                // give mmc the clocks it needs to finish off
              
              lcd_putc("End of read block");
              
              return 0;
              }
              
              /************************** MMC get response **************************************/
              /**** Repeatedly reads the MMC until we get the response we want or timeout ****/
              
              int mmc_response(unsigned char response)
              {
                      unsigned long count = 0xFFFF;           // 16bit repeat, it may be possible to shrink this to 8 bit but there is not much point
              
                      while(SPI_READ(0xFF) != response && --count > 0);
              
                      if(count==0) return 1;                  // loop was exited due to timeout
                      else return 0;                          // loop was exited before timeout
              }
              Last edited by bien_van_khat; 08-07-2007, 11:09 PM.
              đã cháy đến con PIC thứ 100. Oh my god !

              Comment

              • doianhve
                Đệ tử 2 túi
                • Feb 2006
                • 43

                #8
                alo.Ko ai nói j à.Chán ghê.
                đã cháy đến con PIC thứ 100. Oh my god !

                Comment

                • bien_van_khat
                  ...Damned...
                  • Apr 2006
                  • 503

                  #9
                  Các bạn post code thì nên bỏ vào trong thẻ [code] để vậy đọc ko nổi. Lần này mình sửa dùm bạn, nhưng ko có lần sau nhé.

                  Chính xác vấn đề mà bạn gặp phải là gì, mình cũng đã làm MMC ở mode SPI rồi, có gì mình có thể giúp bạn. Vấn đề lớn nhất mà mình gặp phải là cái connector, vì đồ chế nên tiếp xúc ko tốt lúc chạy lúc ko, đành phải hi sinh 1 cái đầu đọc thẻ để tháo mỗi cái connector.
                  Last edited by bien_van_khat; 08-07-2007, 11:14 PM.
                  - Xin đọc trước khi post bài

                  Xin đặt code trong thẻ [ code ] [ /code ]

                  Comment

                  • bluepine
                    Đệ tử 3 túi
                    • Jun 2006
                    • 53

                    #10
                    Nguyên văn bởi doianhve View Post
                    Xin chào các cao thủ.Tôi đang nghiên cứu giao tiếp card MMC thông qua chuẩn truyền SPI mà thấy khó ghê.Ai có tài liệu hay kinh nghiệm gì share tôi với.Thanks.
                    Chào bạn,
                    tôi gửi bạn một số tài liệu tham khảo rất có ích cho bạn khi bắt đầu nghiên cứu MMC card qua giao tiếp SPI. Tôi cũng đang tịm hiểu về MMC card, chúng ta có thể trao đổi thêm.
                    http://elm-chan.org/docs/mmc/mmc_e.html


                    Thân.

                    Comment

                    • batinh
                      Nhập môn đệ tử
                      • May 2006
                      • 7

                      #11
                      tôi sử dụng 18F4550 thì khai báo có gì khác không mà sao làm mấy ngày rồi không đc. SD card với LCD.

                      Comment

                      • quyenemic
                        Đệ tử 1 túi
                        • Aug 2007
                        • 19

                        #12
                        Bài viết hay đó, cảm ơn bạn.
                        Trừu đao đoạn thủy, thủy cánh lưu
                        Cử bôi tiêu sầu, sầu cánh sầu...

                        Comment

                        • byte
                          Nhập môn đệ tử
                          • Nov 2007
                          • 5

                          #13
                          tui chơi quả AVR giao tiếp với thẻ nhớ. Chạy ngon, file đọc được ngon nhưng chẳng biết làm gì với nó cả. trừ file text cho hiển thị lcd. Nói chung viết với Vdk nào thì cũng vậy thôi, có điều là mình làm thế nào thì nó mới đưa cho mình dữ liệu (giải thuật). Để ghi dữ liệu vào hay đọc dữ liệu ra theo một sector thì đơn giản hơn những gì bạn tưởng. Chỉ đến khi nào bạn muốn làm việc với file thì lúc đó vấn đề mới thực sự bắt đầu. Tôi lằng nhằng mãi với cái đống FAT, rdet, sdet, bootsector...mãi mới ra, giờ thì cũng thông rồi. Các bạn cứ làm đi, có gì tôi biết tôi có thể chỉ cho các bạn.
                          Bạn chú ý khi mắc phần cứng, tay MMC làm việc với điện áp 3.3v cho nên bạn đấu cẩn thận. Nguồn 5V cho qua 2 thằng diode mới được đưa vào thẻ nhớ. (5-0.7*2 = 3.4 ~3.3). Mức 1 ở VDK là 5V, khi đưa mức 1 này vào thẻ cũng cần qua cầu phân áp cho nó còn khoảng 3.3 v mới dc. Tôi chưa thử phi 5V vào nên chẳng biết là sẽ có chuyện gì sảy ra. Nhưng nói chung là không nên. Hì hì
                          Bạn đừng hỏi nhiều quá, bắt tay vào làm từ ABC, đến đâu không biết bắt đầu mới hỏi. Như vậy thì mình mới hiểu sâu vấn đề dc.

                          Comment

                          • namqn
                            Trưởng lão PIC bang
                            • Feb 2006
                            • 3020

                            #14
                            Nguyên văn bởi byte View Post
                            ...
                            Nguồn 5V cho qua 2 thằng diode mới được đưa vào thẻ nhớ. (5-0.7*2 = 3.4 ~3.3). ...
                            5 - 0.7*2 = 3.6 chứ. Các giải pháp rẻ tiền tạo nguồn 3.3 V từ nguồn 5 V tôi đã nói ở post #21 trong luồng sau:

                            Theo dự kiến của Microchip, vào khoảng năm 2011 dsPIC sẽ có doanh số lớn hơn PIC


                            Thân,
                            Biển học mênh mông, sức người có hạn.

                            Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
                            http://www.picvietnam.com/forum/showthread.php?t=1263

                            Comment

                            • byte
                              Nhập môn đệ tử
                              • Nov 2007
                              • 5

                              #15
                              hì, quên. Nếu chơi sang làm hẳn con IC gì gì đó về tạo nguồn 3.3V , cái đó tui cũng chưa biết, trước tới giờ toàn chơi 2 chú 1n4007. Hì hì

                              Comment

                              Working...