JiZzJiZZ国产免费A_国产午夜成人AV在线播放_亚洲欧美在线观看一区二区_91久久久久精品无嫩草影院_欧美高清一区二区三区_欧美日韩国产码高清_亚洲精品国产电影_亚洲AV无码专区亚洲AV桃
廣告招募

GPIO實(shí)現(xiàn)I2C從機(jī)的設(shè)計(jì)

2025年07月15日 08:48:27      來源:江蘇瑞易通電子科技有限公司 >> 進(jìn)入該公司展臺      閱讀量:8

分享:

在本階段的工作中,需要實(shí)現(xiàn)一個(gè)由GPIO模擬的I2C從機(jī)工程設(shè)計(jì),以前只使用GPIO模擬I2C設(shè)計(jì)過主機(jī),對于從機(jī)的設(shè)計(jì),還是。下面就講本次工作中從機(jī)設(shè)計(jì)思想做詳細(xì)記錄。

I2C的簡單總結(jié)

對于I2C信號,需要有START,STOP,ACK,NACK,以及接收DATA。接收DATA是在SCL的低電平可能發(fā)生跳變,START和STOP是在高電平跳變。當(dāng)SCL保持高電平的時(shí)候,SDA從H跳變到L,即為START;當(dāng)SCL保持高電平的時(shí)候,SDA從L跳變到H,即為STOP。

START信號: 
 
圖1

STOP信號 
 
圖2

ACK信號 
 
圖3

主機(jī)下發(fā)地址以及讀寫信號 

圖4

程序設(shè)計(jì)以及分析

//為所使用的硬件平臺的寄存器配置

#define WAIT_IIC_SCL_HIGH   while ( !GET_SCL_DAT )

#define WAIT_IIC_SCL_LOW    while ( GET_SCL_DAT )

#define WAIT_IIC_SDA_HIGH   while ( !GET_SDA_DAT )

#define WAIT_IIC_SDA_LOW    while ( GET_SDA_DAT )


#define IIC_WAIT_START      WAIT_IIC_SCL_HIGH;  WAIT_IIC_SDA_LOW    

#define IIC_WAIT_STOP       WAIT_IIC_SCL_LOW; SDA_IN; WAIT_IIC_SCL_HIGH; WAIT_IIC_SDA_HIGH 


#define IIC_SLAVE_SEND_LOW  WAIT_IIC_SCL_LOW; SDA_OUT; SET_SDA_LOW; WAIT_IIC_SCL_HIGH      

#define IIC_SLAVE_SEND_HIGH WAIT_IIC_SCL_LOW; SDA_OUT; SET_SDA_HIGH; WAIT_IIC_SCL_HIGH


#define IIC_SLAVE_SEND_ACK  IIC_SLAVE_SEND_LOW

#define IIC_SLAVE_SEND_NAK  IIC_SLAVE_SEND_HIGH


  • 初始化

void iic_init(void)  // 完成GPIO作為I2C的初始化

完成GPIO時(shí)鐘寄存機(jī)配置等功能。

  • 接收地址以及讀寫命令模塊

