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

📄 spi.c

📁 simulink real-time workshop for dragon12 development board from
💻 C
字号:
/**
 * These functions are used to write and read from the SPI.
 * The code was written specifically for the nRF24L01 module.
 * The module has a peculiar implementation of the SPI interface,
 * in which the CSN line must be held low for subsequent bytes
 * of the same message. The implementation uses busy-waiting.
 *
 * @author Stephen Craig 25/07/2006
 */

/* System macros (EXT_MODE, etc.) -- generated by 'gen_cpp_req_defines_h.tlc' */
#include "cpp_req_defines.h"

#if HAS_SPI > 0

#include <mc9s12dp256.h>        /* derivative information */
#include "spi.h"                /* macro definitions */

/**
 * Initialise the SPI.
 * DO NOT USE sci0.h MACROS!
 * @param baudRate one of the SPI_BAUD_XXX defines in spi.h
 */
void SPI_Init(unsigned char baudRate) {
unsigned char dummy;

  /* configure CSN pin as an output */
  CSN_DDR = 1;

/* bit SPICR1
 7 SPIE  = 0   no interrupts
 6 SPE   = 1   enable SPI
 5 SPTIE = 0   SPTEF interrupt disabled
 4 MSTR  = 1   master
 3 CPOL  = 0   output changes on fall, clock normally low
 2 CPHA  = 0   and input clocked in on rise
 1 SSOE  = 0   Slave Select Output Enable
 0 LSBFE = 0   most significant bit first */
  SPI0CR1 = 0x50;
  
/* bit SPICR2
 4 MODFEN = 0  Mode Fault Enable Bit  
 3 BIDIROE= 0  Output enable in the Bidirectional mode of operation
 1 SPISWAI= 0  SPI Stop in Wait Mode Bit
 0 SPC0   = 0  normal mode */
  SPI0CR2 = 0x00;
  
  SPI0BR = baudRate;		// baud rate 
  // bits 6,5,4 are SPPR, bits 2,1,0 are SPR
  // divisor is (1+SPPR)*2**(SPR+1)
  
  dummy = SPI0SR;
  dummy = SPI0DR;  //clear SPIF
}

/**
 * SPI_Pause pauses for the time it takes for the SPI to transmit
 * one byte. Unfortunately, because of the way the radio module wants
 * CSN to remain low for subequent bytes of the same message, coupled
 * with the inability to configure the SPI on the Motorola to behave
 * in this way, there's no straightforward way to exploit parallelism.
 */
void SPI_Pause() {
unsigned short i;

  switch(SPI0BR) {
  case SPI_BAUD_46875:
    for(i = 198; i != 0; i--) {
      
    }  
    break;    
   

  case SPI_BAUD_93750:
    for(i = 97; i != 0; i--) {
    }
    break;


  case SPI_BAUD_187500:
    for(i = 47; i != 0; i--) {
    }
    break;
  
  
  case SPI_BAUD_375000:
    for(i = 22; i != 0; i--) {
    }
    break;

  case SPI_BAUD_750000:
    for(i = 10; i != 0; i--) {
    }
    break;
    
  case SPI_BAUD_1500000:
    for(i = 4; i != 0; i--) {
    }
    break;

  case SPI_BAUD_3000000:
    for(i = 2; i != 0; i--) {
    }
    break;

  case SPI_BAUD_6000000:
    for(i = 1; i != 0; i--) {
    }
    break;
    
  default:
    // #error
    
    // SCI0_OutString("WARNING: Undefined SPI_BAUD_RATE!");

    for(i = 1000; i != 0; i--) {
      // this delay should be sufficient for all baud rates
    }
    break;    
  }
}

/**
 * Wait for new SPI port input, busy-waiting synchronization
 * Returns the character received. Radio code should use
 * SPI_Read() instead.
 * @return character received
 */
unsigned char SPI_InChar(void) {
  while(SPI0SR_SPIF == 0) {}
  return (SPI0DR);
}

/**
 * Wait for output buffer to be empty, output 8-bit to SPI port,
 * busy-waiting synchronization
 * @param data data to be sent to SPI
 */
void SPI_OutChar(unsigned char data) {
  while(SPI0SR_SPTEF == 0) {}

  CSN = 0;

  SPI0DR = data;
  SPI_Pause();  

  CSN = 1;
}

/**
 * Wait for buffer to be empty, output 16-bit to SPI port
 * busy-waiting synchronization. CSN is kept low for both bytes.
 * @param command data to be sent first to SPI
 * @param data data to be sent second to SPI
 */
void SPI_OutChar2(unsigned char command, unsigned char data) {

  while(SPI0SR_SPTEF == 0) {}

  CSN = 0;

  SPI0DR = command;
  while(SPI0SR_SPTEF == 0);
  SPI_Pause();

  SPI0DR = data;
  SPI_Pause();  

  CSN = 1;
}

/**
 * Wait for buffer to be empty, output arbitrary length to SPI port,
 * busy-waiting synchronization. CSN is kept low for all bytes.
 * @param command data to be sent first to SPI
 * @param data data to be sent, starting from address 0
 * @param len the length of the data array
 */
void SPI_OutChar3(unsigned char command,
                  unsigned char *data,
                  unsigned char len) {
unsigned char i;

  while(SPI0SR_SPTEF == 0) {}

  CSN = 0;

  SPI0DR = command;
  SPI_Pause();

  for(i = 0; i<len; i++) {    
    while(SPI0SR_SPTEF == 0) {}
    SPI0DR = data[i];
    SPI_Pause();
  }
  
  CSN = 1;
}

/**
 * Will attempt to read the bytes following the status register
 * which always is sent by the Radio module.
 * @param command read command, specifies which register to start from
 * @param data data is stored in this array
 * @param len the amount of data to read (must be no more than length of data array)
 */
void SPI_Read(unsigned char command,
              unsigned char *data,
              unsigned char len) {
unsigned char dummy, i;

  dummy = SPI0SR;
  dummy = SPI0DR;  // clear SPIF

  while(SPI0SR_SPTEF == 0) {}

  CSN = 0;
  
  SPI0DR = command;
  SPI_Pause();
  dummy = SPI_InChar(); // read and discard the status byte

  for(i=0; i<len; i++) {
    while(SPI0SR_SPTEF == 0) {}
    SPI0DR = 0xff;
    SPI_Pause();
    data[i] = SPI_InChar();
  }

  CSN = 1;
}

#endif /* HAS_SPI */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -