View Single Post
Old 19-12-2011, 12:30 AM   #1
sogoku_vn
Nhập môn đệ tử
 
Tham gia ngày: Dec 2007
Bài gửi: 5
:
Vấn đề với 18f2550 với flash spi 8Mbit

Mình đang làm giao tiếp 18f2550 với SPI flash A25L80P 8Mbit. Lần đầu ghi xuống một kí tự và đọc ngược trở lên thì dc, nhưng sang lần 2 thì không ghi được, giá trị đọc lên sai. Nguồn nuôi toàn bộ là 3.3V tuơng thích với Flash,MCU.18f2550 giao tiếp với PC thông qua uart usb có sẵn trên PIC
Code của mình
//main.h
Code:
#include <18F2550.h>

  //configure a 20MHz crystal to operate at 48MHz
  #fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
  //#fuses   USBDIV, PLL1, CPUDIV1, PROTECT, NOCPD, noBROWNOUT,HSPLL,NOWDT,nolvp, VREGEN
  #use delay(clock=20000000)
    
   #include <usb_cdc.h>
   #include <25L80.c>

void main() {

   char RcvUSB,Rcv;
   #use standard_io(A)
   usb_cdc_init();
   usb_init();
   init_ext_eeprom();
   output_bit( PIN_A0, 1);
   erase_ext_eeprom();
   output_bit( PIN_A0, 0);
   
   while(!usb_cdc_connected()) {}

   do {
      usb_task();
      if (usb_enumerated()) {
         printf(usb_cdc_putc, "\r\nType a character : !");
         RcvUSB = usb_cdc_getc();
         write_ext_eeprom(1, RcvUSB);
         delay_ms(250);
         output_bit( PIN_A0, 1);
         delay_ms(250);
         output_bit( PIN_A0, 0);
         Rcv=read_ext_eeprom(1);
         usb_cdc_putc(Rcv);        
      }
   } while (TRUE);
}
//25L80.c
Code:
#ifndef EEPROM_SELECT

#define EEPROM_SELECT PIN_B0
#define EEPROM_CLK    PIN_B1
#define EEPROM_DI     PIN_B2
#define EEPROM_DO     PIN_B4

#endif

#define EEPROM_ADDRESS int32
#define EEPROM_SIZE    1048576

void init_ext_eeprom() {
   output_high(EEPROM_SELECT);
   output_low(EEPROM_DI);
   output_low(EEPROM_CLK);
}

BOOLEAN ext_eeprom_ready() {
   BYTE cmd[1], i, data;

   cmd[0] = 0x05;                  //rdsr opcode

   output_low(EEPROM_SELECT);

   for(i=1; i<=8; ++i) {
      output_bit(EEPROM_DI, shift_left(cmd,1,0));
      output_high(EEPROM_CLK);   //data latches
      output_low(EEPROM_CLK);      //back to idle
   }

   for(i=1; i<=8; ++i) {
        output_high(EEPROM_CLK);   //data latches
        shift_left(&data,1,input(EEPROM_DO));
        output_low(EEPROM_CLK);  //back to idle
   }
     output_high(EEPROM_SELECT);
     return !bit_test(data, 0);
}

void erase_ext_eeprom()
{
   BYTE i, wren, erase;
   
   wren = 0x06;                  // wren opcode
   erase = 0xc7;                 // chip erase
   
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());
   
   output_low(EEPROM_SELECT);
   
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&wren, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   }
   
   output_high(EEPROM_SELECT);
   
   output_low(EEPROM_SELECT);
   
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&erase, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   }
   
   output_high(EEPROM_SELECT);
   
   delay_ms(40000);              // tCE
}

void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data) {
   BYTE cmd[5];
   BYTE i;
   BYTE wren;
   wren=0x06;
   cmd[0]=data;
   cmd[1]=address;
   cmd[2]=(address>>8);
   cmd[3]=(address>>16);
   cmd[4]=0x02;
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());

   output_low(EEPROM_SELECT);
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&wren,1,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   output_high(EEPROM_SELECT);
   output_low(EEPROM_SELECT);
   for(i=0; i<40; ++i)
   {
      output_bit(EEPROM_DI, shift_left(cmd,5,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   output_high(EEPROM_SELECT);
}

BYTE se_ext_eeprom(EEPROM_ADDRESS address) {
   BYTE cmd[4];
   BYTE i,data;
   cmd[0]=address;
   cmd[1]=(address>>8);
   cmd[2]=(address>>16);
   cmd[3]=0xd8;
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());

   output_low(EEPROM_SELECT);
   for(i=0; i<32; ++i)
   {
      output_bit(EEPROM_DI, shift_left(cmd,4,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   for(i=0; i<8; ++i)
   {
      shift_left(&data,1,input(EEPROM_DO));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   output_high(EEPROM_SELECT);
   return(data);
} 

BYTE read_ext_eeprom(EEPROM_ADDRESS address) {
   BYTE cmd[4];
   BYTE i,data;
   cmd[0]=address;
   cmd[1]=(address>>8);
   cmd[2]=(address>>16);
   cmd[3]=0x03;
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());

   output_low(EEPROM_SELECT);
   for(i=0; i<32; ++i)
   {
      output_bit(EEPROM_DI, shift_left(cmd,4,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   for(i=0; i<8; ++i)
   {
      shift_left(&data,1,input(EEPROM_DO));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   output_high(EEPROM_SELECT);
   return(data);
}
A25L80P datasheet
http://www.amictechnology.com/pdf/A25L80P.pdf
Thanks
sogoku_vn vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn