1. 程式人生 > >51單片機基於I2C總線的秒表模擬應用

51單片機基於I2C總線的秒表模擬應用

ons 解決 char s oid 保存數據 con 標誌位 周期 顯示

————————————————————————————————————————————

參考地址:

http://blog.csdn.net/junyeer/article/details/46480863

http://blog.csdn.net/bob_fly1984/article/details/22690381

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

硬件結構:

  • SDA數據線
  • SCL時間線
  • 上拉電阻

    p.s. 當總線空閑狀態時,兩根線被上拉電阻拉高,保持高電平。連接總線上的任一器件輸出的低電平都將使總線的信號變低

技術分享

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

總線特征:

  • I2C總線上的每一個設備都可以作為主設備或從設備
  • 每個設備會對應一個唯一的地址,主從設備之間通過地址來確定與哪個器件通信

    p.s. 地址分為7位或10位,此處只介紹7

  • 通常情況下,把CPU帶有I2C總線接口的模塊作為主設備,其他掛在總線上的作為從設備
  • 主從設備之間以字節為單位進行雙向數據傳輸

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

工作方式:

  • 主從工作方式:主器件啟動數據的發送,產生時鐘信號,發出停止信號

    p.s. 是沒有I2C總線硬件接口的單片機采用軟件模擬

    I2C總線常用的工作方式

  • 多主工作方式:需要總線競爭或仲裁

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

通信時序(主從工作方式):

  • 空閑狀態:
    • SCL和SDA保持高電平狀態
  • 忙狀態:

    p.s. SDA線必須在SCL時鐘的高電平周期才能保持穩定,SDA數據線的高或低電平狀態只能在SCL低電平時才能改變

    • 起始條件 S:
      • SCL為高電平,SDA下降沿1→0時,主器件產生起始信號
      • 起始信號產生後,總線處於忙狀態,其他I2C器件無法訪問總線
    • 停止條件 P:
      • SCL為高電平,SDA上升沿0→1時,主器件產生停止信號

        p.s. 非應答信號規定:當主機為接收設備,主機對最後一個字節不應答,以向發送設備表示數據傳送結束

      • 停止條件產生後,主從設備釋放總線,總線再次處於空閑狀態

      技術分享

    • 傳輸過程:
      • 主設備在傳輸有效數據之前先指定從設備的地址,設備地址為7位時,再加一個最低位表示數據傳輸的方向,0表示主設備→從設備寫數據,1表示主設備讀數據。

        7位地址碼:其中DA3~DA0(硬件出廠時固有的地址編碼)及A2~A0(用戶設定)為從機地址

      技術分享

      技術分享

      • 主設備在SCL線上產生每個時鐘脈沖的過程中將在SDA線上傳輸一個bit
      • 當一個字節按數據位從高到低順序傳輸完之後,接收設備將SDA拉為低電平,表示數據傳輸正確,回傳給主設備一個應答位。一個字節傳輸完畢。

        p.s. 並不是所有的字節傳輸都必須有一個應答位,比如:當從設備不能再接收主設備發送的數據時,從設備回傳一個非應答位

        在一次傳輸中可以傳輸多個字節,圖中只畫出首字節

      技術分享

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  • 當主機向從機發送1字節數據時

    p.s. 實際上主從機的SDA信號是在同一根線上的,分開畫有助於理解各自的行為

    技術分享

  • 當主機從從機接收1字節數據時

    技術分享

————————————————————————————————————————————

AT24C02

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

主要型號:

ATMEL公司生產的AT24C系列EEPROM中具有I2C總線接口。

這類芯片可以解決掉電而造成的數據丟失的問題,可以保存數據100年,擦寫100w次以上。

芯片地址固定部分為1010

型號

存儲容量

AT24C01

128*8

AT24C02

256*8

AT24C04

512*8

AT24C08

1024*4

AT24C16

2048*8

芯片特性:略

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

引腳描述:

技術分享

技術分享

  • A0/A1/A23條地址線,用於確定芯片的硬件地址,在上圖系統中均接地,選擇000
  • 4腳和第8腳為正負電源
  • 5腳為SDA串行數據輸入/輸出,與單片機P3.5相連
  • 6腳為SCL串行時鐘輸入線,與單片機P3.6相連
  • SDASCL都需要與正電源間接一個5.1k歐上拉電阻
  • 7腳寫保護功能接地
  • 24C02中帶有片內地址寄存器,每寫入或讀出一個數據字節後,該地址寄存器自動+1,實現對下一個存儲單元的讀寫。為降低總的寫入時間,一次操作可以寫入多達8個字節的數據。

————————————————————————————————————————————

AT24C02應用實例

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

設計要求:

  • 采用定時中斷方式,設計一個0~59s變化的秒表,將每次顯示在數碼管上的時間存入AT24C02中

技術分享

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

設計思路:

  • 通過定時器50ms觸發中斷,每次觸發中斷時中斷計數,到達1s時flag標識為1
  • 在死循環中始終顯示當前秒數
  • 每次秒數變化時寫入flag清零並寫入AT24C02中

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

硬件清單及連線情況:

技術分享

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

