三,ESP8266 SPI(基於Lua腳本語言)


https://www.cnblogs.com/yangfengwu/p/7520260.html

 

重點是說SPI通信協議,,,,

不要害怕協議因為協議是人規定的,,剛好我也是人......規定的協議既然能成為規范讓所有人所接受,那么必然有它的優勢和優點,必然值得學習,,

害怕協議的人是因為當初碰到了不懂的老師,他只會告訴你這很難............其實是他不會........

CS      :   Chip Selection    片選引腳,多個設備時可以用這個引腳選擇和哪個設備通信

MOSI  :   Master Out   Slave In   主機輸出數據引腳,,,,從機接收數據引腳

MISO :   Master In  Slave Out     主機接收數據引腳....從機輸出數據引腳

CLK  :    時鍾

還有兩個參數----假設有的單片機自帶硬件SPI,一定會提供設置下面兩個參數,,,當然有的支持SPI通信的芯片也可能涉及這兩個參數

CPOL    :表示時鍾信號(CLK引腳)在空閑時是高電平還是低電平

CPHA    :表示數據在時鍾信號(CLK)的第幾個沿開始數據傳輸

現在假如說

CPOL   = 0  ;//時鍾信號(CLK引腳)在空閑時是低電平

CPHA   = 0;//數據在時鍾信號(CLK)的第1個沿開始數據傳輸

 

通信的時候先傳輸高位

假如說  主機發給從機   10101010       從機發給主機    01010101

再假如 主機接收數據存到  MasterData 里面

            從機接收數據存到  SlaveData 里面

 

第一個上升沿  主機的10101010 最高位是 1 所以主機會讓MOSI引腳輸出高電平

                        從機的01010101最高位是 0  所以從機會讓MISO引腳為低電平

 

第一個下降沿  主機接收MISO引腳的數據,因為是低電平所以 MasterData= 0000 0000;

                       從機接收MOSI引腳的數據,因為是高電平所以從機SlaveData = 0000 0001;

 

 

第二個上升沿  主機左移一位  0101010X 最高位是 0 所以主機會讓MOSI引腳輸出低電平

                        從機左移一位 1010101X 最高位是 1  所以從機會讓MISO引腳為高電平

 

 

第二個下降沿  主機接收MISO引腳的數據,因為是高電平所以 MasterData= 0000 0001;

                       從機接收MOSI引腳的數據,因為是低電平所以從機SlaveData = 0000 0010;

 

 就這樣8個上升和8個下降沿之后

                        MasterData  = 01010101

                              SlaveData    =  10101010

 

 

 

現在假如說

CPOL   = 0  ;//時鍾信號(CLK引腳)在空閑時是低電平

CPHA   = 1;//數據在時鍾信號(CLK)的第2個沿開始數據傳輸

 

第一個下降沿  主機的10101010 最高位是 1 所以主機會讓MOSI引腳輸出高電平

                        從機的01010101最高位是 0  所以從機會讓MISO引腳為低電平

 

第一個上升沿  (注意是標號為1的那個,,,實際上是第二個上升沿)

                       主機接收MISO引腳的數據,因為是低電平所以 MasterData= 0000 0000;

                       從機接收MOSI引腳的數據,因為是高電平所以從機SlaveData = 0000 0001;

 

 

 

第二個下降沿  主機左移一位  0101010X 最高位是 0 所以主機會讓MOSI引腳輸出低電平

                        從機左移一位 1010101X 最高位是 1  所以從機會讓MISO引腳為高電平

 

第二個上升沿  主機接收MISO引腳的數據,因為是高電平所以 MasterData= 0000 0001;

                       從機接收MOSI引腳的數據,因為是低電平所以從機SlaveData = 0000 0010;

 

 第八個下降沿  主機把最后一位0放在了 MOSI引腳輸出低電平  

                               從機把最后一位1放在了 MISO引腳輸出高電平  

 

其實現在我也有疑惑,,,這樣就完了嗎??????只把數據放在引腳上就行了嗎????然后內部硬件就自動接收了嗎????

看一下摩托羅拉的數據手冊

難道最后一位會自動的接收?????搞不懂咧咧.....改天自己測試一下,,,讓主機工作在

CPOL   = 0  ;//時鍾信號(CLK引腳)在空閑時是低電平

CPHA   = 1;//數據在時鍾信號(CLK)的第2個沿開始數據傳輸

