ESP8266 SDK開發: 外設篇-SPI


 

 

 

 

SPI引腳

 

 

 

 

上程序

 

 

 

 

 

 

 

#include "spi_interface.h"




SpiAttr spiConfig;//配置SPI
SpiData SpiSend;//配置SPI發送的數據

 

 

 

 2.配置GPIO,設置為主機模式

 

 

 

 

3.關於發送數據

首先大家不要被官方規定的發送的幾種數據所迷惑

 

 

 

你要明白,無論是啥命令,地址,數據

都是用SPI發送數據而已

你要是這都不明白....說明你已經被協議弄糊塗了

其實對於通信而言你需要把大的方向搞明白

什么叫:通信方式 (SPI,串口)

什么叫:通信協議 (在通信方式基礎上規定的數據協議)

 

之所以有命令,地址,和數據之分,其實是咱和某個支持SPI的芯片通信的時候

如果想讀取SPI芯片某個寄存器里面的值

你需要先用SPI發送發送讀命令(告訴芯片我要讀數據)

然后用SPI發送要讀取的地址

然后另一個芯片就返回過來數據了

 

3.發送一個字節數據

用cmd測試

 

 

 

為了方便我監控數據,使用了一個1S的硬件定時器

 

 

 

 

        SpiSend.cmd= 0x55;//設置發送的數據
        SpiSend.cmdLen=1;//發送的數據個數(字節為單位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//發送數據

 

監控如下

 

 

 

 


4.發送兩個字節數據

 

 

 

        SpiSend.cmd= 0x55aa;//設置發送的數據
        SpiSend.cmdLen=2;//發送的數據個數(字節為單位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//發送數據

 

測試如下

先傳的0xaa  后傳輸的 0x55

用戶實際應用的時候要注意!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5.再看一下 addr

addr最大可以傳輸一個32位的數據(4字節)

 

 

 

 

5.1 注意下下面的情況

 

 

 

測試如下:

注意:

其實實際上設置為傳輸1位的時候芯片內部默認先取addr數據地址的 低八位

uint32_t data = 0x01;

實際上 data = 0x01000000

傳輸數據的時候芯片先取的最后面的00

使用addr傳輸的1位數據的時候需要注意

 

 

 

 

注意:

注意:

注意:

使用 addr 只要是不傳輸4位數據

芯片內部都會默認先傳低八位

 

使用 addr 無論是只要是不傳輸4位數據

芯片內部都會默認先傳低八位

 

使用 addr 無論是只要是不傳輸4位數據

芯片內部都會默認先傳低八位

 

 

下面看用addr傳輸4位數據

 

 

 

 

u32 cnt = 0;
uint32_t data = 0x0103070f;
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.addr= &data;//設置發送的數據
        SpiSend.addrLen=4;//發送的數據個數(字節為單位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//發送數據
    }
}

 

測試如下:

正好傳輸4位數據的時候,芯片內部默認先傳輸高八位

 

 

 

5.2 傳輸一個u8型4字節的數組,傳輸個數是2字節

芯片默認是先傳輸數組后面的數據,依次向前

 

 

 

 

 

u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.addr= (uint32_t *)(&temp);//設置發送的數據
        SpiSend.addrLen=2;//發送的數據個數(字節為單位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//發送數據
    }
}

 

 

 

 

 

 

 

 

5.3 傳輸一個u8型4字節的數組,如果傳輸個數是4字節

芯片也會先傳輸數組后面的數據,依次向前

 

 

 

 

u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.addr= (uint32_t *)(&temp);//設置發送的數據
        SpiSend.addrLen=2;//發送的數據個數(字節為單位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//發送數據
    }
}

 

 

 

 

 

 

 

 

 

以上為 使用addr 傳輸數據時需要注意的地方

 

 

 

 

 

 

6 現在看一下  data

只要記住一點即可

data 和 上面的 addr 傳輸的時候取數據的方式完全相反

data就不再多加測試:用戶只需要記住上面的話即可!

