PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mcp25lc256_spi_eeprom.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 #include "pic24_all.h"
31 
32 /** \file
33 SPI Example: Demonstrates SPI functions by reading/writing
34 from that Microchip 25LC256 serial EEPROM that is on the
35 Explorer-16 board.
36 
37 */
38 
39 
40 #define CONFIG_SLAVE_ENABLE() CONFIG_RD12_AS_DIG_OUTPUT()
41 #define SLAVE_ENABLE() _LATD12 = 0 //low true assertion
42 #define SLAVE_DISABLE() _LATD12 = 1
43 
44 #define EEPROM_RDSR 0x05 //read status register command
45 #define EEPROM_READ 0x03 //read command
46 #define EEPROM_WRITE 0x02 //write command
47 #define EEPROM_WENABLE 0x06 //write command
48 
49 #define BLKSIZE 64
50 
51 void configSPI2(void) {
52  //spi clock = 40MHz/1*4*4 = 40MHz/16 = 2.5 MHz
53  SPI2CON1 = SEC_PRESCAL_4_1 | //4:1 secondary prescale
54  PRI_PRESCAL_4_1 | //4:1 primary prescale
55  CLK_POL_ACTIVE_HIGH | //clock active high (CKP = 0)
56  SPI_CKE_ON | //out changes active to inactive (CKE=1)
57  SPI_MODE8_ON | //8-bit mode
58  MASTER_ENABLE_ON; //master mode
59  SPI2STATbits.SPIEN = 1; //enable SPI mode
60  CONFIG_SLAVE_ENABLE(); //chip select for MCP41xxx
61  SLAVE_DISABLE(); //disable the chip select
62 }
63 
64 //Assumes WDT is configured for longer than EEPROM write time
65 void waitForWriteCompletion() {
66  uint8_t u8_spidata,u8_savedSWDTEN;
67  u8_savedSWDTEN = _SWDTEN;
68  _SWDTEN = 1; //enable WDT so that do not get stuck in infinite loop!
69  do {
70  SLAVE_ENABLE();
71  u8_spidata = ioMasterSPI2(EEPROM_RDSR); //send read status command
72  u8_spidata = ioMasterSPI2(0); //get status back
73  SLAVE_DISABLE();
74  } while (u8_spidata & 0x01); //LSB of status is write-in-progress flag
75  _SWDTEN = u8_savedSWDTEN; //restore WDT to original state
76 }
77 
78 //Write enable must be done before attempting a write.
79 void writeEnable() {
80  SLAVE_ENABLE();
81  ioMasterSPI2(EEPROM_WENABLE);
82  SLAVE_DISABLE();
83 }
84 
85 void memWrite25LC256(uint16_t u16_MemAddr, uint8_t *pu8_buf) {
86  uint8_t u8_AddrLo, u8_AddrHi;
87  uint8_t u8_i;
88 
89  u8_AddrLo = u16_MemAddr & 0x00FF;
90  u8_AddrHi = (u16_MemAddr >> 8);
91 
92  waitForWriteCompletion();
93  writeEnable(); //enable the write
94  SLAVE_ENABLE();
95  ioMasterSPI2(EEPROM_WRITE);
96  ioMasterSPI2(u8_AddrHi);
97  ioMasterSPI2(u8_AddrLo);
98  for (u8_i=0; u8_i< BLKSIZE; u8_i++) {
99  ioMasterSPI2(pu8_buf[u8_i]);
100  }
101  SLAVE_DISABLE();
102 }
103 
104 void memRead25LC256(uint16_t u16_MemAddr, uint8_t *pu8_buf) {
105  uint8_t u8_AddrLo, u8_AddrHi;
106  uint8_t u8_i;
107 
108  waitForWriteCompletion();
109  u8_AddrLo = u16_MemAddr & 0x00FF;
110  u8_AddrHi = (u16_MemAddr >> 8);
111  SLAVE_ENABLE();
112  ioMasterSPI2(EEPROM_READ);
113  ioMasterSPI2(u8_AddrHi);
114  ioMasterSPI2(u8_AddrLo);
115  for (u8_i=0; u8_i<BLKSIZE ; u8_i++) {
116  pu8_buf[u8_i] = ioMasterSPI2(0) ; //get one byte
117  }
118  SLAVE_DISABLE();
119 }
120 
121 
122 int main (void) {
123  uint8_t au8_buf[BLKSIZE]; //holds data for EEPROM I/O
124  uint16_t u16_MemAddr;
125  uint8_t u8_Mode;
126 
127  configBasic(HELLO_MSG);
128  configSPI2(); //configure SPI2 Module
129  outString("\nEnter 'w' for write mode, anything else reads: ");
130  u8_Mode = inCharEcho();
131  outString("\n");
132  u16_MemAddr = 0; //start at location 0 in memory
133  while (1) {
134  uint8_t u8_i;
135  if (u8_Mode == 'w') {
136  outString("Enter 64 chars.\n");
137  //first two buffer locations reserved for starting address
138  for (u8_i = 0; u8_i< BLKSIZE; u8_i++) {
139  au8_buf[u8_i] = inCharEcho();
140  }
141  outString("\nDoing Write\n");
142  // write same string twice to check Write Busy polling
143  memWrite25LC256(u16_MemAddr, au8_buf); // do write
144  u16_MemAddr = u16_MemAddr + BLKSIZE;
145  memWrite25LC256(u16_MemAddr,au8_buf); // do write
146  u16_MemAddr = u16_MemAddr + BLKSIZE;
147  } else {
148  memRead25LC256(u16_MemAddr,au8_buf); // do read
149  for (u8_i = 0; u8_i< BLKSIZE; u8_i++) outChar(au8_buf[u8_i]);
150  outString("\nAny key continues read...\n");
151  inChar();
152  u16_MemAddr = u16_MemAddr + BLKSIZE;
153  }
154  }
155 }