標(biāo)題: 利用C51單片機(jī)模擬SPI進(jìn)行雙機(jī)通信 [打印本頁(yè)]

作者: Benjia    時(shí)間: 2019-3-19 21:32
標(biāo)題: 利用C51單片機(jī)模擬SPI進(jìn)行雙機(jī)通信
1.1SPI協(xié)議簡(jiǎn)述
      SPI,是英語(yǔ)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):


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



CS: 其中CS是控制芯片是否被選中的,也就是說(shuō)只有片選信號(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: 通訊是通過(guò)數(shù)據(jù)交換完成的,這里先要知道SPI是串行通訊協(xié)議,也就是說(shuō)數(shù)據(jù)是一位一位的傳輸?shù)。SDO為主機(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é)議可以在八位沒(méi)有發(fā)出送完的情況下停止發(fā)送。


  這里我跑了下示波器。



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

2.1軟件模擬       我使用的單片機(jī)為STC89C52,內(nèi)部沒(méi)有SPI的資源,因此需要自己進(jìn)行軟件模擬。
  利用串口中斷,首先利用電腦A得串口助手發(fā)送的數(shù)據(jù)存入SBUF,再將SBUF的值通過(guò)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.         ;//空語(yǔ)句        
  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;//開(kāi)啟總中斷
  70.         ES = 1;//打開(kāi)串口中斷
  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é)

作者: 從前有只喵嗚    時(shí)間: 2019-11-26 22:51
看看~~~~~~~
作者: Lprong    時(shí)間: 2019-12-3 10:59
不錯(cuò)不錯(cuò)
作者: a461624201    時(shí)間: 2020-7-18 03:33
這里有個(gè)問(wèn)題,如果2種單片機(jī)速度不一樣,那樣模擬的結(jié)果無(wú)法通信。
作者: a461624201    時(shí)間: 2020-7-21 01:28
stc89c52做模擬SPI接收,STC15F104做模擬SPI發(fā)射,按照樓主源碼是收不到的,STC15F104必須增加到8us才可以成功。


作者: test20220315    時(shí)間: 2022-3-16 11:37
a461624201 發(fā)表于 2020-7-18 03:33
這里有個(gè)問(wèn)題,如果2種單片機(jī)速度不一樣,那樣模擬的結(jié)果無(wú)法通信。

請(qǐng)問(wèn)有解決辦法嗎




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1