📄 spi.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 + -