?? spi.c
字號:
/*****************************************************************************
* *
* ********** *
* ************ *
* *** *** *
* *** +++ *** *
* *** + + *** *
* *** + CHIPCON CC1010 EXAMPLE PROGRAM *
* *** + + *** SPI *
* *** +++ *** *
* *** *** *
* *********** *
* ********* *
* *
*****************************************************************************
* The program demonstrates the use of the SPI macros and functions: *
* - SPI_CONTROL() *
* - MOSI_OE() *
* - SPI_DATA *
* - SPI_IS_ACTIVE *
* - halSpiTransferBlock() *
* *
* The example program requires the X25020 SPI Serial EEPROM wired to a flat *
* test cable inserted on the CC1010 evaluation board. However, the program *
* is written primarily as an example on how to use the SPI functions and *
* the methods are easily extended to other external SPI slave chips. *
* *
* The X25020 has the following pins and connections besides VDD and GND: *
* CS_N -> P0.3 HOLD_N -> VDD *
* SO -> P0.2 SCK -> P0.0 *
* WP_N -> VDD SI -> P0.1 *
*****************************************************************************
* Author: ARR *
*****************************************************************************
* Revision history: *
* 1.0 2002/08/20 First public release *
* *
* $Log: spi.c,v $
* Revision 1.2 2002/11/19 15:41:40 kht
* Added startup macros
*
* Revision 1.1 2002/10/14 11:11:31 tos
* Initial version in CVS.
*
* *
****************************************************************************/
#include <chipcon/hal.h>
#include <chipcon/cc1010eb.h>
#include <stdlib.h>
#include <string.h>
// Define X25020 instructions
#define INST_WREN 0x06
#define INST_WRDI 0x04
#define INST_RDSR 0x05
#define INST_WRSR 0x01
#define INST_READ 0x03
#define INST_WRIT 0x02
// Define the addresses
#define RAMBUF1_ADDRESS 0x0000
#define RAMBUF2_ADDRESS 0x0100
#define BUF_SIZE 256
// EEPROM access function prototypes
void eepromReadByte(byte address); // one byte only
void eepromReadBytes(byte address, byte xdata *buffer, word length);
void eepromWriteByte(byte address, byte databyte); // one byte only
bool eepromWriteBytes(byte address, byte xdata *buffer, word length); // 1-256 bytes
void eepromReadStatus(void);
void eepromWriteStatus(byte databyte);
void eepromWriteEnable(void);
void eepromWriteDisable(void);
void eepromWait(void);
void eepromWriteWait(void);
// Set up properly aligned RAM buffers
byte xdata ramBuf1[BUF_SIZE] _at_ RAMBUF1_ADDRESS;
byte xdata ramBuf2[BUF_SIZE] _at_ RAMBUF2_ADDRESS;
// Array which will be initialized with random bytes
byte xdata rndData[BUF_SIZE];
int main() {
int i;
// Turn off watchdog timer
WDT_ENABLE(FALSE);
// Set optimum settings for speed and low power consumption
MEM_NO_WAIT_STATES();
FLASH_SET_POWER_MODE(FLASH_STANDBY_BETWEEN_READS);
// All I/Os are inputs after reset. Make I/Os connected to LEDs outputs
RLED=YLED=GLED=BLED=LED_OFF;
RLED_OE(TRUE); YLED_OE(TRUE); GLED_OE(TRUE); BLED_OE(TRUE);
// Set up P0.3 as output to CS_N
PORTDIRBIT(0,3,POUT);
// Fill rndData with random contents.
srand(0xF012);
for (i=0; i<BUF_SIZE; i++)
rndData[i]=rand()%0xFF;
memcpy(ramBuf1, rndData, BUF_SIZE);
// Set up SPI for transfer. MSB first, sample on posedge,
// output on negedge, SCK = CLK/16, three-wire protocol
SPI_CONTROL(SPI_SPM_DISABLED | SPI_ENABLE | SPI_MSB_FIRST |
SPI_POSEDGE_IDLE0 | SPI_CLK_DIV_64);
MOSI_OE(TRUE);
// Set write enable latch
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_WREN;
while (SPI_IS_ACTIVE);
PORTBIT(0,3) = 1; // Set CS_N high
for (i=0;i<8;i++);
// Read status register
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_RDSR;
while (SPI_IS_ACTIVE);
SPI_DATA = 0x00; // clock in answer
while (SPI_IS_ACTIVE);
PORTBIT(0,3) = 1; // Set CS_N high
for (i=0;i<8;i++);
// Write and read back 2 bytes
eepromWriteByte(0x00, 0xA5);
eepromWriteByte(0xE1, 0x73);
eepromReadByte(0x00);
if (SPI_DATA != 0xA5)
YLED = LED_ON;
eepromReadByte(0xE1);
if (SPI_DATA != 0x73)
GLED = LED_ON;
// Write and read a buffer in EEPROM, wraparound address
eepromWriteBytes(0xFB, ramBuf1, BUF_SIZE);
eepromReadBytes(0xFB, ramBuf2, BUF_SIZE);
if (memcmp(ramBuf1, ramBuf2, BUF_SIZE))
RLED = LED_ON;
else
GLED = LED_ON;
// Write and read another buffer, different address size
eepromWriteBytes(0x49, ramBuf1, 27);
eepromReadBytes(0x49, ramBuf2, 27);
if (memcmp(ramBuf1, ramBuf2, 27))
RLED = LED_ON;
else
GLED = LED_ON;
// Write protect 1/4 and read back status register
eepromWriteStatus(0x04);
eepromReadStatus();
// Attempt to write protected part
eepromWriteByte(0xC0, 0xAA);
eepromReadByte(0xC0);
if (SPI_DATA != 0xAA)
RLED = LED_ON;
else
YLED = LED_ON;
// Attempt to write unprotected part
eepromWriteByte(0xBF, 0xCC);
eepromReadByte(0xBF);
if (SPI_DATA != 0xCC)
RLED = LED_ON;
else
YLED = LED_ON;
// Switch off LEDs
RLED = LED_OFF;
YLED = LED_OFF;
GLED = LED_OFF;
// Disable protection, write contiguous buffer and check
eepromWriteStatus(0x00);
eepromWriteBytes(0xBE, ramBuf1, 4);
eepromReadBytes(0xBE, ramBuf2, 4);
if (memcmp(ramBuf1, ramBuf2, BUF_SIZE))
RLED = LED_ON;
else
GLED = LED_ON;
// Check disabling of write
eepromWriteEnable();
eepromReadStatus();
if (SPI_DATA != 0x02)
RLED = LED_ON;
else
YLED = LED_ON;
eepromWriteDisable();
eepromReadStatus();
if (SPI_DATA)
RLED = LED_ON;
else
BLED = LED_ON;
// Disable SPI
SPI_CONTROL(SPI_DISABLE);
// Infinite loop
while(1);
}
// EEPROM access functions
// Function reads a byte at the specified address location
// SPDR will contain the read byte
void eepromReadByte(byte address) {
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_READ; // write instruction
while (SPI_IS_ACTIVE);
SPI_DATA = address; // write address
while (SPI_IS_ACTIVE);
SPI_DATA = 0x00; // clock in answer
while (SPI_IS_ACTIVE);
PORTBIT(0,3) = 1; // Set CS_N high
eepromWait();
}
// Function reads _length_ bytes from the specified address
// location and puts them in _buffer_
void eepromReadBytes(byte address, byte xdata *buffer, word length) {
word i;
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_READ; // write instruction
while (SPI_IS_ACTIVE);
SPI_DATA = address; // write address
while (SPI_IS_ACTIVE);
for (i=0; i<length; i++) {
SPI_DATA = 0x00; // clock in answer
while (SPI_IS_ACTIVE);
*buffer = SPI_DATA;
buffer++;
}
PORTBIT(0,3) = 1; // Set CS_N high
eepromWait();
}
// Function writes specified byte to the specified address location
void eepromWriteByte(byte address, byte databyte) {
eepromWriteEnable(); // Must enable write latch first
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_WRIT; // write instruction
while (SPI_IS_ACTIVE);
SPI_DATA = address; // write address
while (SPI_IS_ACTIVE);
SPI_DATA = databyte; // write data
while (SPI_IS_ACTIVE);
PORTBIT(0,3) = 1; // Set CS_N high
eepromWait();
eepromWriteWait();
}
// Function writes _length_ bytes to the specified address location
bool eepromWriteBytes(byte address, byte xdata *buffer, word length) {
word bytes_to_write;
byte page_index_address = address;
if (!length)
return FALSE;
// The following algorithm divides the data buffer into 4-byte
// page entities. If the supplied address is not on a page
// boundary, 1-3 bytes are written first, then full pages are
// written until the end of the buffer.
while (length) {
eepromWriteEnable(); // Must enable write latch first
// Pre-processing
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_WRIT; // write instruction
while (SPI_IS_ACTIVE);
SPI_DATA = page_index_address; // write address
while (SPI_IS_ACTIVE);
// Decide number of bytes in page
switch (page_index_address & 0x03) {
case 0x00: bytes_to_write = 4; break;
case 0x01: bytes_to_write = 3; break;
case 0x02: bytes_to_write = 2; break;
case 0x03: bytes_to_write = 1; break;
default: break;
}
// Write data bytes, 1-4
if (length<bytes_to_write) {// true only for last page
halSpiTransferBlock(buffer, length, FALSE);
length = 0;
}
else {
halSpiTransferBlock(buffer, bytes_to_write, FALSE);
buffer+=bytes_to_write;
length-=bytes_to_write;
}
// Address adjustment
page_index_address += bytes_to_write;
// Post-processing
PORTBIT(0,3) = 1; // Set CS_N high
eepromWait();
eepromWriteWait();
}
return TRUE;
}
// Function reads the EEPROM status register
// SPDR will contain the status byte
void eepromReadStatus(void) {
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_RDSR; // write instruction
while (SPI_IS_ACTIVE);
SPI_DATA = 0x00; // clock in answer
while (SPI_IS_ACTIVE);
PORTBIT(0,3) = 1; // Set CS_N high
eepromWait();
}
// Function writes the EEPROM status register
void eepromWriteStatus(byte databyte) {
eepromWriteEnable(); // Must enable write latch first
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_WRSR; // write instruction
while (SPI_IS_ACTIVE);
SPI_DATA = databyte; // write status byte
while (SPI_IS_ACTIVE);
PORTBIT(0,3) = 1; // Set CS_N high
eepromWait();
eepromWriteWait();
}
// Function sets the write enable latch
void eepromWriteEnable(void) {
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_WREN; // write instruction
while (SPI_IS_ACTIVE);
PORTBIT(0,3) = 1; // Set CS_N high
eepromWait();
}
// Function resets the write enable latch
void eepromWriteDisable(void) {
PORTBIT(0,3) = 0; // Set CS_N low
SPI_DATA = INST_WRDI; // write instruction
while (SPI_IS_ACTIVE);
PORTBIT(0,3) = 1; // Set CS_N high
eepromWait();
}
// Function counts 8 clock cycles and waits for write to finish
void eepromWait(void) {
int i;
for (i=0; i<8; i++);
}
// Function waits for write to finish
void eepromWriteWait(void) {
// Wait until finished with write
while (1) {
eepromReadStatus();
if (!(SPI_DATA&0x01)) // Write in progress ?
break;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -