找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 10191|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

利用C51單片機(jī)模擬SPI進(jìn)行雙機(jī)通信

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
1.1SPI協(xié)議簡(jiǎn)述
      SPI,是英語Serial Peripheral interface的縮寫,顧名思義就是串行外圍設(shè)備接口。由Motorola首創(chuàng)。SPI接口主要應(yīng)用在 EEPROM,F(xiàn)LASH,實(shí)時(shí)時(shí)鐘,AD轉(zhuǎn)換器,還有數(shù)字信號(hào)處理器和數(shù)字信號(hào)解碼器之間。SPI,是一種高速的,全雙工,同步的通信總線。
  優(yōu)缺點(diǎn):
  • 1.協(xié)議簡(jiǎn)單,相對(duì)數(shù)據(jù)速率高。
  • 2.占用的Pin口較多
  • 3.沒有指定的流控制,沒有應(yīng)答機(jī)制確認(rèn)是否接收到數(shù)據(jù)。


      SPI的通信原理很簡(jiǎn)單,它以主從方式工作,這種模式通常有一個(gè)主設(shè)備和一個(gè)或多個(gè)從設(shè)備,需要至少4根線,事實(shí)上3根也可以(單向傳輸時(shí))。也是所有基于SPI的設(shè)備共有的,它們是SDI,SDO,SCK,CS。

  • SDO – 主設(shè)備數(shù)據(jù)輸出,從設(shè)備數(shù)據(jù)輸入
  • SDI – 主設(shè)備數(shù)據(jù)輸入,從設(shè)備數(shù)據(jù)輸出
  • SCK – 時(shí)鐘信號(hào),由主設(shè)備產(chǎn)生
  • CS – 從設(shè)備使能信號(hào),由主設(shè)備控制


CS: 其中CS是控制芯片是否被選中的,也就是說只有片選信號(hào)為預(yù)先規(guī)定的使能信號(hào)時(shí)(高電位或低電位),對(duì)此芯片的操作才有效,這就允許在同一總線上連接多個(gè)SPI設(shè)備成為可能。

SCK:SCK為時(shí)鐘信號(hào)線,主要控制時(shí)序。相當(dāng)于整個(gè)SPI協(xié)議是以SCK為準(zhǔn)進(jìn)行的。因此SCK的控制在每次發(fā)送中只能在主機(jī)的控制下進(jìn)行,從機(jī)不可控制。

SDI/SDO: 通訊是通過數(shù)據(jù)交換完成的,這里先要知道SPI是串行通訊協(xié)議,也就是說數(shù)據(jù)是一位一位的傳輸?shù)摹DO為主機(jī)發(fā)送,從機(jī)接收;SDI為主機(jī)接受,從機(jī)發(fā)送。

參考網(wǎng)站(請(qǐng)自行替換.):dlnware點(diǎn)com/theory/SPI-Bus

1.2SPI的四種模式

     這四種模式分別為:

模式                   CPOL&CPHA
MODE0          CPOL=0;CPHA=0
MODE1          CPOL=0;CPHA=1
MODE2          CPOL=1;CPHA=0
MODE3          CPOL=1;CPHA=1

參考網(wǎng)站(請(qǐng)自行替換.)dlnware點(diǎn)com/theory/SPI-Transfer-Modes

       在這四種模式中,我們常用MODE0和MODE2。因?yàn)樗阌诓僮。我便是使用的MODE2模式。這四種模式的區(qū)別在參考網(wǎng)站中有詳細(xì)的描述,這里便不再贅述。

  在MODE2模式下。時(shí)鐘在空閑時(shí)始終置1,每產(chǎn)生一次下降沿便會(huì)發(fā)送1 bit 數(shù)據(jù)。大家可能已經(jīng)想到,SPI協(xié)議可以在八位沒有發(fā)出送完的情況下停止發(fā)送。


  這里我跑了下示波器。



        從圖中清晰可見8個(gè)下降沿,時(shí)鐘在空閑時(shí)始終置1。
  
  其余的三個(gè)模式以此類推。

2.1軟件模擬       我使用的單片機(jī)為STC89C52,內(nèi)部沒有SPI的資源,因此需要自己進(jìn)行軟件模擬。
  利用串口中斷,首先利用電腦A得串口助手發(fā)送的數(shù)據(jù)存入SBUF,再將SBUF的值通過SPI的SDO發(fā)送給從機(jī)的SDI接收,并存入從機(jī)的SBUF,顯示在電腦B的串口助手上。
  目的:電腦A發(fā)送數(shù)據(jù),如:AB,電腦B可接收到AB。

  如圖:


     PS:在此項(xiàng)目中CS(片選)可以不用。
2.2代碼
  1. # include <reg52.h>//頭文件
  2. # include <intrins.h>//頭文件

  3. # define uchar unsigned char
  4. # define uint unsigned int

  5. sbit SCK = P1^0;//位定義時(shí)鐘
  6. //sbit CS = P1^1;//位定義片選(使能)  此項(xiàng)目可以不使用
  7. sbit SDI = P1^2;//位定義Input
  8. sbit SDO = P1^3;//位定義Output

  9. /*-----函數(shù)聲明-----*/
  10. void delay5us();
  11. void SpiSend(uchar dat1);
  12. uchar SpiReceive();
  13. void UARTInit();

  14. /*-----主函數(shù)-----*/
  15. void main()
  16. {        
  17.         UARTInit();
  18.          while(1)
  19.     {
  20.                 SBUF = SpiReceive();// 循環(huán)接收數(shù)據(jù)
  21.     }
  22.         ;//空語句        
  23. }

  24. /*-----5微秒延時(shí)函數(shù)-----*/
  25. void delay5us()
  26. {
  27.         _nop_();
  28. }

  29. /*-----CPHA=0;CPOL=1 模式2-----*/
  30. /*-----SPI發(fā)送函數(shù)-----*/
  31. /*-----上升沿發(fā)送-----*/
  32. void SpiSend(uchar dat1)
  33. {
  34.         uchar i;
  35.         for (i=0; i<8; ++i)//8bit,一位一位寫
  36.         {
  37.                 SCK = 0;
  38.                 if (dat1 & 0x80)//判斷當(dāng)前最高位為1還是0
  39.                 {
  40.                         SDO = 1;               
  41.                 }
  42.                 else
  43.                 {
  44.                         SDO = 0;
  45.                 }
  46.                 SCK = 1;//上升沿發(fā)送數(shù)據(jù)
  47.                 dat1 <<= 1;
  48.                 delay5us();               
  49.         }
  50. }

  51. /*-----SPI接收函數(shù)-----*/
  52. /*-----下降沿接收-----*/
  53. uchar SpiReceive()
  54. {
  55.         uchar i, dat0;
  56.         dat0 = 0x00;//dat0初始化
  57.         for (i=0; i<8; ++i)//8bit,一位一位讀
  58.         {
  59.                 dat0<<=1;
  60.         while(SCK == 1);   
  61.         while(SCK == 0);//下降沿讀取數(shù)據(jù)      
  62.         dat0 |= SDI;         
  63.         }
  64.         return (dat0);//收到數(shù)據(jù)(返回值)dat0
  65. }

  66. /*-----串口(中斷)初始化-----*/
  67. void UARTInit()
  68. {
  69.         EA = 1;//開啟總中斷
  70.         ES = 1;//打開串口中斷
  71.         SM0 = 0;SM1 = 1;//串口工作方式1,8位UART波特率可變
  72.         REN = 1;//串口允許接收
  73.         TR1 = 1;//啟動(dòng)定時(shí)器1
  74.         TMOD |= 0X20;//定時(shí)器1,工作模式2 8位自動(dòng)重裝
  75.         TH1 =0XFD;
  76.         TL1 =0XFD;//設(shè)置波特率9600
  77. }

  78. /*-----串口中斷服務(wù)函數(shù)-----*/
  79. void UART() interrupt 4
  80. {
  81.         if (RI)//判斷是否接收完成
  82.         {
  83.                 RI = 0;//軟件清零
  84.                 SpiSend(SBUF);// 轉(zhuǎn)發(fā)接收到的數(shù)據(jù)
  85.         }
  86.         if (TI)//判斷是否發(fā)送完成
  87.         {
  88.                 TI = 0;//軟件清零
  89.         }               
  90. }
復(fù)制代碼

      PS:SDI和SDO需交叉連接。

3.總結(jié)
  • 在發(fā)送數(shù)據(jù)時(shí),時(shí)鐘僅由發(fā)送端(主機(jī))控制;
  • SPI四種模式,只需將主從機(jī)同步一種模式即可;
  • SCK,SDI,SDO,CS四個(gè)引腳由自己定義即可。

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏9 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

來自 2#
ID:67274 發(fā)表于 2020-7-21 01:28 | 只看該作者
stc89c52做模擬SPI接收,STC15F104做模擬SPI發(fā)射,按照樓主源碼是收不到的,STC15F104必須增加到8us才可以成功。

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

板凳
ID:620021 發(fā)表于 2019-11-26 22:51 | 只看該作者
看看~~~~~~~
回復(fù)

使用道具 舉報(bào)

地板
ID:648072 發(fā)表于 2019-12-3 10:59 | 只看該作者
不錯(cuò)不錯(cuò)
回復(fù)

使用道具 舉報(bào)

5#
ID:67274 發(fā)表于 2020-7-18 03:33 | 只看該作者
這里有個(gè)問題,如果2種單片機(jī)速度不一樣,那樣模擬的結(jié)果無法通信。
回復(fù)

使用道具 舉報(bào)

6#
ID:1010785 發(fā)表于 2022-3-16 11:37 | 只看該作者
a461624201 發(fā)表于 2020-7-18 03:33
這里有個(gè)問題,如果2種單片機(jī)速度不一樣,那樣模擬的結(jié)果無法通信。

請(qǐng)問有解決辦法嗎
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表