PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Giao tiếp USB, CAN, I2C, SPI, USART... (http://www.picvietnam.com/forum/forumdisplay.php?f=45)
-   -   Vấn đề với 18f2550 với flash spi 8Mbit (http://www.picvietnam.com/forum/showthread.php?t=12186)

sogoku_vn 19-12-2011 12:30 AM

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

ThanhPhuc 09-01-2012 03:46 PM

Bạn thử dùng mạch nạp để kiểm tra thử eeprom có die không?
Xem lại datasheet của eeprom,chú ý thời gian lên và xuống của các xung để hiệu chỉnh các xung lập trình phù hợp.
Chúc bạn thành công.


Múi giờ GMT. Hiện tại là 06:36 PM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam