PDA

View Full Version : Vấn đề với 18f2550 với flash spi 8Mbit


sogoku_vn
19-12-2011, 12:30 AM
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
#include <18F2550.h>

//configure a 20MHz crystal to operate at 48MHz
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDI V1,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
#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.