新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 用I/O口模擬總線時序

        用I/O口模擬總線時序

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

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

        本文引用地址:http://www.104case.com/article/201611/315354.htm

        好了,直接來看案例吧。

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

        #define IIC_SCL RC0 //I2C時鐘線

        #define IIC_SDA RC1 //I2C數據線

        #define IIC_SCL_DIR TRISC0 //I2C時鐘線傳輸方向

        #define IIC_SDA_DIR TRISC1 //I2C數據線傳輸方向

        #define PORT_INPUT 1

        #define PORT_OUTPUT 0

        #define IIC_SCL_HIGH() IIC_SCL_DIR = PORT_INPUT //時鐘線拉高

        #define IIC_SCL_LOW() IIC_SCL_DIR = PORT_OUTPUT;IIC_SCL=0//時鐘線拉低

        #define IIC_SDA_HIGH() IIC_SDA_DIR = PORT_INPUT //數據線拉高

        #define IIC_SDA_LOW() IIC_SDA_DIR = PORT_OUTPUT;IIC_SDA=0//數據線拉低

        /***************

        *SHT11啟動時序

        ***************/

        void SHT_START(void)

        {

        IIC_SCL_HIGH();

        IIC_SDA_HIGH();

        delay_us(5);

        IIC_SDA_LOW();

        delay_us(5);

        IIC_SCL_LOW();

        delay_us(5);

        IIC_SCL_HIGH();

        delay_us(5);

        IIC_SDA_HIGH();

        delay_us(5);

        IIC_SCL_LOW();

        }

        /***************

        *SHT11發送數據時序

        ***************/

        void SHT_SEND(uchar data)

        {uchar i,data1;

        for(i=0;i<8;i++)

        {

        data1=data<

        if(!(data1&0x80))

        IIC_SDA_LOW();

        if(data1&0x80)

        IIC_SDA_HIGH();

        IIC_SCL_LOW();//寫完1位數據將時鐘線拉低,等待發送

        delay_us(5);

        IIC_SCL_HIGH();//時鐘線上升沿,發送1位數據

        delay_us(5); //等待1位數據發送完成

        }

        IIC_SCL_LOW();

        IIC_SDA_HIGH();//8位數據發送完成,數據線拉高,等待SLAVE器件響應

        delay_us(5);

        IIC_SCL_HIGH();//時鐘線拉高,產生上升沿讀取數據線是否SLAVE器件有響應

        //while(IIC_SDA==1);

        delay_us(5);

        IIC_SCL_LOW();

        IIC_SDA_HIGH();//數據線拉高,時鐘線拉低,等待轉換完成

        }

        /***************

        *SHT11接收數據時序

        ***************/

        uint SHT_REC(void)

        {

        uint i;

        uint REC1=0,REC0=0,REC=0;

        for(i=0;i<8;i++)

        {

        IIC_SCL_HIGH();//轉換完成,SLAVE器件將數據線拉低,時鐘線產生上升沿讀取高8位數據

        REC1=(REC1<<1)+IIC_SDA;

        delay_us(5);

        IIC_SCL_LOW(); //將時鐘線拉低,等待下一個上升沿的到來

        delay_us(5);

        }

        SHT_ASK(); //高8位數據接收完畢,發送應答信號

        for(i=0;i<8;i++)

        {

        IIC_SCL_HIGH();//轉換完成,SLAVE器件將數據線拉低,時鐘線產生上升沿讀取低8位數據

        REC0=(REC0<<1)+IIC_SDA;

        delay_us(5);

        IIC_SCL_LOW();

        delay_us(5);

        }

        SHT_STOP();//低8位數據接收完畢,結束

        REC=(REC1<<8)+REC0;

        return REC;

        }

        /***************

        *SHT11應答時序

        ***************/

        void SHT_ASK(void)

        {

        IIC_SCL_LOW();

        IIC_SDA_LOW();//數據線拉低

        delay_us(5);

        IIC_SCL_HIGH();//時鐘線拉高才生應答信號

        delay_us(5);

        IIC_SDA_HIGH();

        IIC_SCL_LOW();

        delay_us(5);

        }

        /***************

        *SHT11停止時序

        ***************/

        void SHT_STOP(void)

        {

        IIC_SDA_HIGH();

        IIC_SCL_LOW();

        delay_us(5);

        IIC_SCL_HIGH();

        delay_us(5);

        IIC_SDA_HIGH();

        IIC_SCL_LOW();

        }



        關鍵詞: IO口模擬總線時

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 榆中县| 思南县| 平乡县| 新竹市| 南木林县| 万州区| 阳高县| 江口县| 大庆市| 石渠县| 勃利县| 泰宁县| 西贡区| 衡水市| 东阳市| 宜阳县| 双峰县| 岳阳市| 百色市| 万盛区| 信丰县| 临泉县| 五寨县| 奎屯市| 平遥县| 通海县| 凤山市| 平远县| 晋江市| 鄂托克前旗| 北宁市| 葵青区| 荥经县| 正镶白旗| 扎鲁特旗| 大邑县| 新平| 乳山市| 万盛区| 阿图什市| 江都市|