PIC16F887 có giao tiếp được với bộ nhớ ngoài (SD card) ?

40903219

Trứng gà
Các dòng VDK sẻ reset lại toàn bộ khi bị mất nguồn (do 1 lí do nào đó) or bị tác động vào chân reset !
vậy có cách nào để những dữ liệu trong quá trình mình xử lí bằng MCU thu thập được được bảo vệ một cách an toàn?(khi bị reset :(()
dữ liệu cần bảo vệ :
+ khi tác động vào sensor lần 1 sau 1 thời gian tác động lần 2 --> dữ liệu cần là khoảng thời gian giữa 2 lần tác động (không xuất ra LCD). và nếu cứ tiếp tục như trên thì ta sẻ có nhiều số liệu cần phải lưu trữ lại
+ nếu lưu các số liệu đó vào 1 mãng thì khi gặp sự cố thì coi như công cốc
+ và giả sử sau 1 ngày mình mới câp nhật dữ liệu một lần thì phải làm thế nào?
==> đòi hỏi phải có 1 thiết bị lưu trữ bên ngoài !
vấn đề e muốn hỏi ở đây là :
+ pic giao tiếp với bộ nhớ ngoại như thế nào?
+ nó có gửi & nhận trực tiếp từ bộ nhớ ngoài không?
+ để đọc dữ liệu từ bô nhớ ngoài (qua LCD) mà không cần tới PC?
anh chị giải đáp giúp em nhá !
em củm ơn nhiều :) !
 

tungbk

Cố Vấn CLB
Staff member
Chú ý là PIC16887 có 1 EEPROM nội 256 byte nếu cần lưu trữ mảng nhỏ thì có thể tận dụng EEPROM này ( việc ghi, đọc bằng lệnh rất dễ-xem trong HTC Manual). Nếu cần dùng thêm bộ nhớ ngoài có thể dùng ROM ngoài có đủ cỡ 256 byte, 512B, 1K, 2k,4K...các loại này thường dùng I2C hoặc SPI giao tiếp và cũng khá đơn giản. Nếu cần nhiều hơn nữa thì dùng thẻ nhớ.
Thẻ nhớ có thể giao tiếp 2 kiểu hoặc SPI mode (data 2 dây) hoặc SD Bus mode (data 4 dây). Trong PIC16F887 thì chỉ dùng kiểu SPI. Việc giao tiếp thẻ phải theo 1 qui trình xem ở đây và code cũng khá dài cách dễ hơn là port sample code từ các nhà sản xuất sang dùng. Vd vừa rồi a có port code từ ARMM3 LPC1769 của NXP sang cho thèn ARM ST chỉ sửa 1 vài lệnh liên quan phần cứng như SPI_read, write...còn quá trình thiết lập thì code C như nhau cả. E xem thử trang web có link ở trên rồi tính tiếp.
 
Đây là file myMMC.c và myMMC.h định nghĩa sẵn các hàm dùng để giao tiếp với SD Card. Mình lấy nguồn từ 2 file viết cho AVR sửa lại để dùng cho PIC.
Chương trình còn có nhiều chỗ mình sửa code chưa tốt lắm và cũng chưa có cơ hội làm mạch thật để test, chỉ làm proteus mô phỏng thôi. Bạn thử làm phần cứng rồi chạy thử xem nha.

myMMC.c
Code:
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// Title:   myMMC                                                                    ;
// Description: thu vien ghi-doc card MMC/SD cho PIC                                 ;
// Chuong trinh duoc chinh sua tu thu vien ghi-doc card MMC/SD cho AVR				 ;
// Source website: www.hocavr.com                                                    ;
// Author: anhxtuan                                                                  ; 
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//*************************KHONG THAY DOI BAT CU THU GI KE TU DONG NAY*******************************************
#include <htc.h>
#include "myMMC.h"
#include "uart.h"


//cai dat cho  SPI o che do Master---------------------------------------------------------------------------- 
void SPI_MasterInit(void)
{
   // I/O PORT init for SPI communication
   
   TRISC3 = 0;      // SCK pin is output
   TRISC5 = 0;      // SDO pin is output
   TRISC4 = 1;      // SDI pin is input
    
   // init LATCH PIN: RC1
   TRISC1 = 0;        // is output
   
   //SSPSTAT 
   SMP = 1;       // data in sampled at middle
   CKE = 1;       // data out at rising edge (with CKP = 0)
   //SSPCON
   SSPCON = 0b00100000;   // CKP = 0, SPI mode baudrate = Fosc/4    
}

//Truyen 1 byte 
unsigned char spi(unsigned char b)
{
   WCOL = 0;            // clear any write collision condition
   SSPIF = 0;           // clear SSP interrupt flag
   SSPBUF = b;          // load the SSP buffer with data
   while(!SSPIF);       // wait for SSPIF to be sent
   return SSPBUF;
}

// end of SPI--------------------------------------------------------------------------------------------

// for mmc***********************************************
//nhan va so sanh Response tu mmc
char mmc_rResponse(char Response)
{
   int Timeout = 0x0fff;
   char Res;
   while((Timeout--) > 0)
	{
      Res = spi(0xff);
      if (Res == Response) break;   //escape from while      
    }
   if (Timeout == 0) return 1;        //tra ve 1 neu timeout 
   else return 0;                    // ko co loi, tra ve 0
} 

void mmc_tCommand(char Cmd, long arg)
{
   //command la 48 bit lien tiep trong do
   //bit47=0 (start bit)
   //bit46=1 (transmission bit)
   //bit45:40 la ma lenh
   //bit39:8  la argument cua lenh
   //bit7:1   Cyclic Redundancy Check (CRC)
   //bit0=1 la end bit
   
   cbi(SPI_PORT, SS_PIN);        //kich hoat duong SS cua SPI, MMC duoc chon
   spi(0xFF);              //dummy, 1 lenh luon bat dau 0 nen send FF thi MMC ko dap ung
   spi(Cmd | 0x40);        //0x40=01000000 la ma bat buoc khi goi lenh
   
   spi((char)(arg >>24));   
   spi((char)(arg >>16));
   spi((char)(arg >> 8));   
   spi((char) arg);
   
   spi(0x95);              //CRC, cho lan dau nhung neu cac lan sau send 0x95 cung ko van de;
   spi(0xFF);              //ko quan tam return   
}

char mmc_init(void)
{
   // local variable
   int i;
	char mmc_status;   

   SPI_MasterInit();
   sbi(SPI_PORT, SS_PIN);              //disable SPI MMC
   for (i = 0; i < 10; i++) 
      spi(0xFF);                 		//MMC se vao SPI mode neu duoc nhan nhieu hon 80 clock tren SCK
   cbi(SPI_PORT, SS_PIN);              //cho phep MMC hoat dong
   
   mmc_tCommand(CMD0, 0);               //lenh CMD0. reset mmc   
   if(mmc_rResponse(0x01) == 1){       //co loi kiem tra response
      mmc_status = 1;                    // timeout khi reset
      sbi(SPI_PORT, SS_PIN);           //disable SPI MMC
      return mmc_status;
   }
   
   //goi lenh CMD1 cho den khi nhan duoc response =0 hoac timeout
   i = 0xffff;                           //max timeout
   do{
      mmc_tCommand(CMD1,0);            //lenh CMD1
      i--;
   } while((spi(0xff) != 0) && (i > 0));

   if(i == 0){                         //co loi khi goi CMD1
      mmc_status = 2;                    // loi CMD1
      sbi(SPI_PORT, SS_PIN);           //disable SPI MMC
      return mmc_status;
   }   
   
   mmc_tCommand(CMD16, Block_len);      //lenh CMD16, set do dai sector,Block_len=512
   if(mmc_rResponse(0x00) == 1){       //co loi kiem tra response
      mmc_status=3;                    // timeout khi set len
      sbi(SPI_PORT, SS_PIN);           //disable SPI MMC
      return mmc_status;
   }
   
   sbi(SPI_PORT, SS_PIN);              //disable SPI MMC
   return 0;                           //no error
}

char mmc_writeblock(long LBAddress, char *buff)
{
   //local variable
   long tempA;
   int i;
	char mmc_status;
   tempA = LBAddress<<9;   
      
   //cach bo tri dia lba cho cho lenh write xxxxxxxx-xxxxxxxx , xxxxxxx0-00000000
   //trong do x la cac bit cua dia chi, nhu vay 9 bit dau cua argument low ko dung   
   cbi(SPI_PORT, SS_PIN);              //cho phep MMC hoat dong   
   mmc_tCommand(CMD24,tempA);          //goi lenh cho phep ghi single sector, chu y cach set dia chi

	
   if(mmc_rResponse(0x00) == 1){       //co loi kiem tra response
      mmc_status=4;                    // timeout khi goi lenh write block
      sbi(SPI_PORT, SS_PIN);           //disable SPI MMC
      return mmc_status;
   }

   //goi dau hieu (token) bao cho mmc biet sap co data den, dau hieu=0xFE
   spi(0xFE);
   
   //goi Block_len = 512 byte data
   for (i = 0; i < Block_len; i++)
	{ 
      	spi(buff[i]);
		//uart_putc(buff[i]);
		//if(buff[i] == 0) break;
	}

   //goi 2 byte checksum
   spi(0xFF);
   spi(0xFF);
	
   //doc trai thai response, phai la 0x05
   char status;
	status = spi(0xff);

   if((status & 0x0F) != 0x05){          //co loi kiem tra response
      mmc_status = 5;                    // loi khi goi datablock
      sbi(SPI_PORT, SS_PIN);             //disable SPI MMC
      return mmc_status;
   }

	__delay_ms(1);
	//uart_puts("a\r\n");
   
   //cho mmc het busy
   i = 0xffff;                           // max timeout
   while(!spi(0xff) && (--i)){;}             // wait until we are not busy
   if (i==0) {
      mmc_status=6;                       // loi timeout khi cho busy
      sbi(SPI_PORT, SS_PIN);              //disable SPI MMC
      return mmc_status;
   }
   
   sbi(SPI_PORT, SS_PIN);                 //disable SPI MMC   
   return 0; 
  
}

char mmc_readblock(long LBAddress, char *buff)
{
    long tempA;
    int i;  
	char mmc_status; 
    tempA = LBAddress<<9;
      
    //cach bo tri dia lba cho cho lenh write xxxxxxxx-xxxxxxxx , xxxxxxx0-00000000
    //trong do x la cac bit cua dia chi, nhu vay 9 bit dau cua argument low ko dung   
    cbi(SPI_PORT, SS_PIN);              //cho phep MMC hoat dong   
    mmc_tCommand(CMD17,tempA);          //goi lenh cho phep doc single sector, chu y cach set dia chi
   
    if(mmc_rResponse(0x00) == 1)        //co loi kiem tra response
    { 
       mmc_status = 7;                    // timeout khi goi len read block
       sbi(SPI_PORT, SS_PIN);           //disable SPI MMC
       return mmc_status;
    }
   
    //kiem tra dau hieu (token) read
    if(mmc_rResponse(0xFE) == 1)        //co loi kiem tra response
    { 
      mmc_status=8;                    // timeout khi goi len read block
      sbi(SPI_PORT, SS_PIN);           //disable SPI MMC
      return mmc_status;
    }
   
	__delay_ms(1);

   //sau day la goi Block_len=512 byte data
   for (i = 0; i < Block_len; i++) 
	{
        //
		//uart_putc(spi(0xff));
		//uart_putc(i);
		//__delay_ms(50);
		buff[i] = spi(0xff);
	}
   	uart_puts("\r\nANHXTUAN\r\n");
   //goi 2 byte checksum
   spi(0xFF);
   spi(0xFF);   
   
   sbi(SPI_PORT, SS_PIN);              //disable SPI MMC   
   return 0;   
}
 
Còn đây là file myMMC.h
Code:
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// Title:   myMMC                                                                    ;
// Description: thu vien ghi-doc card MMC/SD cho PIC                                 ;
// Chuong trinh duoc chinh sua tu thu vien ghi-doc card MMC/SD cho AVR				 ;
// Source website: www.hocavr.com                                                    ;
// Author: anhxtuan                                                                  ;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#ifndef _myMMC_H_
#define _myMMC_H_

#include <stdio.h>

//Dinh nghia cac chan SPI, hay thay doi tuy theo cau hinh that cua chip
//cau hinh ben duoi danh cho chip PIC16F887
#define SPI_PORT   PORTC
#define SCK_PIN    3
#define MISO_PIN   4
#define MOSI_PIN   5
#define SS_PIN     1
//---------------------------------

#define Block_len   512 //dinh nghia do dai 1 sector

//*************************KHONG THAY DOI BAT CU DONG NAO KE TU DONG NAY*****************************
#ifndef cbi
   #define cbi(port, position)       (port) &= ~(1 << (position))
#endif
#ifndef sbi
   #define sbi(port, position)       (port) |=  (1 << (position))
#endif

//Dinh nghia mot so lenh co ban giao tiep voi MMC
#define CMD0    0x00   //GO_IDLE_STATE, reset va dua vao trang thai nghi
#define CMD1    0x01   //SEND_OP_COND, Yeu cau Card tra loi ve trang thai cua CARD
#define CMD16   0x10   //SET_BLOCKLEN, Dat do dai (tinh theo byte) cho 1 khoi du lieu (data block)
#define CMD17   0x11   //READ_SINGLE_BLOCK, doc 1 block du lieu cua CARD
#define CMD24   0x18   //WRITE_BLOCK, ghi 1 mang du lieu vao 1 block cua CARD

char mmc_status = 0; //cac trang thai tra ve khi thao tac voi card
//mmc_status=0;
//0: ok
//1: loi khi reset, timeout khi reset
//2: loi xay ra luc goi lenh CMD1
//3: loi khi set blocklen
//4: timeout ghi goi lend writeblock CMD24
//5: timeout trong qua trinh write data
//6: timeout do card dang ban
//7: loi khi goi lenh readblock, CMD17
//8: loi khi kiem tra token cua lenh doc du lieu

//cai dat cho  SPI o che do Master------------------
void SPI_MasterInit(void);
unsigned char spi(unsigned char b);
// end of SPI---------------------------------------

//cac lenh giao tiep mmc***********************************************
char mmc_rResponse(char Response);   //yeu cau Response (dap ung) tu card
void mmc_tCommand(char Cmd, long arg); //goi 1 lenh den card
char mmc_init(void); //khoi dong card
char mmc_writeblock(long LBAddress, char *buff); //ghi 1 sector (1 khoi du lieu)
char mmc_readblock(long LBAddress, char *buff);  //doc 1 sector (1 khoi du lieu)

#endif
//**************************************************************************************************
 
Top