2016-02-19 9 views
1

Я использую микроконтроллер PIC32MX350F128L для чтения и записи в EEPROM (SST26VF032B) с использованием связи SPI. Связь SPI в этой программе работает, я проверил ее, отправив код JEDEC, который содержится в спецификации SST26VF032B. Поэтому, когда я отправляю 0x9F, я получаю 3 байта данных, как указано в техническом описании. Когда я запускаю сейчас, я отправляю строку данных на конкретный адрес eeprom и получаю 0xff взамен. Я стираю eeprom, прежде чем писать в него. Так что я думаю, что получаю 0xff после стирания eeprom. Операции записи, чтения не работают. Если я отправляю строку значения или BYTE, я получаю 0xff взамен. Так что, ребята, пожалуйста, предложите мне, где я иду не так. Я использую UART для цели отладки для чтения значений, полученных через spi-связь. Полный код ниже, я использую MPLAB X.Как читать и записывать в EEPROM, запрашивая связь SPI

С наилучшими пожеланиями

Sandesh

#include <xc.h> 
#include <stdio.h> 
#include <plib.h> 
#include <p32xxxx.h> 


/* Configuration Bits */ 

#pragma config FSRSSEL = PRIORITY_7  // Shadow Register Set Priority Select (SRS Priority 7) 
#pragma config PMDL1WAY = ON   // Peripheral Module Disable Configuration (Allow only one reconfiguration) 
#pragma config IOL1WAY = ON    // Peripheral Pin Select Configuration (Allow only one reconfiguration) 

// DEVCFG2 
#pragma config FPLLIDIV = DIV_2   // PLL Input Divider (2x Divider) 
#pragma config FPLLMUL = MUL_20   // PLL Multiplier (20x Multiplier) 
#pragma config FPLLODIV = DIV_1  // System PLL Output Clock Divider (PLL Divide by 1) 

// DEVCFG1 
#pragma config FNOSC = PRIPLL    // Oscillator Selection Bits (Primary Osc (XT,HS,EC)) 
#pragma config FSOSCEN = ON    // Secondary Oscillator Enable (Enabled) 
#pragma config IESO = ON    // Internal/External Switch Over (Enabled) 
#pragma config POSCMOD = HS   // Primary Oscillator Configuration (XT osc mode) 
#pragma config OSCIOFNC = ON   // CLKO Output Signal Active on the OSCO Pin (Enabled) 
#pragma config FPBDIV = DIV_1   // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/8) 
#pragma config FCKSM = CSECME   // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled) 
#pragma config WDTPS = PS1048576  // Watchdog Timer Postscaler (1:1048576) 
#pragma config WINDIS = OFF    // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode) 
#pragma config FWDTEN = OFF    // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls)) 
#pragma config FWDTWINSZ = WINSZ_25  // Watchdog Timer Window Size (Window Size is 25%) 

// DEVCFG0 
#pragma config DEBUG = OFF    // Background Debugger Enable (Debugger is Disabled) 
#pragma config JTAGEN = OFF    // JTAG Enable (JTAG Disabled) 
#pragma config ICESEL = ICS_PGx2  // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2) 
#pragma config PWP = OFF    // Program Flash Write Protect (Disable) 
#pragma config BWP = OFF    // Boot Flash Write Protect bit (Protection Disabled) 
#pragma config CP = OFF     // Code Protect (Protection Disabled) 

/* MACRO DEFINITIONS */ 

/* Defining the Slave Select Pin */ 
#define SS  LATDbits.LATD9 

/* Defining the System Clock Frequency */ 
#define SYSCLK 40000000 

/* Macro to get array size in bytes 
* note that array size can't be found after passing pointer to a function */ 
#define LEN(x) (sizeof(x)/sizeof(x[0])) 

/* SST26VF032B EEPROM instructions */ 

/* Write Enable */ 
#define WREN 0x06 

/* Write Disable */ 
#define WRDI 0x04 

/* Initialize Start of Write Sequence */ 
#define WRITE 0x02  

/* Initialize Start of Read Sequence */ 
#define READ 0x03 

/* Erase all sectors of Memory */ 
#define CE  0xc7 

/* Read STATUS Register */ 
#define RDSR 0x05 

/* Function Prototypes */ 

/* UART bit configuration */ 
void Bitconfig_uart(void); 

/* SPI Initialization */ 
void SPI1_Init(void); 

/* UART Initialization */ 
void Init_uart(void); 

/* Send a Character Byte through UART */ 
void UART5PutChar(char Ch); 

/* Function to Read and Write SPI1 buffer */ 
int SPI1_transfer(int b); 

/* Function to check the Status of SPI */ 
void waitBusy(); 

/* Function to erase the contents in EEPROM */ 
void eraseEEPROM(); 

/* Function to Read data from EEPROM */ 
void readEEPROM(int address, char* loadArray, int loadArray_size); 

/* Function to Write to EEPROM */ 
void writeEEPROM(int address, char* storeArray, int storeArray_size); 

/* Global Variables Declaration */ 
/* Declare variables to check the functionality of EEPROM */ 
int i,j = 0; 
char st = 0x9F; 
char rec; 
int x,y,z; 

/******************************************************************************* 
* Function Name: main() 
******************************************************************************** 
* Summary: 
* Initializes SPI 
* Erase EEPROM 
* Writes to EEPROM 
* Read from EEPROM 
* 
* Parameters: 
* None. 
* 
* Return: 
* None. 
* 
*******************************************************************************/ 
int main() 
{  

    int i; 
    /* Clock Setting */ 
    SYSTEMConfigPerformance(SYSCLK); 

    /* UART bit configuration */ 
    Bitconfig_uart(); 

    /* Set the Controller OScillator Register bits */ 
    //OSCCON = 0x00002200; 

    /* Initialize a String to Write to EEPROM and an array to Read back contents */ 
    char writeData[] = "123456789ABCDEF"; 

    /* Array to read 35 bytes of data */ 
    char readData[15]; 

    /* SPI Initialization */ 
    SPI1_Init(); 

    /* UART Initialization */ 
    Init_uart(); 

    /* Erase contents of EEPROM */ 
    eraseEEPROM(); 

    /* Write contents of writeData array to address 180 */ 
    writeEEPROM(0x1000, writeData, LEN(writeData)); 

    /* 
    JEDEC Code (working) getting output as per datasheet (0x9F = 159) 
    SS=0; 
    SPI1_transfer(159); 
    x=SPI1_transfer(0); 
    UART5PutChar(x); 
    y=SPI1_transfer(0); 
    UART5PutChar(y); 
    z=SPI1_transfer(0); 
    UART5PutChar(z); 
    */ 
    while(1) 
    { 
     /* Read contents of EEPROM into readData array 
     * start at address 180 and read up to 180+length(readData) */ 
     readEEPROM(0x1000, readData, LEN(readData)); 
    } 
} /* END main() */ 

/******************************************************************************* 
* Function Name: SPI1_Init() 
******************************************************************************** 
* Summary: 
* SPI1 Initialization 
* 
* Parameters: 
* None. 
* 
* Return: 
* None. 
* 
*******************************************************************************/ 
void SPI1_Init(void) 
{ 
    /* Configure Peripheral Pin Select (PPS) for the SPI1 module 
    * Note: SS will be toggled manually in code 
    * SCK is hardwired to pin 55 */ 

    /* Output Pin Selection */ 
    RPE5R = 8; 
    SDI1R = 3; 

    /* RB4 (Slave Select 1) : output */ 
    TRISDbits.TRISD9 = 0;  

    /* SPI configuration */ 

    /* SPI1CON Register Configuration 
    * MSTEN: Master Mode Enable bit = 1 (Master) 
    * CKP (clock polarity control) = 0 
    * CKE (clock edge control) = 1 
    * ON: SPI Peripheral On bit 
    * 8-bit, Master Mode */ 
    SPI1CON = 0x8120; 

    /* SPI1BRG Register Configuration */ 
    SPI1BRG = 0x4D; 
    //REFOCONbits.ON = 1; 
    // REFOCONbits.DIVSWEN = 1; 
} 

/******************************************************************************* 
* Function Name: SPI1_transfer() 
******************************************************************************** 
* Summary: 
* Write to and Read from SPI1 buffer 
* 
* Parameters: 
* char b - Writes a Character to Buffer 
* 
* Return: 
* Char - Returns the Character Read from EEPROM 
* 
*******************************************************************************/ 
int SPI1_transfer(int b) 
{ 
    /* write to buffer for TX */ 
    SPI1BUF = b;  

    /* wait transfer complete */ 
    while(!SPI1STATbits.SPIRBF);  

    /* read the received value */ 
    return SPI1BUF;      
} /* END SPI1_transfer() */ 


/******************************************************************************* 
* Function Name: waitBusy() 
******************************************************************************** 
* Summary: 
* Checks if EEPROM is ready to be modified and waits if not ready 
* 
* Parameters: 
* None. 
* 
* Return: 
* None. 
* 
*******************************************************************************/ 
void waitBusy() 
{ 
    char status = 0; 

    do{ 
     /* Select EEPROM */ 
     SS = 0; 

     /* Read EEPROM status register */ 
     SPI1_transfer(RDSR);  

     /* send dummy byte to receive incoming data */ 
     status = SPI1_transfer(0); 

     /* Release EEPROM */ 
     SS = 1;       
    } 

    /* write-in-progress while status<0> set to '1' */ 
    while(status & 0x01);    

} /* END waitBusy() */ 




/******************************************************************************* 
* Function Name: readEEPROM() 
******************************************************************************** 
* Summary: 
* Reads data from EEPROM 
* 
* Parameters: 
* Inputs: address - EEPROM address 
*   loadArray - array to load EEPROM data to 
*   loadArray_size - number of bytes of EEPROM data to load into array 
* 
* Return: 
* None. 
* 
*******************************************************************************/ 
void readEEPROM(int address, char* loadArray, int loadArray_size) 
{ 
    int i; 

    /* Wait until EEPROM is not busy */ 
    waitBusy(); 

    /* Select EEPROM */ 
    SS = 0;     

    /* Initiate Read */ 
    SPI1_transfer(READ);   

    /* Address must be 16-bits but we're transferring it in two 8-bit sessions */ 
    SPI1_transfer(address >> 16); 
    SPI1_transfer(address >> 8); 
    SPI1_transfer(address);  

    /* Request and store loadArray_size number of bytes into loadArray */ 
    for(i=0 ; i<loadArray_size ; i++) 
    { 
     /* send dummy byte to read 1 byte */ 
     loadArray[i] = SPI1_transfer(0x00); 
    } 
    /* Release EEPROM */ 
    SS = 1;       

     /* UART Test */ 
     for(i=0;i<35;i++) 
     { 
      UART5PutChar(loadArray[i]); 
      for(j=0;j<20000;j++) 
      {} 
     } 

} /* END readEEPROM() */ 

/******************************************************************************* 
* Function Name: writeEEPROM() 
******************************************************************************** 
* Summary: 
* Write data to EEPROM 
* 
* Parameters: 
* Inputs: address - EEPROM address 
*   storeArray - array of which contents are stored in EEPROM 
*   storeArray_size - number of bytes in array to store into EEPROM 
* 
* Return: 
* None. 
* 
*******************************************************************************/ 

void writeEEPROM(int address, char* storeArray, int storeArray_size) 
{ 
    int i; 

    /* Wait until EEPROM is not busy */ 
    waitBusy(); 

    /* Select EEPROM */ 
    SS = 0; 

    /* Send WRITE_ENABLE command */ 
    SPI1_transfer(WREN); 

    /* Release EEPROM */ 
    SS = 1;     

    /* Select EEPROM again after WREN cmd */ 
    SS = 0; 

    /* Initiate Write */ 
    SPI1_transfer(WRITE); 

    SPI1_transfer(address >> 16); 
    SPI1_transfer(address >> 8); 
    SPI1_transfer(address); 

    /* write 1 byte at a time from array */ 
    /* MSB at lowest address (0 - first letter in string) */ 
    for(i=0 ; i<storeArray_size; i++) 
    { 
      /* Initiate Write */ 
      SPI1_transfer(WRITE); 
      SPI1_transfer((address+i) >> 16); 
      SPI1_transfer((address+i) >> 8); 
      SPI1_transfer(address+i); 

     SPI1_transfer(storeArray[i]); 
    } 
    /* Release EEPROM */ 
    SS = 1;      

} /* END writeEEPROM() */ 

