SPI flash memory (AT26DF161A) with PIC16F883 write wrong data in memory and Manufacturer ID is wrong
I'm working on a product with a TFT display and I want to save the screens in a flash memory. I had available an AT26DF161A memory, so I build a prototype in order to test it with a PIC16F883. I wrote the code just to send a 20 char array with ascii characters, read it back and send it through UART comm to the PC terminal with a USB to Serial converter. First of all, when I check the device manufaturer ID, instead of 1Fh, I recieve 58h. However, both bytes of Device ID are ok, 46h and 01h. I don't know if this is a bad component or if the manufacturer ID changed and they forgot to update the datasheet. The most important problem, is that I'm wititng to the memory the array, but when I read it all the data saved is wrong, there is data where I tried to write my array, but is not what I wrote. Below you'll find the code I've written.
EDIT1
The array I'm sending to the memory is this:
{41h 42h 43h 44h 45h 46h 47h 48h 49h 4Ah 4Bh 4Ch 4Dh 4Eh 4Fh 50h 00h 00h 00h 00h} (in ascii is {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',0x00,0x00,0x00,0x00}...
and the response is:
{43h 0Ah 28h 12h 4Dh 24h FFh 62h FFh 2Ch FFh FFh FFh 32h FFh 30h 00h 00h 00h 00h}
After this I've tried again and the response was this {43h 0Ah 28h 12h 4Dh 24h FFh 51h 59h FFh 5Dh 45h 65h FFh 75h 18h 00h 00h 00h 00h}.
First I unprotect the sector, then I perform a 4kB erase and then I write, If I don't do this, the response is all FFh. The chip is marked as Atmel, I don't know why the response is another manufacturer.
/*MEM_HAL_functions.h*/
#define CMD_SEQUENTIAL_MODE 0xAF
#define CMD_BYTE_PAGE_WRITE 0x02
#define CMD_WRITE_EN 0x06
#define CMD_WRITE_DIS 0x04
#define CMD_READ_ARRAY 0x0B
#define CMD_READ_ARRAY_LF 0x03
#define CMD_READ_STAT_REG 0x05
#define CMD_WRITE_STAT_REG 0x01
#define CMD_CHIP_ERASE 0x60
#define CMD_GLOBAL_UNPROT 0x00
#define CMD_GLOBAL_PROT 0x3C
#define CMD_UNPROTECT_SECTOR 0x39
#define CMD_PROTECT_SECTOR 0x36
#define CMD_READ_DEV_ID 0x9F
#define DEV_ID_OK 0xCC
#define DEV_ID_NOK 0xDD
#define UPDATE_STAT_REG 0x11
#define NO_UPDATE_STAT_REG 0x22
#define MEM_STAT_REG_ERROR 0xFF
#define MEM_WRITE_ERROR 0xBB
#define MEM_WRITE_OK 0xAA
#define WEL_BIT 31
#define EPE_BIT 35
#define RDY_BSY_BIT 30
#define SPM_BIT 36
#define MASK_SPM_BIT 0b01000000
#define SPM_BIT_ON 0x01
#define SPM_BIT_POS 6
#define MASK_WEL_BIT 0b00000010
#define WEL_BIT_POS 1
#define WEL_BIT_ON 0b00000010
#define EPE_ERROR 0xEE
#define MASK_EPE_BIT 0b00100000
#define EPE_BIT_POS 5
#define EPE_BIT_NO_ERR 0b00000000
#define RDY_BSY_BIT_POS 0
#define MASK_RDY_BSY_BIT 0b00000001
#define RDY_BSY_BIT_BUSY 0b00000001
#define SCREEN0_ADD_0 0x00
#define SCREEN0_ADD_1 0x01
#define SCREEN0_ADD_2 0x00
#define SCREEN1_ADD_0 0x00
#define SCREEN1_ADD_1 0x58
#define SCREEN1_ADD_2 0x02
#define DUMMY_BYTE 0x55
#define MEM_CS_SETTLE_TIME 10 //uS
#define BLOCK_4KB_ERASE_CMD 0x20
#define BLOCK_32KB_ERASE_CMD 0x52
#define BLOCK_64KB_ERASE_CMD 0x68
#define ALL_BLOCKS_ERASE_CMD 0x60
#define BLOCK_4KB 4
#define BLOCK_32KB 32
#define BLOCK_64KB 64
#define ALL_BLOCKS 255
void MemCSEnable(void);
void MemCSDisable(void);
char MemStatRegBitCheck (char bit2check, char update_stat_reg);
void TxSPIData2Mem(char* data,char data_size, char address2, char address1, char address0);
void RxSPIMemData(char* data,char data_size, char address2, char address1, char address0);
char MemWritePageByte (char* data, char data_size, char address2, char address1, char address0);
void MemGlobalUnprotect (void);
void MemUnprotectSector (char address2, char address1, char address0);
void MemErase(char block_size, char address2, char address1, char address0);
char MemReadDeviceID (char* data);
/*MEM_HAL_functions.c*/
#include "MEM_HAL_functions.h"
#include "PIC16F883_HAL_functions.h"
void MemCSEnable(void)
{
MEM_CS_ON; //Habilito la memoria
__delay_us(MEM_CS_SETTLE_TIME);
}
void MemCSDisable(void)
{
MEM_CS_OFF; //Habilito la memoria
__delay_us(MEM_CS_SETTLE_TIME);
}
/******************************************************************************/
/* Chequear el estado del bit indicado del StatReg */
/******************************************************************************/
char MemStatRegBitCheck (char bit2check, char update_stat_reg)
{
static char mem_stat_reg;
char mem_stat_aux;
char result=MEM_STAT_REG_ERROR;
if(update_stat_reg == UPDATE_STAT_REG)
{
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_READ_STAT_REG); //Consulto el registro de estado de la memoria
mem_stat_reg = RxSPI(); //Leo la respuesta
MemCSDisable(); //Deshabilito la memoria
}
mem_stat_aux = mem_stat_reg;
if(mem_stat_aux != MEM_STAT_REG_ERROR)
{
switch (bit2check)
{
case WEL_BIT:
mem_stat_aux &= MASK_WEL_BIT; //Enmascaro el registro para leer solo el EPE bit
if(mem_stat_aux == WEL_BIT_ON)
result = WEL_BIT_ON;
break;
case EPE_BIT:
mem_stat_aux &= MASK_EPE_BIT; //Enmascaro el registro para leer solo el EPE bit
if(mem_stat_aux == EPE_BIT_NO_ERR)
result = EPE_BIT_NO_ERR;
break;
case RDY_BSY_BIT:
mem_stat_aux &= MASK_RDY_BSY_BIT; //Enmascaro el registro para leer solo el EPE bit
if(mem_stat_aux == RDY_BSY_BIT_BUSY)
result = RDY_BSY_BIT_BUSY;
break;
case SPM_BIT:
mem_stat_aux &= MASK_SPM_BIT; //Enmascaro el registro para leer solo el EPE bit
if(mem_stat_aux == SPM_BIT_ON)
result = SPM_BIT_ON;
break;
}
}
return result;
}
/******************************************************************************/
/* Transmitir datos a memoria por SPI */
/******************************************************************************/
void TxSPIData2Mem(char* data,char data_size, char address2, char address1, char address0)
{
//Inicialmente, la frecuencia del SPI está configurada en 125kHz
char aux = 0;
//aux = data_size;
do{
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_WRITE_EN); //envío el comando para habilitar la escritura
MemCSDisable(); //Deshabilito la memoria para que se efectúe el comando
while(MemStatRegBitCheck(WEL_BIT,UPDATE_STAT_REG) != WEL_BIT_ON)
{
CLEAR_WDT;//reset watchdog
}
}while(MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) != EPE_BIT_NO_ERR);
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_SEQUENTIAL_MODE); //Transmito comando de inicio de escritura secuencial
TxSPI(address2); //Envío byte más alto de la dirección
TxSPI(address1); //Envío segundo byte de dirección
TxSPI(address0); //Envío byte más bajo de la dirección
CLEAR_WDT; //reset watchdog
while(aux < data_size)
{
while(MemStatRegBitCheck(EPE_BIT,UPDATE_STAT_REG) != EPE_BIT_NO_ERR)
{
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_SEQUENTIAL_MODE); //Transmito comando de inicio de escritura secuencial
TxSPI(data[aux]); //Transmito el dato
MemCSDisable(); //Deshabilito la memoria para que se guarde el dato transmitido
CLEAR_WDT;
}
aux++;
}
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_WRITE_DIS); //Envío el comando para deshabilitar la escritura
MemCSDisable(); //Deshabilito la memoria para que se efectúe el comando y salir de la función
}
/******************************************************************************/
/* Recibir datos de memoria por SPI */
/******************************************************************************/
void RxSPIMemData(char* data,char data_size, char address2, char address1, char address0)
{
char aux = 0;
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_READ_ARRAY_LF); //Envío comando de lectura secuencial
TxSPI(address2); //Envío los 3 bytes de dirección de memoria
TxSPI(address1); //con el más alto primero y el más bajo último
TxSPI(address0);
//TxSPI(DUMMY_BYTE); //Para cerrar el comando se envía un byte bobo (solo HF)
CLEAR_WDT; //reset watchdog
while(aux < data_size)
{//Levanto todas las posiciones de memoria requeridas
data[aux] = RxSPI();
aux++;
CLEAR_WDT; //reset watchdog
__delay_us(20);
}
MemCSDisable();
}
/******************************************************************************/
/* Escribir una página de memoria (256bytes) byte a byte */
/******************************************************************************/
char MemWritePageByte (char* data, char data_size, char address2, char address1, char address0)
{
char aux=0;
do{
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_WRITE_EN); //envío el comando para habilitar la escritura
MemCSDisable(); //Deshabilito la memoria para que se efectúe el comando
while((MemStatRegBitCheck(WEL_BIT,UPDATE_STAT_REG) != WEL_BIT_ON) && (MemStatRegBitCheck(RDY_BSY_BIT,NO_UPDATE_STAT_REG) == RDY_BSY_BIT_BUSY))
{
CLEAR_WDT; //reset watchdog
}
}while(MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) != EPE_BIT_NO_ERR);
MemCSEnable();
TxSPI(CMD_BYTE_PAGE_WRITE); // Comando desproteger sector (65kB/sector)
TxSPI(address2); // Dirección de 24 bits
TxSPI(address1);
TxSPI(address0);
CLEAR_WDT;
//MemCSEnable(); //Habilito la memoria
while(aux < data_size)
{
TxSPI(data[aux]); //Transmito el dato
aux++;
__delay_us(50);
}
MemCSDisable(); //Deshabilito la memoria para que se guarde el dato transmitido
if(((MemStatRegBitCheck(WEL_BIT,UPDATE_STAT_REG) != WEL_BIT_ON) && (aux < data_size)) || (MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) != EPE_BIT_NO_ERR))
{
if(MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) != EPE_BIT_NO_ERR)
return EPE_ERROR;
else
return MEM_WRITE_ERROR;
}
while((MemStatRegBitCheck(RDY_BSY_BIT,UPDATE_STAT_REG) == RDY_BSY_BIT_BUSY) && (MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) == EPE_BIT_NO_ERR))
{
CLEAR_WDT; //reset watchdog
}
return MEM_WRITE_OK;
}
/******************************************************************************/
/* Desproteger toda la memoria */
/******************************************************************************/
void MemGlobalUnprotect (void)
{
//do{
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_WRITE_EN); //envío el comando para habilitar la escritura
MemCSDisable(); //Deshabilito la memoria para que se efectúe el comando
while((MemStatRegBitCheck(WEL_BIT,UPDATE_STAT_REG) != WEL_BIT_ON) || (MemStatRegBitCheck(WEL_BIT,NO_UPDATE_STAT_REG) == MEM_STAT_REG_ERROR))
{
CLEAR_WDT; //reset watchdog
}
//}while(MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) != EPE_BIT_NO_ERR);
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_WRITE_STAT_REG); //envío el comando para escribir el registro de estado
TxSPI(CMD_GLOBAL_UNPROT); //envío el comando para desproteger toda al memoria
MemCSDisable(); //Deshabilito la memoria para que se efectúe el comando
while(MemStatRegBitCheck(WEL_BIT,UPDATE_STAT_REG) == WEL_BIT_ON)
{
CLEAR_WDT; //reset watchdog
}
}
/******************************************************************************/
/* Desproteger el sector de la dirección de memoria recibida */
/******************************************************************************/
void MemUnprotectSector (char address2, char address1, char address0)
{
do{
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_WRITE_EN); //envío el comando para habilitar la escritura
MemCSDisable(); //Deshabilito la memoria para que se efectúe el comando
while((MemStatRegBitCheck(WEL_BIT,UPDATE_STAT_REG) != WEL_BIT_ON) || (MemStatRegBitCheck(WEL_BIT,NO_UPDATE_STAT_REG) == MEM_STAT_REG_ERROR))
{
CLEAR_WDT; //reset watchdog
}
}while(MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) != EPE_BIT_NO_ERR);
MemCSEnable();
TxSPI(CMD_UNPROTECT_SECTOR); // Comando desproteger sector (65kB/sector)
TxSPI(address2); // Dirección de 24 bits
TxSPI(address1);
TxSPI(address0);
MemCSDisable();
while((MemStatRegBitCheck(WEL_BIT,UPDATE_STAT_REG) == WEL_BIT_ON) || (MemStatRegBitCheck(RDY_BSY_BIT,NO_UPDATE_STAT_REG) == RDY_BSY_BIT_BUSY))
{
CLEAR_WDT; //reset watchdog
}
}
/******************************************************************************/
/* Borrar la memoria - por bloques o en su totalidad */
/******************************************************************************/
void MemErase(char block_size, char address2, char address1, char address0)
{
do{
do{
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_WRITE_EN); //envío el comando para habilitar la escritura
MemCSDisable(); //Deshabilito la memoria para que se efectúe el comando
while((MemStatRegBitCheck(WEL_BIT,UPDATE_STAT_REG) != WEL_BIT_ON) || (MemStatRegBitCheck(RDY_BSY_BIT,NO_UPDATE_STAT_REG) == RDY_BSY_BIT_BUSY))
{
CLEAR_WDT; //reset watchdog
}
}while(MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) != EPE_BIT_NO_ERR);
MemCSEnable();
switch (block_size)
{
case BLOCK_4KB:
TxSPI(BLOCK_4KB_ERASE_CMD); // Comando 4kB Page Erase
TxSPI(address2); // Dirección de 24 bits
TxSPI(address1);
TxSPI(address0);
break;
case BLOCK_32KB:
TxSPI(BLOCK_32KB_ERASE_CMD); // Comando 32kB Page Erase
TxSPI(address2); // Dirección de 24 bits
TxSPI(address1);
TxSPI(address0);
break;
case BLOCK_64KB:
TxSPI(BLOCK_64KB_ERASE_CMD); // Comando 64kB Page Erase
TxSPI(address2); // Dirección de 24 bits
TxSPI(address1);
TxSPI(address0);
break;
case ALL_BLOCKS:
TxSPI(ALL_BLOCKS_ERASE_CMD); //envío el comando para borrar todos los bloques de memoria
break;
}
MemCSDisable(); //Deshabilito la memoria para que se efectúe el comando
while(((MemStatRegBitCheck(RDY_BSY_BIT,UPDATE_STAT_REG) == RDY_BSY_BIT_BUSY) || (MemStatRegBitCheck(WEL_BIT,NO_UPDATE_STAT_REG) == WEL_BIT_ON))&&(MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) == EPE_BIT_NO_ERR))
{
CLEAR_WDT; //reset watchdog
}
}while(MemStatRegBitCheck(EPE_BIT,NO_UPDATE_STAT_REG) != EPE_BIT_NO_ERR);
}
char MemReadDeviceID (char* data)
{
MemCSEnable(); //Habilito la memoria
TxSPI(CMD_READ_DEV_ID); //Envío comando de lectura del device ID
data[0] = RxSPI(); //Recibo el primer byte que corresponde al ID del fabricante (0x1F -> AT26DF161A)
data[1] = RxSPI(); //Recibo la parte 1 del ID del dispositivo (0x46 -> AT26DF161A)
data[2] = RxSPI(); //Recibo la parte 2 del ID del dispositivo (0x01 -> AT26DF161A)
data[3] = RxSPI(); //Recibo el extended device info (0x00 -> AT26DF161A)
CLEAR_WDT; //reset watchdog
__delay_us(20);
MemCSDisable();
if(data[0]!=0x1F || data[1]!=0x46 || data[2]!=0x01)
return DEV_ID_NOK;
else
return DEV_ID_OK;
}
Here is the main program
#include "PIC16F883_HAL_functions.h"
#include "MEM_HAL_functions.h"
char devID[4];
char tick2mS = 0; //contador cada 2,048mS
char tick100mS = 0; //contador cada 100mS
char byte_recibido;
char flag_rx = 0;
char key_in=0;
#define SPI_COMM_BUFFER_SIZE 20
//char spi_comm_buffer[SPI_COMM_BUFFER_SIZE]={0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF};
char spi_comm_buffer[SPI_COMM_BUFFER_SIZE]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'};
char spi_out_buffer[SPI_COMM_BUFFER_SIZE];
void main(void)
{
char test = 'X';
configuracion();
if(OSCILADOR_ESTABLE)
{
MEM_CS_OFF;
TxUART(&test,1);
MemGlobalUnprotect();
if(MemReadDeviceID (devID)==DEV_ID_NOK)
TxUART(devID,3);
else
{
TxUART(&devID[1],1);
TxUART(&devID[2],1);
}
//MemErase(ALL_BLOCKS,0,0,0);
while (1)
{
while(key_in != 'R')
{
CLEAR_WDT;
RxUART(&key_in,1);
}
TxUART(spi_comm_buffer, SPI_COMM_BUFFER_SIZE);
key_in = 0;
__delay_ms(10);
CLEAR_WDT; //reset watchdog
if(tick2mS>=49)
tick100mS++;
MemUnprotectSector (SCREEN0_ADD_2,SCREEN0_ADD_1,SCREEN0_ADD_0);
__delay_ms(2);
MemErase(BLOCK_4KB,SCREEN0_ADD_2,SCREEN0_ADD_1,SCREEN0_ADD_0);
__delay_ms(2);
MemUnprotectSector (SCREEN0_ADD_2,SCREEN0_ADD_1,SCREEN0_ADD_0);
__delay_ms(2);
//TxSPIData2Mem(spi_comm_buffer,SPI_COMM_BUFFER_SIZE,SCREEN0_ADD_2,SCREEN0_ADD_1,SCREEN0_ADD_0);
while(MemWritePageByte(spi_comm_buffer,SPI_COMM_BUFFER_SIZE,SCREEN0_ADD_2,SCREEN0_ADD_1,SCREEN0_ADD_0)!=MEM_WRITE_OK)
{}
__delay_ms(500);
MemUnprotectSector (SCREEN0_ADD_2,SCREEN0_ADD_1,SCREEN0_ADD_0);
__delay_ms(2);
RxSPIMemData(spi_out_buffer, SPI_COMM_BUFFER_SIZE,SCREEN0_ADD_2,SCREEN0_ADD_1,SCREEN0_ADD_0);
__delay_ms(500);
TxUART(spi_out_buffer, SPI_COMM_BUFFER_SIZE);
__delay_ms(5);
TxUART(spi_comm_buffer, SPI_COMM_BUFFER_SIZE);
__delay_ms(500);
}
}
}
#include "PIC16F883_HAL_functions.h"
void configuracion(void)
{
// Configuraci?n del oscilador, el timer0 y el WD
FREQUENCY_SELECT = FREQ_8MHZ;//Internal Oscillator Frequency Select bits, 111 = 8 MHz
SYS_CLOCK_SEL = SYS_CLK_INTERNAL_OSC;
ANSEL = 0b00000000;
ANSELH = 0b00000000;
TFT_DB0_IO = OUTPUT;
TFT_DB1_IO = OUTPUT;
TFT_DB2_IO = OUTPUT;
TFT_DB3_IO = OUTPUT;
TFT_DB4_IO = OUTPUT;
uC_SPI_CS_IO = OUTPUT;
TFT_DB6_IO = OUTPUT;
TFT_DB5_IO = OUTPUT;
TFT_RD_IO = OUTPUT;
TFT_WR_IO = OUTPUT;
TFT_RS_IO = OUTPUT;
TFT_RESET_IO = OUTPUT;
TFT_CS_IO = OUTPUT;
PUERTO_LIBRE0_IO = INPUT;
ICSPCLK_IO = INPUT;
ICSPDAT_IO = INPUT;
TFT_DB7_IO = OUTPUT;
PUERTO_LIBRE1_IO = INPUT;
MEM_CS_IO = OUTPUT;
SPI_CK_IO = OUTPUT;
SPI_DI_IO = INPUT;
SPI_DO_IO = OUTPUT;
UART_TX_IO = OUTPUT;
UART_RX_IO = INPUT;
PORTA = 0;
PORTB = 0;
PORTC = 0;
nPORTB_PULLUPS=1;//PORTB pull-ups are disabled
TIMER0_CLK_SOURCE = CLK_SRC_INT_OSC;//0 = Internal instruction cycle clock (FOSC/4)
PRESCALER_ASSIGNMENT = PSA_WDT;//1 = Prescaler is assigned to the WDT
TMR0=0;//
WDT_PRESCALER = 0b0111;//1;4096
//WDTCONbits.SWDTEN=1;//watchdog habilitado (software enable)
// Configuraci?n de interrupciones
GENERAL_INT_EN = 1; //habilito irq general
PERIF_INT_EN = 0; //habilito irq perifericos
TIMER0_INT_EN = 1; //habilito irq por Timer0
flag_TIMER0_INT = 0; //flag de irq x timer overflow
//Configuracion SPI
configSPI();
//Configuración UART
configUSART();
}
/******************************************************************************/
/* */
/******************************************************************************/
void configSPI(void)
{
SPI_SAMPLE_BIT_CONF = 0; //Input data sampled at middle of data output time
SPI_CKP_CONF = 1; //El estado idle del clock es en '1'
SPI_CKE_CONF = 0; //Con CKP=1, Data transmitted on falling edge of SCK
SPI_PORTMODE_CONF = 0b0010; //SPI master mode - clock Fosc/64 (Fosc 8MHz - Fck 125kHz)
SPI_EN = 1;
}
/******************************************************************************/
/* Enviar datos por SPI */
/******************************************************************************/
void TxSPI (char data)
{
SPI_BUFFER = data;
while (!SPI_BUFFER_FULL_FLAG) // Esperar a que la transmisión termine
CLEAR_WDT;
}
/******************************************************************************/
/* Recibir daots por SPI */
/******************************************************************************/
char RxSPI (void)
{
SPI_BUFFER = SPI_EMPTY_BYTE; // Iniciar la recepción enviando un byte nulo
while (!SPI_BUFFER_FULL_FLAG) // Esperar a que la recepción termine
CLEAR_WDT;
return SPI_BUFFER; // Devolver el dato recibido
}
EDIT2
The schematics is this: memory schematics
The PCB layout: memory pcb
Any help? Ideas?
Thanks in advance.
1 Answer 1
Finally, I've changed the power source of the PIC from 5V to 3,3V. I have removed all the attenuators and the memory started working ok. I thought that at 125kHz the resistors attenuator would work just fine, but I was wrong. Thanks to all who helped!! Regards.
0x1f
is Atmel, and0x58
is "MHS Electronic" (at least in bank 1...) ... do you have a genuine Atmel/Microchip part, or a compatible from another manufacturer? \$\endgroup\$?
characters represent? \$\endgroup\$