0
\$\begingroup\$

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.

asked Jul 4, 2024 at 12:05
\$\endgroup\$
7
  • \$\begingroup\$ What did you write, and what did you read back? Did you perform an erase before the write? \$\endgroup\$ Commented Jul 4, 2024 at 12:26
  • 1
    \$\begingroup\$ 0x1f is Atmel, and 0x58 is "MHS Electronic" (at least in bank 1...) ... do you have a genuine Atmel/Microchip part, or a compatible from another manufacturer? \$\endgroup\$ Commented Jul 4, 2024 at 12:41
  • \$\begingroup\$ 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 ? 62h ? 2Ch ? ? ? 32h ? 30h 00h 00h 00h 00h} Yes, 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 0xFF The chip is marked as Atmel, I don't know why the response is another manufacturer. \$\endgroup\$ Commented Jul 5, 2024 at 14:20
  • 1
    \$\begingroup\$ Please add this information to your question using the edit button. Can you clarify what the ? characters represent? \$\endgroup\$ Commented Jul 5, 2024 at 15:48
  • 1
    \$\begingroup\$ I have some ideas. Why not check the waveforms with an oscilloscope? Even if the clock is 125 kHz, it will be very rounded due to the resistors used for level shifting. Is there a possibility to use a 5V flash or change the MCU to 3.3V? \$\endgroup\$ Commented Jul 5, 2024 at 22:17

1 Answer 1

0
\$\begingroup\$

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.

answered Jul 8, 2024 at 18:43
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.