SPI就是用4條線來串行傳輸數據, 2541只能用模擬的方式用GPIO來做.
//******************************************************************************
// INCLUDES
//******************************************************************************
#include <ioCC2541.h>
#include "hal_spi_master.h"
#include "OSAL.h"
#include "hal_mcu.h"
#include <string.h>
#define SPI_CS P1_4
#define SPI_CLK P1_5
#define SPI_MOSI P1_6
#define SPI_MISO P1_7
//4個GPIO引腳
#define SPI_MAX_PACKET_LEN 39
#define SPI_MAX_DATA_LEN 35
const uint8 W25X_ReadData=0x03;
void startSending(void);
void _nop_(void){
}
//下面的delay 1ms在紅外遙控器里面改寫過, 因為需要更精確的delay.
void SPI_DLY_ms(unsigned int ms)
{
unsigned int a;
while(ms)
{
a=1800;
while(a--);
ms--;
}
return;
}
void SPI_DLY_us(unsigned int us)
{
unsigned int a;
while(us)
{
a=2;
while(a--);
us--;
}
return;
}
void SPI_Init(void)
{
P1SEL &= 0x0F; //將 P1.4 P1.5 P1.6 P1.7 設置為GPIO引腳 00001111
P1DIR |= 0x70; //設置 P1.4 P1.5, p1.6 引腳為輸出, P1.7 為輸入 01110000
SPI_SendByte(0xff);
}
void SPI_GetFlashID(void){
uint16 Temp = 0;
//startSending();
SPI_CS=0;
SPI_SendByte(0x90);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
Temp|=SPI_ReadByte()<<8;
Temp|=SPI_ReadByte();
SPI_CLK=1;
_nop_();
SPI_CS=1;
}
void W25Q64_Read(uint8* pBuffer,uint8* readAddr,uint16 NumByteToRead){
int i;
SPI_CS=0;
SPI_SendByte(0x03);
//SPI_SendByte((uint8)((ReadAddr)>>16));
//SPI_SendByte((uint8)((ReadAddr)>>8));
SPI_SendByte(readAddr[0]);
SPI_SendByte(readAddr[1]);
SPI_SendByte(readAddr[2]);
//SPI讀W25Q時, 先發頁地址.
//SPI_SendByte((uint8)ReadAddr);
for(i=0;i<NumByteToRead;i++){
pBuffer[i]=SPI_ReadByte(); //循環讀
}
SPI_CLK=1;
_nop_();
SPI_CS=1;
}
//發送一個字節, 基本上先拉低使能CS腳, 然后不斷的時鍾高低, 在時鍾的后變化沿, 就是所謂clock tailing edge, 讀MISO值.
uint8 SPI_ReadByte(void){
unsigned char i=0, in=0, temp=0;
//SPI_CS=0;
//先拉低, 然后拉高的時候, 讀取MISO
SPI_CLK = 0;
for(i=0;i<8;i++){
in = (in << 1);
SPI_CLK = 1;
//SPI_DLY_us(1);
temp = SPI_MISO;
if (temp == 1){
in = in | 0x01;
}
SPI_CLK = 0;
//SPI_DLY_us(1);
}
//SPI_CS=1;
return in;
}
//發送字節也是一樣, 先拉低時鍾, 然后發送, 然后拉高.
void SPI_SendByte(uint8 cmd){
unsigned char i=8, temp=0;
//SPI_CS=0;
for(i=0;i<8;i++){
SPI_CLK=0;
temp = cmd&0x80;
if (temp == 0)
{
SPI_MOSI = 0;
}
else
{
SPI_MOSI = 1;
}
cmd<<=1;;
SPI_CLK=1;
//SPI_DLY_us(1);
}
SPI_MOSI=1;
}
重點是配合邏輯分析儀使用, 用STM32的板子硬件SPI的波形做參考, 慢慢調就行.