然后讓主機發一個字節的數據看看CLK怎樣變化的..............然后再嘗試手寫從機接收....然后知道結果了再來修改這個地方....

其余的兩種就不說了

其實說白了就是

CPOL控制在空閑狀態下CLK是高電平還是低電平

CPHA控制數據是在第一個沿就開始傳輸還是在第二個沿

其實呢!!寫程序最終還是要看芯片的資料,,,,,

現在看一下ESP8266的SPI

 

 

 

spi.setup(1, spi.MASTER, spi.CPOL_HIGH, spi.CPHA_HIGH, 8, 8)

用SPI1,主機模式,,空閑狀態下Clk為高電平,,第二個沿開始數據傳輸,8位數據,8分頻(10Mhz),默認半雙工

發送數據呢就簡單了

比如向從機發送0xaa,0x55,0x02,0x01

 

spi.send(1,0xaa,0x55,0x02,0x01)

接收數據呢還另有個函數
假設需要接收4個數據

 

ReadData = spi.recv(1,4,0xaa)

其實就是讓CLK產生32個脈沖信號,每8個代表一個字節的數據,,后面的0xaa哈,是在產生脈沖信號的時候MOSI引腳發送的數據,,如果不寫

默認發0xFF

 

對了接收到的數據都是以字符串的形式保存在變量里面,,可能會問我怎么自己解析數據呢

假如說判斷是不是接收到0xaa 和0x55

aa = spi.recv(1,2,0xaa)

if   aa:byte(1)==0xaa  and  aa:byte(2)==0x55  then

    自己的執行函數

end

大家肯定會說你咋知道要這樣寫

因為有API文檔

 

 還有一點,,我一開始看到過別人這樣做過,,所以呢我就知道可以這樣用....知識這東西一定要活學活用

http://blog.csdn.net/silno/article/details/72866623?locationNum=10&fps=1

 

 最后說一下和STM32進行SPI通信的一些注意,,,當然是把stm32配置成從機模式,,然后呢其余的設置一定要一樣

列如我配置的

void Spi2SlaveInit(void)
{
  SPI_InitTypeDef   SPI_InitStructure;
  GPIO_InitTypeDef  GPIO_InitStructure;

    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,  ENABLE );//SPI2時鍾使能       
         
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//CS
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    
    //GPIO_ResetBits(GPIOB,GPIO_Pin_12);  //PB13/14/15上拉
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;        
    GPIO_Init(GPIOB,&GPIO_InitStructure);
  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 
    GPIO_Init(GPIOB,&GPIO_InitStructure);    
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
    GPIO_Init(GPIOB,&GPIO_InitStructure);    
  
    GPIO_ResetBits(GPIOB,GPIO_Pin_14);  //PB13/14/15上拉
  
    GPIO_ResetBits(GPIOB,GPIO_Pin_15);  //PB13/14/15上拉
    

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
//     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;  //如果這里使用硬件模式,從機低電平
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI2, &SPI_InitStructure); 
    
    SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE);
    
    SPI_Cmd(SPI2 , ENABLE);
}

 

要注意

CS引腳在模塊剛啟動的時候一定是低電平............

再說一點,我的32程序用的中斷接收的SPI的數據,然后在中斷里面准備發送的數據,,大家這樣想

主機的數據發過來一個字節數據之后才進的中斷,,所以如果想在中斷里面發送數據,,應該在進中斷之前准備好數據的第一個字節

假設主機需要讀四個字節就會進四次中斷

我從機發給主機的數據是0xaa 0x55 0x01 0x02

char table[4] = {0xaa, 0x55, 0x01, 0x02}

在主機發送數據之前

我需要   SPI2->DR = table;

              Spi2SendBuff = table+1;

void SPI2_IRQHandler(void)  
{  
  if(SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) == SET)  
  {    
        SPI2->DR = *Spi2SendBuff;
        Spi2ReadBuff[Spi2ReadCnt] = SPI2->DR;
        
        Spi2ReadCnt ++;    
        Spi2SendBuff ++;
  }  
} 

這樣的話來第一個中斷的時候我的第一個數據0xaa也發向了主機,然后又准備了第二個數據,,,,,,,四次中斷就會把數據發給了主機,,注意指針溢出亂指了一下

這篇文章呢主要是會用ESP8266的SPI就行哈......

https://www.cnblogs.com/yangfengwu/p/7524326.html
 


免責聲明!

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



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