由此便推導出使用data應該會怎么傳輸

我想官方這樣做是為了應對客戶不同的傳輸數據情況!

 

 

 

 

 

6.1 測試使用data ,u8型數組傳輸2字節的情況

 

 

 

u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.data= (uint32_t *)(&temp);//設置發送的數據
        SpiSend.dataLen=2;//發送的數據個數(字節為單位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//發送數據
    }
}

 

測試如下:

和addr完全相反,data是先傳輸數組前面的數據

 

 

 

6.2 測試使用data ,u8型數組傳輸4字節的情況

 

 

u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.data= (uint32_t *)(&temp);//設置發送的數據
        SpiSend.dataLen=4;//發送的數據個數(字節為單位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//發送數據
    }
}

 

測試如下:

 

 

 

 

關於組合起來

 

 

 

 

 

u32 cnt = 0;
u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.cmd = 0x55;
        SpiSend.cmdLen = 1;
        SpiSend.addr= (uint32_t *)(&temp);//設置發送的數據
        SpiSend.addrLen=4;//發送的數據個數(字節為單位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//發送數據
    }
}

 

 

 

 

測試如下:

總結:

cmd,addr,data的數據該怎么傳還是怎么傳

但是是先傳 cmd 然后 addr 最后 data

 

 

 

 

如果想SPI發送數據的時候接收數據

SPIMasterRecvData(SpiNum spiNum, SpiData* pOutData)

 

 

 

 

 

史上最短的引腳模擬SPI

/**
* @brief  SPI函數
* @param  value--發送的數據
* @param  None
* @param  None
* @retval SPI接收的數據
* @example
**/
unsigned char SPIWriteRead(unsigned char value)
{
    unsigned char i=0,temp=0;
    SPI_CLK = 0;//進入之前其實是高電平
    if(SPI_MISO)temp|=0x80;//接收數據
    for(i=0;i<8;i++)
    {
        SPI_MOSI=value&(0x80>>i);//准備數據
        SPI_CLK=1;
        SPI_CLK = 0;
        if(i<7)if(SPI_MISO)temp|=0x80>>(i+1);//接收數據
    }
    return temp;
}

 

 

源碼在默認最大是20M

按照規律修改為其它頻率

 

 

 

typedef enum
{
    SpiSpeed_2MHz  = 40 - 1,
    SpiSpeed_5MHz  = 16 - 1,
    SpiSpeed_10MHz = 8 - 1,
    SpiSpeed_16MHz = 5 - 1,
    SpiSpeed_20MHz = 4 - 1,
    SpiSpeed_40MHz = 2 - 1,
    SpiSpeed_80MHz = 1 - 1,
} SpiSpeed;

 

 

 

NONOS_SDK版本區別

 

#include "driver/spi_interface.h"

 

 

 

 

/*配置SPI GPIO 口*/
    WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);

    /*配置SPI 模式*/
    spiConfig.mode = SpiMode_Master;//主機
    spiConfig.speed = SpiSpeed_20MHz;//時鍾頻率
    spiConfig.subMode = SpiSubMode_0;//模式0
    spiConfig.bitOrder = SpiBitOrder_MSBFirst;//先傳輸高位

    SpiSend.addr=0;
    SpiSend.addrLen=0;
    SpiSend.cmd=0;
    SpiSend.cmdLen=0;
    SPIInit(SpiNum_HSPI,&spiConfig);//初始化SPI

 

 

其它頻率

 

 

 

 

 

typedef enum
{
    SpiSpeed_0_5MHz     = 160,
    SpiSpeed_1MHz       = 80,
    SpiSpeed_2MHz       = 40,
    SpiSpeed_5MHz       = 16,
    SpiSpeed_8MHz       = 10,
    SpiSpeed_10MHz      = 8,
    SpiSpeed_20MHz      = 4,
    SpiSpeed_40MHz      = 2,
    SpiSpeed_80MHz      = 1,
 
} SpiSpeed;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM