久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7111|回復: 10
打印 上一主題 下一主題
收起左側

關于STC8單片機模擬I2C的程序問題

[復制鏈接]
跳轉到指定樓層
樓主
ID:475845 發表于 2019-7-12 16:01 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
我是用的STC8A8K64S4A12這個單片機,我想的是通過模擬I2C來控制另一塊顯示板。在開始我硬件I2C,但是并沒有成功,而且好像這一款硬件I2C不怎么好用,我就想著用模擬的,但還是沒有成功,下面我把代碼貼上來,希望大佬能夠指點一下。

單片機源程序如下:
#include <intrins.h>
#include <STC8F.H>

//定義I2C總線
sbit SCL = P1^1;//時鐘線
sbit SDA = P1^0;//數據線
sbit LED = P2^7;

unsigned char KEY;

//函數聲明
void delay1();

void IICdelay();//短暫延時
void IICinit();//總線初始化
void IICstart();//產生起始信號
void IICstop();//產生停止信號
unsigned char SlaRes();//從設備應答
void MasRes();//主設備應答
void NoRes();//主設備不應答
void IICwrite(unsigned char iicdata);//寫一個字節
unsigned char IICread();//讀一個字節

void LED_OUT();
unsigned char KEY_V();

//I2C通信使用delay()函數
//一個_nop_()延時1us,總線要求延時大于4.7us
//單片機頻率執行周期不同時按實際需要修改
void IICdelay()
{
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
}

void delay1s()
{
    unsigned char i, j, k;

    _nop_();
    _nop_();
    i = 43;
    j = 6;
    k = 203;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}

//總線初始化
//將總線都拉高以釋放總線
void IICinit()
{
        SCL = 1;
        IICdelay();
        SDA = 1;
        IICdelay();
}

//啟動信號
//SCL在高電平期間,SDA由高電平向低電平的變化定義為啟動信號
void IICstart()
{
        SDA = 1;
        IICdelay();
        SCL = 1;
        IICdelay();
        SDA = 0;
        IICdelay();
          SCL = 0;
          IICdelay();
}

//停止信號
//SCL在高電平期間,SDA由低電平向高電平的變化定義為停止信號
void IICstop()
{
        SDA = 0;
        IICdelay();
        SCL = 1;
        IICdelay();
        SDA = 1;
        IICdelay();
}

//應答信號
//SCL在高電平期間,SDA被從設備拉為低電平表示應答
//其中(SDA == 1)&&(i<255)表示若在一段時間內沒有收到從器件的應答則主器件默認從器件已經收到數據而不再等待應答信號
unsigned char SlaRes()
{
        unsigned char i = 0;
        
        SCL = 1;
        IICdelay();
        while(SDA)
        {
                i++;
                if(i > 254)
                {
                        IICstop();
                        return 1;
                }
        }
        SCL = 0;
        IICdelay();
        
        return 0;
}

//由主設備發出應答
//從設備在發送完一字節后將SDA拉高(SDA被釋放),主設備將SDA拉低產生應答
void MasRes()
{
        SDA = 0;//直接將SDA拉低,再操縱SCL
        IICdelay();
        SCL = 1;
        IICdelay();
        SCL = 0;
        IICdelay();
}

//主設備不應答
void NoRes()
{
        SDA = 1;//SDA高電平為不應答
        IICdelay();
        SCL = 1;
        IICdelay();
        SCL = 0;
        IICdelay();
}

//寫入
//表示將temp左移一位,最高位將移入PSW寄存器的CY位中,然后將CY賦給SDA進而在SCL的控制下發送出去
//最后將SDA拉高,以等待從設備產生應答
void IICwrite(unsigned char iicdata)
{
        unsigned char i;
        for(i=0; i<8; i++)
        {
                iicdata = iicdata << 1;
                SCL = 0;
                IICdelay();
                SDA = CY;
                IICdelay();
                SCL = 1;
                IICdelay();
        }
        SCL = 0;
        IICdelay();
        SDA = 1;
        IICdelay();
}

//讀出
//串行接受一個字節時需將8位一位一位地接受,然后再組合成一個字節,
unsigned char IICread()
{
        unsigned char i, k;
        SCL = 0;
        IICdelay();
        SDA = 1;
        IICdelay();
        for(i=0; i<8; i++)
        {
                SCL = 1;
                IICdelay();
                k = (k<<1)|SDA;
                SCL = 0;
                IICdelay();
        }
        IICdelay();
        return k;
}



void LED_OUT()
{
    IICstart();                                   //發送起始命令
      IICwrite(0xa0);                             //發送設備地址+寫命令
    SlaRes();
      IICwrite(0x04);                             //發送存儲地址高字節
    SlaRes();
      IICwrite(0x00);                             //發送存儲地址低字節
    SlaRes();
      IICwrite(0x00);                             //寫測試數據1
    SlaRes();
      IICwrite(0x01);                             //寫
    SlaRes();
      IICstop();                                                                        //停止信號
}


unsigned char KEY_V()
{

    IICstart();                                   //發送起始命令
      IICwrite(0xa0);                             //發送設備地址+寫命令
    SlaRes();
      IICwrite(0x00);                             //發送存儲地址高字節
    SlaRes();
    IICstart();                                   //發送起始命令
      IICwrite(0x0F);                             //發送設備地址+讀命令
    SlaRes();
      KEY = IICread();                               //讀取數據
    NoRes();                                      //非應答信號
        IICstop();                                    //發送停止命令
    return KEY;
}


void main()
{
    IICinit();
   
   
   while(1)
     {
    KEY_V();
         {
            if(KEY != 0X00)
                {
                  LED_OUT();
                    LED=~LED;
                    delay1s();
                    delay1s();
                    delay1s();
                    delay1s();
                }
         }
     }
}

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

使用道具 舉報

沙發
ID:401564 發表于 2019-7-13 11:41 | 只看該作者
從機的應答信號不能用延時,而且,你延時的時間太短了
從機的應答信號應該是:先釋放SDA,然后再不斷的去檢測SDA,一直要等到SDA出現低電平才能視為應答信號
如果是怕死循環,可以用看門狗或者中斷或者是設定檢測次數之類,到時間就退出循環就可以了
回復

使用道具 舉報

板凳
ID:475845 發表于 2019-7-15 15:45 | 只看該作者
Y_G_G 發表于 2019-7-13 11:41
從機的應答信號不能用延時,而且,你延時的時間太短了
從機的應答信號應該是:先釋放SDA,然后再不斷的去檢測S ...

這個程序大體是沒有問題的吧,我把那個位置的改了下,但是還是沒有解決問題.因為之前沒有弄過這個,延時的話是看網上說的要4.7us,一個Nop()相當于1us,就用的這個延時,主程序里面自己是用的另外一個
回復

使用道具 舉報

地板
ID:475845 發表于 2019-7-15 15:49 | 只看該作者
本帖最后由 Ty78619120 于 2019-7-15 18:43 編輯
Y_G_G 發表于 2019-7-13 11:41
從機的應答信號不能用延時,而且,你延時的時間太短了
從機的應答信號應該是:先釋放SDA,然后再不斷的去檢測S ...

這個程序大體上應該沒有問題吧?我把你說的位置改了試了下,但是還是沒有解決問題,我自己在試一下。自己之前沒有弄過這個東西,剛玩單片機不久。看網上別說延時大于4.7us就行了,一個nop()相當于1us,自己主程序里面是用的另外一個延時。
回復

使用道具 舉報

