giao tiep voi sd card

Collapse
This is a sticky topic.
X
X
 
  • Giờ
  • Show
Clear All
new posts
  • trachao
    Nhập môn đệ tử
    • Apr 2009
    • 2

    #1

    giao tiep voi sd card

    Minh dang lam giao tiep voi sd card de doc du lieu file mp3 trong the nho' de phat ra am thanh.co' ai biet lam,hoac co' tai lieu ve mon' nay` ko chi giup minh voi'.
  • lcd_amptech
    Đệ tử 2 túi
    • Feb 2008
    • 35

    #2
    @trachao
    Bạn xem ở đây nè, code viet cho atmega8. Sơ đồ kết nối chân như trong định nghĩa trong code nên mình không post sơ đồ mạch lên.
    Tài liệu thì có đầy trên mạng, bạn lên google kiếm.
    http://my.opera.com/lcdamptech

    Comment

    • tahi
      Đệ tử 4 túi
      • Mar 2009
      • 64

      #3
      em đang dính bệnh rất lạ , gửi cmd0 để reset thẻ thì ok, cmd1 để chuyển sang trạng thái data transfer mode cũng ok, nhưng đến lúc gửi lệnh đọc single block (cụ thể là sector 0)thì luôn response về mã lỗi 0x20, là address error. Gửi lệnh đọc các sector khác cũng bị tình trạng tương tự. Không biết bác nào bị bệnh này chưa, cho em hỏi với...

      Comment

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

        #4
        code bạn tự viết hay dùng thư viện. Thư viện và code mẫu cho SD card rất nhiều trên Net, bạn có thể tham khảo thư viện MDD của microchip.

        http://www.microchip.com/stellent/id...cName=en537044
        - Xin đọc trước khi post bài

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

        Comment

        • tahi
          Đệ tử 4 túi
          • Mar 2009
          • 64

          #5
          code tham khảo của bác falleaf (dùng cho chú dsPIC30F4013).Cụ thể là trong thread này:


          Code:
          #define BLOCK_SIZE 512
          unsigned char SD_ReadBlock(unsigned long addr, unsigned char *buf)
          {
          	unsigned int i;
          	unsigned char status;
          	unsigned char CMD17_READ_SINGLE_BLOCK[] = {17,0x00,0x00,0x0,0x00,0xFF};
          	CMD17_READ_SINGLE_BLOCK[1] = ((addr & 0xFF000000) >> 24);
          	CMD17_READ_SINGLE_BLOCK[2] = ((addr & 0x00FF0000) >> 16);
          	CMD17_READ_SINGLE_BLOCK[3] = ((addr & 0x0000FF00) >> 8);
          	CMD17_READ_SINGLE_BLOCK[4] = ((addr & 0x000000FF));
          	SD_Enable();
          	i=0;
          	do
          	{	
          		status = SD_WriteCommand(CMD17_READ_SINGLE_BLOCK);
          		send_hex(status,"CMD17:");	
          		if(i++ > 50)
          		{	
          			putsUART1((unsigned int*)"Read sector failed\n\r");
          			break;
          		}
          	}
          	while(status != 0x00);
          	//Waif
          	Delay_Us(150);
          	// Send the read command
          	if(status != 0)
          	{
          		// ABORT: invalid response for read single command
          		return 1;
          	}
          	// Now wait for the "Start Block" token	(0xFE)
          	// (see SanDisk SD Card Product Manual v1.9 section 5.2.4. Data Tokens)
          	do
          	{
          		status = SPIRead();
          		send_hex(status,"waitf token:");
          	} while(status != 0xFE);
          	// Read off all the bytes in the block
          	for(i = 0; i < BLOCK_SIZE; ++i)
          	{
          		status = SPIRead();
          		*buf = status;
          		buf++;
          	}	
          	// Read CRC bytes
          	status = SPIRead();
          	status = SPIRead();
          	SD_Disable();
          	// Following a read transaction, the SD Card needs 8 clocks after the end 
          	// bit of the last data block to finish up its work.
          	// (from SanDisk SD Card Product Manual v1.9 section 5.1.8)
          	SPIWrite(0xFF); 
          	return 0;
          }
          trong main
          status = SD_ReadBlock(0, buffer);
          Hàm SD_WriteCommand vẫn giữ nguyên. Hàm read đã có write dummy data (write FF)
          Còn lệnh nào có response R1 mà test đuợc không nhỉ. Tốc độ giao tiếp phụ thuộc thế nào với các loại thẻ khác nhau.
          Khởi tạo thẻ nhớ với tốc độ 150k, gửi lệnh cmd0 để reset thẻ, R1 = 0x01 (ok..đã in idle state). Sau đó gửi lệnh cmd1 để vào data transfer mode. Chuyển tốc độ lên 1.25MHz. R1 = 0x00 (đã vào mode transfer)
          Sau đó gửi lệnh CMD17 để đọc single block thì toàn response 0x20
          Ở đây em chỉ đọc 512 byte bắt đầu từ địa chỉ 0x00, không biết đó có phải sector 0 hay ko. (em đã quét cả dải địa chỉ mà vẫn báo về như thế...)
          CRC có chú ý gì ko?

          Comment

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

            #6
            Nguyên văn bởi tahi View Post
            code tham khảo của bác falleaf (dùng cho chú dsPIC30F4013).Cụ thể là trong thread này:


            Code:
            #define BLOCK_SIZE 512
            unsigned char SD_ReadBlock(unsigned long addr, unsigned char *buf)
            {
            	unsigned int i;
            	unsigned char status;
            	unsigned char CMD17_READ_SINGLE_BLOCK[] = {17,0x00,0x00,0x0,0x00,0xFF};
            	CMD17_READ_SINGLE_BLOCK[1] = ((addr & 0xFF000000) >> 24);
            	CMD17_READ_SINGLE_BLOCK[2] = ((addr & 0x00FF0000) >> 16);
            	CMD17_READ_SINGLE_BLOCK[3] = ((addr & 0x0000FF00) >> 8);
            	CMD17_READ_SINGLE_BLOCK[4] = ((addr & 0x000000FF));
            	SD_Enable();
            	i=0;
            	do
            	{	
            		status = SD_WriteCommand(CMD17_READ_SINGLE_BLOCK);
            		send_hex(status,"CMD17:");	
            		if(i++ > 50)
            		{	
            			putsUART1((unsigned int*)"Read sector failed\n\r");
            			break;
            		}
            	}
            	while(status != 0x00);
            	//Waif
            	Delay_Us(150);
            	// Send the read command
            	if(status != 0)
            	{
            		// ABORT: invalid response for read single command
            		return 1;
            	}
            	// Now wait for the "Start Block" token	(0xFE)
            	// (see SanDisk SD Card Product Manual v1.9 section 5.2.4. Data Tokens)
            	do
            	{
            		status = SPIRead();
            		send_hex(status,"waitf token:");
            	} while(status != 0xFE);
            	// Read off all the bytes in the block
            	for(i = 0; i < BLOCK_SIZE; ++i)
            	{
            		status = SPIRead();
            		*buf = status;
            		buf++;
            	}	
            	// Read CRC bytes
            	status = SPIRead();
            	status = SPIRead();
            	SD_Disable();
            	// Following a read transaction, the SD Card needs 8 clocks after the end 
            	// bit of the last data block to finish up its work.
            	// (from SanDisk SD Card Product Manual v1.9 section 5.1.8)
            	SPIWrite(0xFF); 
            	return 0;
            }
            trong main
            status = SD_ReadBlock(0, buffer);
            Hàm SD_WriteCommand vẫn giữ nguyên. Hàm read đã có write dummy data (write FF)
            Còn lệnh nào có response R1 mà test đuợc không nhỉ. Tốc độ giao tiếp phụ thuộc thế nào với các loại thẻ khác nhau.
            Khởi tạo thẻ nhớ với tốc độ 150k, gửi lệnh cmd0 để reset thẻ, R1 = 0x01 (ok..đã in idle state). Sau đó gửi lệnh cmd1 để vào data transfer mode. Chuyển tốc độ lên 1.25MHz. R1 = 0x00 (đã vào mode transfer)
            Sau đó gửi lệnh CMD17 để đọc single block thì toàn response 0x20
            Ở đây em chỉ đọc 512 byte bắt đầu từ địa chỉ 0x00, không biết đó có phải sector 0 hay ko. (em đã quét cả dải địa chỉ mà vẫn báo về như thế...)
            CRC có chú ý gì ko?
            Bạn sử dụng trình dịch gì?
            - Xin đọc trước khi post bài

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

            Comment

            • tahi
              Đệ tử 4 túi
              • Mar 2009
              • 64

              #7
              MPLAB IDE 8.36 với C30 version 3.20

              Loại thẻ nào có thể ăn với lệnh CMD55+ACMD41...Em gửi lệnh này sau khi đã reset thẻ thì nó báo về
              R1 = 0x05 (illegal command + in idle state)

              Comment

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

                #8
                Nguyên văn bởi tahi View Post
                MPLAB IDE 8.36 với C30 version 3.20

                Loại thẻ nào có thể ăn với lệnh CMD55+ACMD41...Em gửi lệnh này sau khi đã reset thẻ thì nó báo về
                R1 = 0x05 (illegal command + in idle state)
                Chỉ có SD card mới trả lời CMD55. MMC ko trả lời CMD55.
                Bạn phải chờ tới khi card trả lời CMD55 hoặc timeout rồi mới gửi ACMD41

                Bạn thử gửi ACMD41 với các tham số
                Code:
                unsigned char ACMD41_SD_SEND_OP_COND[] = {41,0x40,0x00,0x00,0x00,0xFF};
                Đoạn code bạn sử dụng vốn chỉ là đoạn code mẫu, để tránh mất thời gian debug vô ích mình khuyên bạn nên dùng MDD.
                - Xin đọc trước khi post bài

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

                Comment

                • tahi
                  Đệ tử 4 túi
                  • Mar 2009
                  • 64

                  #9
                  Code:
                      // Send CMD55, required to precede all "application specific" commands
                  	unsigned char CMD55_APP_CMD[] = {55,0x00,0x00,0x00,0x00,0x00};
                  	status = SD_WriteCommand(CMD55_APP_CMD); // Do not check response here	
                  	send_hex(status,"CMD55:");	
                  	
                  	// Send the ACMD41 command to initialize SD Card mode (not supported by MMC cards)
                  	i = 0;
                  	unsigned char ACMD41_SD_SEND_OP_COND[] = {41,0x40,0x00,0x00,0x00,0xFF};
                  	do
                  	{
                  		status = SD_WriteCommand(ACMD41_SD_SEND_OP_COND);
                  		// Might return 0x04 for Invalid Command if MMC card is connected
                  		send_hex(status,"ACMD41:");
                  		if(i++ > 50)
                  		{
                  			return 3;
                  		}
                  	} while( (status & R1_IN_IDLE_STATE) != 0 );
                  Gửi CMD55 trả về 0x01 , in idle state
                  Gửi ACMD41 trả về 0x05, in idle state and illegal command
                  có phải lệnh CMD1 và CMD55+ACMD41 là tương đương nhau ?

                  Bản MDD 1.2.1 down về, ko thấy support dòng dsPIC33, cũng ko thấy chỗ nào gán thanh ghi cho dspic33, mặc dù tiêu đề ghi là có hỗ trợ. Đương nhiên là có thể sửa từ PIC24,

                  Hay là phần cứng có vấn đề gì (e chỉ nối MOSI, MISO, SS, CLK). Thằng này có tính năng remappable, nhưng em chỉ remap cho thằng MOSI, MISO, CLK, còn SS thì define cho 1 pin khác.

                  Comment

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

                    #10
                    Nguyên văn bởi tahi View Post
                    Code:
                        // Send CMD55, required to precede all "application specific" commands
                    	unsigned char CMD55_APP_CMD[] = {55,0x00,0x00,0x00,0x00,0x00};
                    	status = SD_WriteCommand(CMD55_APP_CMD); // Do not check response here	
                    	send_hex(status,"CMD55:");	
                    	
                    	// Send the ACMD41 command to initialize SD Card mode (not supported by MMC cards)
                    	i = 0;
                    	unsigned char ACMD41_SD_SEND_OP_COND[] = {41,0x40,0x00,0x00,0x00,0xFF};
                    	do
                    	{
                    		status = SD_WriteCommand(ACMD41_SD_SEND_OP_COND);
                    		// Might return 0x04 for Invalid Command if MMC card is connected
                    		send_hex(status,"ACMD41:");
                    		if(i++ > 50)
                    		{
                    			return 3;
                    		}
                    	} while( (status & R1_IN_IDLE_STATE) != 0 );
                    Gửi CMD55 trả về 0x01 , in idle state
                    => card bạn dùng là SD card
                    Gửi ACMD41 trả về 0x05, in idle state and illegal command
                    Đáng lẽ card phải trả lời 0x01, sau đó bạn tiếp tục gửi CMD55 + ACMD41 cho tới khi card trả lời 0x00
                    có phải lệnh CMD1 và CMD55+ACMD41 là tương đương nhau ?
                    CMD1 là chuyển từ IDLE sang hoạt động và dùng cho thẻ SD/MMC
                    CMD55+ACMD41 để chuyển từ IDLE sang hoạt động và chỉ dùng cho thẻ SD

                    Tuy nhiên vì thẻ SD tương thích với thẻ MMC nên mình nghĩ bạn có thể bỏ qua CMD55+ACMD41 và gửi lệnh SET_BLOCK_LEN = 512 (command 16), sau đó kết thúc phần init bằng 8 lần ghi 0xff.

                    Đoạn code mẫu của anh Hiệp thiếu lệnh SET_BLOCK_LEN, có lẽ đây là lý do làm bạn nhận về mã lỗi địa chỉ sai.

                    Hay là phần cứng có vấn đề gì (e chỉ nối MOSI, MISO, SS, CLK). Thằng này có tính năng remappable, nhưng em chỉ remap cho thằng MOSI, MISO, CLK, còn SS thì define cho 1 pin khác.
                    Bạn ko nên dùng chân SS của SPI, dùng 1 chân IO bình thường để nối tới chân CS của card (hình như bạn đang làm như vậy, bạn nói chưa rõ).

                    Khi khởi động, card ở chế độ SD, do đó chân SDO của card là opendrain, bạn cần 1 con điện trở pull-up ở chân này, từ 10k-50k.
                    - Xin đọc trước khi post bài

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

                    Comment

                    • tahi
                      Đệ tử 4 túi
                      • Mar 2009
                      • 64

                      #11
                      Cảm ơn bác đã giúp. Đoạn gửi ACMD41 đúng là em hơi sơ xuất, em chỉ loop mỗi gửi ACMD41, đáng nhẽ phải loop cả CMD55 và ACMD41
                      Bạn ko nên dùng chân SS của SPI, dùng 1 chân IO bình thường để nối tới chân CS của card (hình như bạn đang làm như vậy, bạn nói chưa rõ).
                      Em gán cho 1 thằng I/O bình thường
                      Khi khởi động, card ở chế độ SD, do đó chân SDO của card là opendrain, bạn cần 1 con điện trở pull-up ở chân này, từ 10k-50k.
                      Em ko có con trở pull-up nào. Đồng thời dính hiến tượng, cắm thẻ thì reset (sụt áp)

                      Khi send 6 byte lệnh, có delay giữa các byte hay ko hay là gửi liên tiếp,
                      Code:
                      unsigned char SD_WriteCommand(unsigned char* cmd)
                      {
                      	unsigned int i;
                      	unsigned char response;
                      	unsigned char savedSD_CS = SD_CS;	
                      	// SD Card Command Format
                      	// (from Section 5.2.1 of SanDisk SD Card Product Manual v1.9).
                      	// Frame 7 = 0
                      	// Frame 6 = 1
                      	// Command (6 bits)
                      	// Address (32 bits)
                      	// Frame 0 = 1
                      
                      	// Set the framing bits correctly (never change)
                      	cmd[0] |= (1<<6);
                      	cmd[0] &= ~(1<<7);
                      	cmd[5] |= (1<<0);	
                      	// Send the 6 byte command
                      	SD_Enable();
                      	for(i = 0; i < 6; ++i)
                      	{
                      		SPIWrite(*cmd);
                      		Delay_Us(100);  //để 10 thì ăn, còn để 0 hoặc 100 là response về FF
                      		cmd++;
                      	}	
                      	// Wait for the response
                      	i = 0;
                      	do
                      	{
                      		response = SPIRead();
                      		if(i > 500) //If this value = 100, will recieved 0xFF with cmd17
                      		{
                      			break;
                      		}
                      		i++;
                      	} while(response == 0xFF);
                      
                      	SD_Disable();
                      
                      	// Following any command, the SD Card needs 8 clocks to finish up its work.
                      	// (from SanDisk SD Card Product Manual v1.9 section 5.1.8)
                      	SPIWrite(0xFF); 
                      	SD_CS = savedSD_CS;
                      	return(response);
                      }

                      Comment

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

                        #12
                        Nguyên văn bởi tahi View Post
                        Đồng thời dính hiến tượng, cắm thẻ thì reset (sụt áp)
                        Bạn phải kiểm tra chắc chắn là phần cứng đúng. Vì thẻ ngốn dòng nhiều nhất khi ghi, nhưng cũng không quá 100mA
                        Khi send 6 byte lệnh, có delay giữa các byte hay ko hay là gửi liên tiếp,
                        Gửi liên tiếp ko delay, nhưng lần ghi sau cùng phải chờ tới khi module SPI xuất hết dữ liệu ra, tức là cờ ngắt bật thì mới được đưa chân CS về 1. Vì sau khi ghi vào thanh ghi SPIxBUF, cần tốn 1 thời gian tùy thuộc vào tốc độ baud thì dữ liệu mới ghi ra bus hết. Nếu bạn đưa chân CS về 1 ngay sau khi ghi SPIxBUF thì byte cuối cùng thẻ sẽ không nhận!


                        Và chú ý bạn phải gửi lệnh SET_BLOCK_LEN, đây là lệnh bắt buộc trong quá trình khởi tạo thẻ

                        Bạn muốn tự viết driver thẻ?
                        Last edited by bien_van_khat; 30-11-2009, 05:05 PM.
                        - Xin đọc trước khi post bài

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

                        Comment

                        • tahi
                          Đệ tử 4 túi
                          • Mar 2009
                          • 64

                          #13
                          Và chú ý bạn phải gửi lệnh SET_BLOCK_LEN, đây là lệnh bắt buộc trong quá trình khởi tạo thẻ
                          Em đọc tài liệu thấy bảo là, block length =512 là default mà .
                          Bạn muốn tự viết driver thẻ?
                          Đương nhiên là không rồi, e chỉ viết các hàm init cơ bản để test thôi. Em đã down mấy cái example về sử dụng MDD của microchip ko thấy nó hỗ trợ cho dòng 33F...Có cái thì bọn nó viết lại gần hết SD-SPI.c, cũng chẳng theo gì MDD. Còn có mấy cái project cho 30F thì ok...Bác có cái template nào viết cho dòng 33F ko, post lên cho em tham khảo với.

                          Comment

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

                            #14
                            Nguyên văn bởi tahi View Post
                            Em đọc tài liệu thấy bảo là, block length =512 là default mà .
                            Mình chưa kiểm tra kỹ vụ này.

                            Đương nhiên là không rồi, e chỉ viết các hàm init cơ bản để test thôi. Em đã down mấy cái example về sử dụng MDD của microchip ko thấy nó hỗ trợ cho dòng 33F...Có cái thì bọn nó viết lại gần hết SD-SPI.c, cũng chẳng theo gì MDD. Còn có mấy cái project cho 30F thì ok...Bác có cái template nào viết cho dòng 33F ko, post lên cho em tham khảo với.
                            port giữa pic24, PIC33 và PIC32 rất dễ, vì các thanh ghi ngoại vi 3 dòng này giống nhau.


                            Mình nghĩ bạn dùng PIC33FJxxGP8xx, nếu vậy có lẽ chỉ cần thay file header và điều chỉnh lại các chân remap của SPI là xong!
                            Last edited by bien_van_khat; 30-11-2009, 11:29 PM.
                            - Xin đọc trước khi post bài

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

                            Comment

                            • tahi
                              Đệ tử 4 túi
                              • Mar 2009
                              • 64

                              #15
                              Em đã đọc được single block, nhưng em chưa hiểu lắm. Khi format thẻ với định dạng khác nhau thì đọc MBR có giống nhau không ? (theo em là có nhưng thực tế là đọc lần nào cũng như lần nào)

                              Em soi lại cại MDD file system, trong khi đợi data token.. (của lệnh CMD17 sau khi response = 0 thì đợi data token..) không thấy bọn nó cho chân SD_CS = 0;

                              Không thấy bọn nó switch speed sau khi init thẻ xong.

                              Comment

                              Working...