for(bitcount = 0; bitcount < 7;="" bitcount="">

{

    WAIT_IIC_SCL_LOW;                   

    WAIT_IIC_SCL_HIGH;

    iic_slv_addr <= 1;="">

    if(GET_SDA_DAT)

        iic_slv_addr |= 0x01;

    else

        iic_slv_addr |= 0x00;

}

iic_slv_addr <=>

// 讀取7位地址


WAIT_IIC_SCL_LOW;

WAIT_IIC_SCL_HIGH;

if(GET_SDA_DAT)

    iic_master_rw = 1;

else

    iic_master_rw = 0;

// 讀寫標(biāo)志位


if (iic_slv_addr == SLAVE_ADDR)

    IIC_SLAVE_SEND_ACK;    // 地址正確,從機(jī)發(fā)送ACK信號

從機(jī)接收接口定義以及說明


uint8_t L_i2c_rx( uint8_t xdata *pDestBuf, uint16_t *wRecLen);


pDestBuf:接收數(shù)據(jù)保存的目的地址 wRecLen:實(shí)際接收到的數(shù)據(jù)的長度


接收核心代碼分析



while(!recFinish)

{

    for(bitcount=0; bitcount<8;>

    {

        while(GET_SCL_DAT);

        SDA_IN;

        while(!GET_SCL_DAT);


    r0 = GET_SDA_DAT;

    while(GET_SCL_DAT)

    {

        r1 = GET_SDA_DAT;

        if((r0 == 0) && (r1 == 1))

        {

            recFinish = 1;

            return 0;

        }

    }


    rxbyte <=>

    if(r1)

        rxbyte |= 0x01;

    else

        rxbyte |= 0x00; 

}

buf[len] = rxbyte;

len++;

IIC_SLAVE_SEND_ACK;


在從機(jī)接收完地址以后,如果讀寫標(biāo)志位是寫(L),接下來,從機(jī)就會接收數(shù)據(jù),接收數(shù)據(jù)完成的標(biāo)志為接收到了STOP信號,就必須在從機(jī)發(fā)完ACK后的個(gè)SCL高電平時(shí)檢測是否有SDA從H跳轉(zhuǎn)到L,如果發(fā)生了,接收程序結(jié)束,如果沒有發(fā)生跳變,繼續(xù)接收數(shù)據(jù)的bit7,bit6,……bit0.

 
圖5

根據(jù)圖5,在時(shí)鐘節(jié)拍①中從機(jī)發(fā)送ACK信號以后,因?yàn)镚PIO的采樣頻率遠(yuǎn)大于I2C的始終頻率(設(shè)計(jì)中使用100K),所以需要在發(fā)送ACK后,要等待SCL變?yōu)長,在上面的代碼中體現(xiàn)在c點(diǎn),在時(shí)鐘節(jié)拍②中,SDA可能會發(fā)生變化。最重要的時(shí)需要在時(shí)鐘節(jié)拍③內(nèi)采樣SDA,判斷是否有變化(即從f到g中連續(xù)采樣SDA),如果發(fā)生了SDA從H到L,那么就認(rèn)為接收到了STOP信號,跳出接收數(shù)據(jù)的函數(shù);如果發(fā)生SDA從L到H,會被認(rèn)為是一個(gè)異常的信號(START信號,但不應(yīng)該在此時(shí)出現(xiàn),上段代碼中沒有處理此異常情況,請注意),同樣也需要跳出接收數(shù)據(jù)的函數(shù);如果SDA沒有發(fā)生任何變化,同時(shí)等待到SCL發(fā)生由H到L的變化,則意味著接收到了下一字節(jié)的bit7……

這樣最核心的問題就變?yōu)樵鯓优袛嘣跁r(shí)鐘節(jié)拍③中SDA是否發(fā)生了變化,并且發(fā)生了怎樣的變化。設(shè)計(jì)的思想為:在f點(diǎn)(上升沿)后取個(gè)SDA的采樣值r0,遍歷時(shí)鐘節(jié)拍③直到g點(diǎn)(下降沿),連續(xù)采樣SDA的下一個(gè)采樣值r1,當(dāng)在時(shí)鐘節(jié)拍③內(nèi),只要發(fā)生了r1 != r0的時(shí)候,馬上跳出接收數(shù)據(jù)程序。但如果r1 === r0,在檢測到h點(diǎn)的時(shí)候,才把r1賦值給接收字節(jié)rxbyte.

以上采樣能夠成功的一個(gè)前提是:SDA在SCL每一時(shí)鐘節(jié)拍的變化能夠被采樣到。

在此假設(shè)GPIO的時(shí)鐘為2MHz,SCL的傳輸速度為100KHz,時(shí)序關(guān)系如下圖所示:


圖6