5#
ID:155507 發表于 2019-7-15 20:43 | 只看該作者
我給你來個STC8單片機模擬 的I2C程序試試


  1. /****************************/
  2. void        I2C_Delay(void)        //for 1T  STC        delay
  3. {
  4.         uint16 j,i;   
  5.         for(j=0;j<2;j++)   
  6.         {   
  7.                 for(i=0;i<7;i++);   
  8.         }  
  9. }

  10. /****************************/
  11. void I2C_Start(void)               //start the I2C, SDA High-to-low when SCL is high
  12. {
  13.         SDA = 1;
  14.         I2C_Delay();
  15.         SCL = 1;
  16.         I2C_Delay();
  17.         SDA = 0;
  18.         I2C_Delay();
  19.         SCL = 0;
  20.         I2C_Delay();
  21. }               

  22. /****************************/
  23. void I2C_Stop(void)                                        //STOP the I2C, SDA Low-to-high when SCL is high
  24. {
  25.         SDA = 0;
  26.         I2C_Delay();
  27.         SCL = 1;
  28.         I2C_Delay();
  29.         SDA = 1;
  30.         I2C_Delay();
  31. }

  32. /****************************/
  33. void S_ACK(void)              //Send ACK (LOW)
  34. {
  35.         SDA = 0;
  36.         I2C_Delay();
  37.         SCL = 1;
  38.         I2C_Delay();
  39.         SCL = 0;
  40.         I2C_Delay();
  41. }

  42. /****************************/
  43. void S_NoACK(void)           //Send No ACK (High)
  44. {
  45.         SDA = 1;
  46.         I2C_Delay();
  47.         SCL = 1;
  48.         I2C_Delay();
  49.         SCL = 0;
  50.         I2C_Delay();
  51. }

  52. /****************************/
  53. void I2C_Check_ACK(void)         //Check ACK, If F0=0, then right, if F0=1, then error
  54. {
  55.         SDA = 1;
  56.         I2C_Delay();
  57.         SCL = 1;
  58.         I2C_Delay();
  59.         F0  = SDA;
  60.         SCL = 0;
  61.         I2C_Delay();
  62. }

  63. /****************************/
  64. void I2C_WriteAbyte(uint8 dat)                //write a byte to I2C
  65. {
  66.         uint8 i;
  67.         i = 8;
  68.         do
  69.         {
  70.                 if(dat & 0x80)        SDA = 1;
  71.                 else                        SDA        = 0;
  72.                 dat <<= 1;
  73.                 I2C_Delay();
  74.                 SCL = 1;
  75.                 I2C_Delay();
  76.                 SCL = 0;
  77.                 I2C_Delay();
  78.         }
  79.         while(--i);
  80. }

  81. /**************************************
  82. 功能描述:向指定地址寫數據
  83. 入口參數:uint8 addr, uint8 *p, uint8 number
  84. 返回值:無
  85. ***************************************/
  86. uint8 I2C_ReadAbyte(void)                        //read A byte from I2C
  87. {
  88.         uint8 i,dat;
  89.         i = 8;
  90.         SDA = 1;
  91.         do
  92.         {
  93.                 SCL = 1;
  94.                 I2C_Delay();
  95.                 dat <<= 1;
  96.                 if(SDA)                dat++;
  97.                 SCL  = 0;
  98.                 I2C_Delay();
  99.         }
  100.         while(--i);
  101.         return(dat);
  102. }

  103. /**************************************
  104. 功能描述:向指定地址寫數據
  105. 入口參數:uint8 addr, uint8 *p, uint8 number
  106. 返回值:無
  107. ***************************************/
  108. void WriteNbyte(uint8 addr, uint8 *p, uint8 number)                        /*        WordAddress,First Data Address,Byte lenth        */
  109.                                                                                                  //F0=0,right, F0=1,error
  110. {
  111.         I2C_Start();
  112.         I2C_WriteAbyte(SLAW);
  113.         I2C_Check_ACK();
  114.         if(!F0)
  115.         {
  116.                 I2C_WriteAbyte(addr);
  117.                 I2C_Check_ACK();
  118.                 if(!F0)
  119.                 {
  120.                         do
  121.                         {
  122.                                 I2C_WriteAbyte(*p);                p++;
  123.                                 I2C_Check_ACK();
  124.                                 if(F0)        break;
  125.                         }
  126.                         while(--number);
  127.                 }
  128.         }
  129.         I2C_Stop();
  130. }


  131. /**************************************
  132. 功能描述:向指定地址讀取數據
  133. 入口參數:uint8 addr, uint8 *p, uint8 number
  134. 返回值:無
  135. ***************************************/
  136. void ReadNbyte(uint8 addr, uint8 *p, uint8 number)                /*        WordAddress,First Data Address,Byte lenth        */
  137. {
  138.         I2C_Start();
  139.         I2C_WriteAbyte(SLAW);
  140.         I2C_Check_ACK();
  141.         if(!F0)
  142.         {
  143.                 I2C_WriteAbyte(addr);
  144.                 I2C_Check_ACK();
  145.                 if(!F0)
  146.                 {
  147.                         I2C_Start();
  148.                         I2C_WriteAbyte(SLAR);
  149.                         I2C_Check_ACK();
  150.                         if(!F0)
  151.                         {
  152.                                 do
  153.                                 {
  154.                                         *p = I2C_ReadAbyte();        p++;
  155.                                         if(number != 1)                S_ACK();        //send ACK
  156.                                 }
  157.                                 while(--number);
  158.                                 S_NoACK();                        //send no ACK
  159.                         }
  160.                 }
  161.         }
  162.         I2C_Stop();
  163. }



  164. /*********************************END FILE********************************************/       

復制代碼
回復

使用道具 舉報

6#
ID:401564 發表于 2019-7-16 08:18 | 只看該作者
Ty78619120 發表于 2019-7-15 15:49
這個程序大體上應該沒有問題吧?我把你說的位置改了試了下,但是還是沒有解決問題,我自己在試一下。自己 ...

C不會,只能看一個大概.
但IIC協議是知道的,IIC的時序很重要:主機的應答可以用延時,從機的應答最好是等待,一直等到從機自己產生應答信號為止.
STC的指令速度和傳統的8051是不同的,要快很多倍的,最快的是快12倍,所以,你那延時可能是1uS都沒有

在程序最初的調試階段,你可以暫時不要理會速度問題,先把所有的延時都用到100mS,把程序調試好了,再慢慢的去調試延時
回復

使用道具 舉報

7#
ID:475845 發表于 2019-7-16 11:28 | 只看該作者
Y_G_G 發表于 2019-7-16 08:18
C不會,只能看一個大概.
但IIC協議是知道的,IIC的時序很重要:主機的應答可以用延時,從機的應答最好是等待 ...

嗯嗯,好的,謝謝幫助,我試一下
回復

使用道具 舉報

8#
ID:475845 發表于 2019-7-16 11:29 | 只看該作者
angmall 發表于 2019-7-15 20:43
我給你來個STC8單片機模擬 的I2C程序試試

謝謝了,我用著試一下
回復

使用道具 舉報

9#
ID:371527 發表于 2019-7-21 11:52 | 只看該作者
STC8a8k比STC15的指令執行速度還要快,延時時間,不能照搬以前的一個Nop用1us的概念,最好示波器看一下,即便用ISP生成的延時軟件,也要對應相應的MCU STC ,最好是用Mosc相應公式做延時程序,再用示波器觀察延時是否正確。
回復

使用道具 舉報

10#
ID:307020 發表于 2019-7-23 12:25 | 只看該作者
論壇里有PCF8574 I2C 轉并口驅動LCD1602液晶顯示屏的例程,在左上側的“請輸入搜索內容”后邊輸入PCF8547就可以看到;且為模塊化很好。
回復

使用道具 舉報

11#
ID:975054 發表于 2021-12-7 19:49 | 只看該作者
還是用硬件I2C簡約一點吧,近期一直在研究
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲成人一二区 | 国产欧美精品一区二区三区 | 久久天天躁狠狠躁夜夜躁2014 | 成人精品在线观看 | 久久精品久久久久久 | 国产精品精品久久久 | 国产伦精品一区二区三区照片91 | 国产视频一区二区 | 天天色天天射天天干 | 黄色大片在线播放 | 日韩在线观看网站 | 午夜视频一区二区三区 | 天天久| www国产成人免费观看视频,深夜成人网 | 一区福利视频 | 久久69精品久久久久久国产越南 | 黄色毛片大全 | 日日日操 | 日韩久久精品 | 天天色官网 | 国内精品99 | 亚洲精品久久久9婷婷中文字幕 | 国产精品一区二区视频 | 午夜欧美a级理论片915影院 | 91性高湖久久久久久久久_久久99 | 久久人体视频 | 99爱视频| 伊人网综合 | 99爱视频 | 久久久久久久久99 | 国产精品不卡 | 91资源在线 | 亚洲成人播放器 | 国产成人精品福利 | 九九热免费视频在线观看 | 欧美日韩一区二区三区四区 | 天天拍天天色 | 国产欧美精品一区二区 | 懂色中文一区二区三区在线视频 | 欧美视频免费 | 99久9 |