/******************************************************************************* 
* Function Name: eraseEEPROM() 
******************************************************************************** 
* Summary: 
* Erase entire contents of EEPROM 
* 
* Parameters: 
* None 
* 
* Return: 
* None. 
* 
*******************************************************************************/ 
void eraseEEPROM() 
{ 
    /* Wait until EEPROM is not busy */ 
    waitBusy(); 

    /* Select EEPROM */ 
    SS = 0;    

    /* Send WRITE_ENABLE command */ 
    SPI1_transfer(WREN); 

    /* Release EEPROM */ 
    SS = 1;     

    /* Select EEPROM again after WREN cmd */ 
    SS = 0;    

    /* send CHIP_ERASE command */ 
    SPI1_transfer(CE); 

    /* Release EEPROM */ 
    SS = 1;     

} /* END eraseEEPROM() */ 

/******************************************************************************* 
* Function Name: Init_uart() 
********************************************g************************************ 
* Summary: 
* Initialize UART4 
* 
* Parameters: 
* None 
* 
* Return: 
* None. 
* 
*******************************************************************************/ 
void Init_uart() 
{ 
    /* Enable UART */ 
    U5MODEbits.ON = 1 ; 

    /* set baud rate(9600) */ 
    U5BRG = 521; 

    /* Set U4STA Register for Enabling tx and rx */ 
    U5STA=0x9400; 

} 

/******************************************************************************* 
* Function Name: UART4PutChar(unsigned char Ch) 
******************************************************************************** 
* Summary: 
* Send data from controller to putty GUI 
* 
* Parameters: 
* input 
* unsigned char Ch - To Send a byte of data over UART 
* 
* Return: 
* None. 
* 
*******************************************************************************/ 
void UART5PutChar(char Ch) 
{ 
while(U5STAbits.UTXBF == 1); 
U5TXREG=Ch; 
} 

/******************************************************************************* 
* Function Name: Bitconfig_uart() 
******************************************************************************** 
* Summary: 
* UART Pin Configuration 
* 
* Parameters: 
* None 
* 
* Return: 
* None. 
* 
*******************************************************************************/ 
void Bitconfig_uart(void) 
{ 
    /* UART4 Initialization */ 
    // OSCCON=0x00002200; 

    /* Set pins as digital */ 
    ANSELBbits.ANSB2 = 0; 
    ANSELBbits.ANSB0 = 0; 

    /* Set UART Tx pin as Output */ 
    TRISBbits.TRISB0 = 0; //in controler tx 
    TRISBbits.TRISB2 = 1; // in controller RX  


    /* Peripheral Pin select for UART4 */ 
    U5RXR=0x07; 
    RPB0R=0x04; 
} 

ответ

1

я столкнулся с той же проблемой в течение 3 долгих дней, пока я не нашел, что есть 18bytes длинный регистр под названием Block Регистр защиты BPR. Вам нужно установить свои биты в 0, в соответствии с областью памяти, которую вы хотите записать.

Итак, я прочитал BPR (команда отправки 0x72, за которой следует 18 байтов), и я обнаружил, что во всем моем случае это было не везде. Чтение на стр. 41 таблицы показывает, что после включения питания в регистре BPR установлено значение 5555 FFFFFFFF FFFFFFFF, поэтому он защищает от записи всей памяти.

Итак, для целей тестирования я попытался полностью очистить его, и для этой цели есть специальная команда (0x98), позволяющая писать где угодно во всей памяти.

Но перед отправкой ясной команды BPR (команда 0x98) обязательно запишите память (команда 0x06).

На этом этапе, если вы прочитали BPR (команда 0x72), вы будете читать 00 на каждом из своих 10 байтов. (И это означает, что вся память теперь доступна для записи)

В этом состоянии, наконец, запись для меня работает. (я отправил WriteEnable - SectorErase - SectorRead - WriteEnable - SectorWrite - SectorRead, и теперь он работает!)

Надеюсь, что это поможет, техническое описание очень хаотично.

P.S. Где-то в техническом описании указано, что BPR составляет 18 байтов, это неправильно, BPR составляет всего 10 байт.