上圖是比較理想的SCL的時(shí)鐘周期信號,在每半個(gè)SCL的時(shí)鐘周期中,有10個(gè)采樣點(diǎn),這樣確保了SCL上升沿后的個(gè)GPIO采樣到了r0=0,也能在后5個(gè)采樣點(diǎn)中采到了r1=1,在這種情況下,不會發(fā)生任何錯(cuò)誤。

但是,實(shí)際情況并非如此,在GPIO模擬I2C的SCL信號中,占空比并不是50%,如果此時(shí)SDA的變化在GPIO個(gè)采樣沿之前就發(fā)生了變化,那么就無法采樣到正確的電平變化信號。

所以,以上設(shè)計(jì)方法能夠成功的前提為:SDA并不會在緊靠著SCL的上升沿或者下降沿而變化,也就是說SDA的任何變化,都能被GPIO的時(shí)鐘采樣到。

  • 從機(jī)發(fā)送接口定義以及說明

uint8_t L_i2c_tx(const uint8_t xdata * pSendBuf, uint16_t wSendLen);


pSendBuf:發(fā)送數(shù)據(jù)緩存地址 wSendLen:發(fā)送數(shù)據(jù)的長度


發(fā)送核心代碼分析

for(bytecount = 0; bytecount < len;="" bytecount="">

{        

    txmask = 0x80;

    txbyte = buf[bytecount];

    for(bitcount = 0; bitcount < 8;="" bitcount="">

    {

        WAIT_IIC_SCL_LOW;

        SDA_OUT;

        if ( txbyte & txmask )

            SET_SDA_HIGH;   

        else    

            SET_SDA_LOW;  

        WAIT_IIC_SCL_HIGH;

        txmask = txmask >> 1;       

    }


    WAIT_IIC_SCL_LOW;                                               

    SDA_IN;

    WAIT_IIC_SCL_HIGH;

    if ( GET_SDA_DAT )  

        break;

}

return (bytecount);


for(bytecount = 0; bytecount < len;="" bytecount="">

{        

    txmask = 0x80;

    txbyte = buf[bytecount];

    for(bitcount = 0; bitcount < 8;="" bitcount="">

    {

        WAIT_IIC_SCL_LOW;

        SDA_OUT;

        if ( txbyte & txmask )

            SET_SDA_HIGH;   

        else    

            SET_SDA_LOW;  

        WAIT_IIC_SCL_HIGH;

        txmask = txmask >> 1;       

    }


    WAIT_IIC_SCL_LOW;                                               

    SDA_IN;

    WAIT_IIC_SCL_HIGH;

    if ( GET_SDA_DAT )  

        break;

}

return (bytecount);

 
流程圖

版權(quán)與免責(zé)聲明:
1.凡本網(wǎng)注明"來源:中美貿(mào)易網(wǎng)"的所有作品,版權(quán)均屬于中美貿(mào)易網(wǎng),轉(zhuǎn)載請必須注明中美貿(mào)易網(wǎng)。違反者本網(wǎng)將追究相關(guān)法律責(zé)任。
2.企業(yè)發(fā)布的公司新聞、技術(shù)文章、資料下載等內(nèi)容,如涉及侵權(quán)、違規(guī)遭投訴的,一律由發(fā)布企業(yè)自行承擔(dān)責(zé)任,本網(wǎng)有權(quán)刪除內(nèi)容并追溯責(zé)任。
3.本網(wǎng)轉(zhuǎn)載并注明自其它來源的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點(diǎn)或證實(shí)其內(nèi)容的真實(shí)性,不承擔(dān)此類作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個(gè)人從本網(wǎng)轉(zhuǎn)載時(shí),必須保留本網(wǎng)注明的作品來源,并自負(fù)版權(quán)等法律責(zé)任。 4.如涉及作品內(nèi)容、版權(quán)等問題,請?jiān)谧髌钒l(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系。

JiZzJiZZ国产免费A_国产午夜成人AV在线播放_亚洲欧美在线观看一区二区_91久久久久精品无嫩草影院_欧美高清一区二区三区_欧美日韩国产码高清_亚洲精品国产电影_亚洲AV无码专区亚洲AV桃