⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 基于cc1010的设计实例
💻 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 + -