實現代碼:

  1 #include <reg51.h>
  2 typedef unsigned char uchar;
  3 typedef unsigned int uint;
  4 sbit scl = P3 ^ 0;
  5 sbit sda = P3 ^ 1;
  6 uchar second = 0;
  7 uchar count = 0;
  8 bit flag = 0;
  9 uchar code table[] =
 10 {
 11     0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6, 0xEE, 0x3E, 0x9C, 0x7A, 0x9E, 0x8E
 12 };
 13 void Init(); //初始化總線
 14 void Start(); //開始
 15 void Stop(); //停止
 16 void Respons(); //響應位
 17 uchar ReadByte(); //讀數據
 18 uchar ReadAddress(uchar address); //讀地址
 19 void WriteByte(uchar dat); //寫字節
 20 void WriteAddress(uchar address, uchar dat); //寫地址
 21 void Display(); //顯示數碼管
 22 void Delay1ms(uchar m); //延時1ms
 23 void Delay(); //延時2個機器周期
 24 void main()
 25 {
 26     /* 初始化總線 */
 27     Init();
 28     /* 初始化LED */
 29     P1 = 0xff;
 30     /* 設置定時器 */
 31     TMOD = 0x01;
 32     TH0 = (65536 - 50000) / 256;
 33     TL0 = (65536 - 50000) % 256;
 34     /* 中斷初始化 */
 35     EA = 1;
 36     ET0 = 1;
 37     /* 定時器開始 */
 38     TR0 = 1;
 39     /* 顯示數碼管並寫入 */
 40     while(1)
 41     {
 42         if (flag == 1)
 43         {
 44             flag = 0;
 45             WriteAddress(2, second);
 46         }
 47         Display();
 48     }
 49 
 50 }
 51 void Init()
 52 {
 53     //空間狀態時SCL與SDA均保持高電平
 54     sda = 1;
 55     Delay();
 56     scl = 1;
 57     Delay();
 58 }
 59 void Start()
 60 {
 61     //SCL高電平情況下,SDA下降沿啟動
 62     sda = 1;
 63     Delay();
 64     scl = 1;
 65     Delay();
 66     sda = 0;
 67     Delay();
 68 }
 69 void Stop()
 70 {
 71     //SCL高電平情況下,SDA上升沿停止
 72     sda = 0;
 73     Delay();
 74     scl = 1;
 75     Delay();
 76     sda = 1;
 77     Delay();
 78 }
 79 void Respons()
 80 {
 81     //在SCL位為高電平時產生響應信號,數據傳輸正確時產生應答且SDA拉低
 82     uchar i;
 83     scl = 1; //此處scl拉高後在while循環中降低,參照時序圖
 84     Delay();
 85     while ((sda == 1) && (i < 255))
 86     {
 87         //SDA拉低時跳出循環,表示數據傳輸正確,產生應答.如果在一段時間內未收到應答,則不再等待跳出循環
 88         i++;
 89         scl = 0;
 90         Delay();
 91     }
 92 }
 93 void WriteAddress(uchar address, uchar dat)
 94 {
 95     Start(); //開始
 96     WriteByte(0xA0); //寫入 1010 0000 高4位為固定值,5-7位為A0 A1 A2,最低位0為寫操作標識
 97     Respons();
 98     WriteByte(address); //寫入 0000 0010
 99     Respons();
100     WriteByte(dat); //寫入數據(秒數)
101     Respons();
102     Stop(); //停止
103 }
104 void WriteByte(uchar dat)
105 {
106     uchar i, temp;
107     temp = dat; //將dat讀入temp
108     for (i = 0; i < 8; ++i)
109     {
110         temp = temp << 1; //temp左移,最高位移入CY
111         scl = 0; //SCL復位,等待最高位存入SDA後置位
112         Delay();
113         sda = CY; //CY在頭文件中已規定,通過SDA發送bit
114         Delay();
115         scl = 1; //SCL置位,延遲2個機器周期後復位
116         Delay();
117     }
118     scl = 0; //為最後一個SCL高電平復位
119     Delay();
120     sda = 1; //一個字節數據發送完畢後置位準備響應
121     Delay();
122 }
123 uchar ReadAddress(uchar address)
124 {
125     uchar byte;
126     Start();
127     WriteByte(0xA0);
128     Respons();
129     WriteByte(address);
130     Respons();
131     Start();
132     WriteByte(0xA1); //寫入地址 1010 0001,讀寫標誌位1為讀
133     Respons();
134     byte = ReadByte();
135     Stop();
136     return byte;
137 }
138 uchar ReadByte()
139 {
140     uchar i, k;
141     scl = 0;
142     Delay();
143     sda = 1;
144     Delay();
145     for (i = 0; i < 8; ++i)
146     {
147         scl = 1;
148         Delay();
149         k = (k << 1) | sda;
150         scl = 0;
151         Delay();
152     }
153     return k;
154 }
155 void Display()
156 {
157     P2 = 0xfe;
158     P1 = table[second % 10];
159     Delay1ms(1);
160     P2 = 0xfd;
161     // P1 = table[second / 10 %10];
162     P1 = table[second / 10];
163     Delay1ms(1);
164     // P2 = 0xfb;
165     // P1 = table[second / 100];
166     // Delay1ms(5);
167 }
168 void Delay()
169 {
170     ;;
171 }
172 void Delay1ms(uchar m) //使用1ms時二極管閃爍,此處將y=110改成y=50
173 {
174     uchar x, y;
175     for (x = m; x > 0; ++x)
176         for (y = 50; y > 0; --y)
177             ;
178 }
179 void time()interrupt 1
180 {
181     TH0 = (65536 - 50000) / 256;
182     TL0 = (65536 - 50000) % 256;
183     count++;
184     if (count == 20)
185     {
186         count = 0;
187         flag = 1;
188         second++;
189         if (second == 60)
190             second = 0;
191     }
192 }

技術分享

51單片機基於I2C總線的秒表模擬應用