程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 用I/O口模擬總線時序,總線時序

用I/O口模擬總線時序,總線時序

編輯:關於C語言

用I/O口模擬總線時序,總線時序


在做總線通信過程中,我們很少會用到這樣方法,一般在我們選擇MCU的時候都會帶有你所需要的通信接口。但是,對於一些簡單的通信應該用的場合,一般在一些傳感器的數據通信過程中,傳感器廠商會將通信協議做一些改變,這些通信協議也沒有一個標准的協議規定。以至於傳感器的兼容性很差,甚至有時候找不到能夠與其通信的MCU,這個時候有一種方法就是用I/O口來模擬通信總線(由於I/O速度的限制一般只適用於低速的通信總線)的時序。之前,用I2C通信做一個溫濕度測量的工程,本篇文章就以一個例子來看看如何用I/O口對總線時序進行模擬。

我們平時計算機常用的RS232/485工作在異步工作狀態時是有嚴格的數據時鐘限制,也就是我們所說的波特率,通信的兩個設備有相同的波特率才能正確的通信。對於同步通信一般沒有嚴格的時間限制,總線通過高低電平來分辨數據是“0”還是“1”,有兩個關鍵的時刻:上升沿,下降沿。它是用過上升沿和下降沿的時刻來讀寫數據的,也就是說這樣的話通信頻率不是固定的,因為通信的設備“數”的是上升沿和下降沿的數目,然後讀寫數據線上的數據。筆者做過實驗,將I2C通信的頻率降到了10Hz左右,這樣用示波器能夠很好的捕捉到每一個時鐘,通信的結果也是正確的。

好了,直接來看案例吧。

通常我們的I2C的通信時序應該如下圖所示,在時鐘線拉高的情況下,將數據線拉低就會產生一個啟動信號。但是傳感器SHT的啟動信號卻是一個數據線拉低後,時鐘線產生一個脈沖,而後再將數據線拉高,這樣做的好處是在一定程度上確保了總線正確的啟動,但是幾乎與之匹配的MCU。這個時候就需要通過I/O模擬的方式來與SHT11完成通信。

 

 

 

  1 #define IIC_SCL RC0     //I2C時鐘線
  2 #define IIC_SDA RC1     //I2C數據線
  3 #define IIC_SCL_DIR TRISC0   //I2C時鐘線傳輸方向
  4 #define IIC_SDA_DIR TRISC1   //I2C數據線傳輸方向
  5 #define PORT_INPUT 1
  6 #define PORT_OUTPUT 0
  7 
  8 #define IIC_SCL_HIGH() IIC_SCL_DIR = PORT_INPUT           //時鐘線拉高
  9 #define IIC_SCL_LOW()  IIC_SCL_DIR = PORT_OUTPUT;IIC_SCL=0//時鐘線拉低
 10 #define IIC_SDA_HIGH() IIC_SDA_DIR = PORT_INPUT           //數據線拉高
 11 #define IIC_SDA_LOW()  IIC_SDA_DIR = PORT_OUTPUT;IIC_SDA=0//數據線拉低
 12 
 13 
 14 /***************
 15 *SHT11啟動時序
 16 ***************/
 17 void SHT_START(void)
 18 {
 19 IIC_SCL_HIGH();
 20 IIC_SDA_HIGH();
 21 delay_us(5);
 22 IIC_SDA_LOW();
 23 delay_us(5);
 24 IIC_SCL_LOW();
 25 delay_us(5);
 26 IIC_SCL_HIGH();
 27 delay_us(5);
 28 IIC_SDA_HIGH();
 29 delay_us(5);
 30 IIC_SCL_LOW();
 31 }
 32 /***************
 33 *SHT11發送數據時序
 34 ***************/
 35 void SHT_SEND(uchar data)
 36 {uchar i,data1;
 37 for(i=0;i<8;i++)
 38 {
 39 data1=data<<i;
 40 if(!(data1&0x80))
 41 IIC_SDA_LOW();
 42 if(data1&0x80)
 43 IIC_SDA_HIGH();
 44 IIC_SCL_LOW();        //寫完1位數據將時鐘線拉低,等待發送
 45 delay_us(5);
 46 IIC_SCL_HIGH();        //時鐘線上升沿,發送1位數據
 47 delay_us(5);           //等待1位數據發送完成
 48 }
 49 IIC_SCL_LOW();
 50 IIC_SDA_HIGH();        //8位數據發送完成,數據線拉高,等待SLAVE器件響應
 51 delay_us(5);
 52 IIC_SCL_HIGH();        //時鐘線拉高,產生上升沿讀取數據線是否SLAVE器件有響應
 53 //while(IIC_SDA==1);
 54 delay_us(5);
 55 IIC_SCL_LOW();
 56 IIC_SDA_HIGH();        //數據線拉高,時鐘線拉低,等待轉換完成
 57 }
 58 /***************
 59 *SHT11接收數據時序
 60 ***************/
 61 uint SHT_REC(void)
 62 {
 63 uint i;
 64 uint REC1=0,REC0=0,REC=0;
 65 for(i=0;i<8;i++)
 66 {
 67 IIC_SCL_HIGH();        //轉換完成,SLAVE器件將數據線拉低,時鐘線產生上升沿讀取高8位數據
 68 REC1=(REC1<<1)+IIC_SDA;
 69 delay_us(5);
 70 IIC_SCL_LOW();                //將時鐘線拉低,等待下一個上升沿的到來
 71 delay_us(5);
 72 }
 73 SHT_ASK();                 //高8位數據接收完畢,發送應答信號
 74 for(i=0;i<8;i++)
 75 {
 76 IIC_SCL_HIGH();        //轉換完成,SLAVE器件將數據線拉低,時鐘線產生上升沿讀取低8位數據
 77 REC0=(REC0<<1)+IIC_SDA;
 78 delay_us(5);
 79 IIC_SCL_LOW();
 80 delay_us(5);
 81 }
 82 SHT_STOP();        //低8位數據接收完畢,結束        
 83 REC=(REC1<<8)+REC0;
 84 return REC;
 85 }
 86 /***************
 87 *SHT11應答時序
 88 ***************/
 89 void SHT_ASK(void)
 90 {
 91 IIC_SCL_LOW();
 92 IIC_SDA_LOW();        //數據線拉低
 93 delay_us(5);
 94 IIC_SCL_HIGH();        //時鐘線拉高才生應答信號
 95 delay_us(5);
 96 IIC_SDA_HIGH();
 97 IIC_SCL_LOW();
 98 delay_us(5);
 99 }
100 /***************
101 *SHT11停止時序
102 ***************/
103 void SHT_STOP(void)
104 {
105 IIC_SDA_HIGH();
106 IIC_SCL_LOW();
107 delay_us(5);
108 IIC_SCL_HIGH();
109 delay_us(5);
110 IIC_SDA_HIGH();
111 IIC_SCL_LOW();
112 }

 


怎使用兩個I/O口來模擬串口時序進行通訊

要設計好 協議 接收方 正常接收 後要反饋 給 發送方,這樣 發送方 才能發送新的數據 建議你 看看 清華出版的 Visual_Basic與_RS-232_串行通信控制 一
 

I2C總線是不是任意兩個I/O口都可以做SCL與SDL,不是像SPI一樣必須單片機支持才可以? 怎理解?

對應主控方的單片機來說,SDL需要支持輸出和輸入雙向或半雙向功能。spi也可以用軟件和普通IO口模擬。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved