標(biāo)題: 51單片機(jī)計(jì)件寫(xiě)入AT24C02存儲(chǔ)芯片源程序與proteus仿真 [打印本頁(yè)]

作者: 曉星辰·    時(shí)間: 2018-3-9 17:25
標(biāo)題: 51單片機(jī)計(jì)件寫(xiě)入AT24C02存儲(chǔ)芯片源程序與proteus仿真
51單片機(jī)計(jì)件仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機(jī)源程序如下:
  1. #include<reg51.h>
  2. #include<intrins.h>  //包含_nop_()函數(shù)定義的頭文件
  3. sbit RS=P1^0;  //寄存器選擇位,將RS位定義為P2.0引腳
  4. sbit RW=P1^1;  //寫(xiě)讀選擇位,將RW位定義為P2.1引腳
  5. sbit E=P1^2;   //使能信號(hào)位,將E位定義為P2.2引腳
  6. sbit BF=P0^7;  //忙碌標(biāo)志位,將BF位定義為P0.7引腳
  7. sbit S=P3^7;   //將S位定義為P3.7引腳
  8. #define OP_READ 0xa1  //器件地址以及讀寫(xiě)操作,0xa1即為1010 0001B
  9. #define OP_WRITE 0xa0 //器件地址以及寫(xiě)入操作,0xa1即為1010 0001B
  10. sbit SDA=P3^4;  //將串行數(shù)據(jù)總線SDA位定義在為P3.4引腳
  11. sbit SCL=P3^3;  //將串行時(shí)鐘總線SCL位定義在為P3.3引腳
  12. unsigned char code digit[]={"0123456789"};  //定義字符數(shù)組顯示數(shù)字
  13. void delay1ms()  //延時(shí)1ms
  14. {
  15.         unsigned char i,j;
  16.         for(i=0;i<10;i++)
  17.         for(j=0;j<33;j++)
  18.         ;
  19. }
  20. void delaynms(unsigned char n)  //延時(shí)若干毫秒,入口參數(shù):n
  21. {
  22.         unsigned char i;
  23.         for(i=0;i<n;i++)
  24.         delay1ms();
  25. }
  26. unsigned char BusyTest(void)  //判斷液晶模塊的忙碌狀態(tài),返回值result。result=1,忙碌。result=0,不忙。
  27. {
  28.         bit result;
  29.         RS=0;  //根據(jù)規(guī)定,RS為低電平,RW為高電平?可以讀狀態(tài)
  30.         RW=1;
  31.         E=1;   //E=1才允許讀寫(xiě)
  32.         _nop_();
  33.         _nop_();
  34.         _nop_();
  35.         _nop_();  //空操作四個(gè)周期
  36.         result=BF;  //將忙碌標(biāo)志電平賦給result
  37.         E=0;  //將E恢復(fù)低電平
  38.         return result;
  39. }
  40. void WriteInstruction(unsigned char dictate)  //將模式設(shè)置指令或顯示地址寫(xiě)入液晶模塊
  41. {
  42.         while(BusyTest()==1);  //如果忙就等待
  43.         RS=0;  //根據(jù)規(guī)定,RS和RW同時(shí)為低電平時(shí),可以寫(xiě)入指令
  44.         RW=0;  //
  45.         E=0;   //E置低電平(根據(jù)表8-6,寫(xiě)指令時(shí),E為高脈沖,讓E從0到1發(fā)生正跳變,所以應(yīng)先置“0”
  46.         _nop_();
  47.         _nop_();  //空操作兩個(gè)機(jī)器周期
  48.         P0=dictate;  //將數(shù)據(jù)送入P0口,即寫(xiě)入指令或地址
  49.         _nop_();
  50.         _nop_();
  51.         _nop_();
  52.         _nop_();  //空操作四個(gè)機(jī)器周期
  53.         E=1;  //E置高電平
  54.         _nop_();
  55.         _nop_();
  56.         _nop_();
  57.         _nop_();  //空操作四個(gè)機(jī)器周期
  58.         E=0;  //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開(kāi)始執(zhí)行命令
  59. }
  60. void WriteAddress(unsigned char x)  //指定字符顯示的實(shí)際地址,入口參數(shù):x
  61. {
  62.         WriteInstruction(x|0x80);  //顯示位置的方法規(guī)定為“80H+地址碼x”
  63. }
  64. void WriteData(unsigned char y)  //將數(shù)據(jù)(字符的標(biāo)準(zhǔn)ASCLL碼)寫(xiě)入液晶模塊,入口參數(shù):y
  65. {
  66.         while(BusyTest()==1);
  67.         RS=1;  //RS為高電平,RW為低電平,可以寫(xiě)入數(shù)據(jù)
  68.         RW=0;
  69.         E=0;   //E置低電平(根據(jù)表8-6,寫(xiě)指令時(shí),E為高脈沖,就是讓E從0到1發(fā)生正跳變,所以應(yīng)先置”0“
  70.         P0=y;  //將數(shù)據(jù)送入P0口,即將數(shù)據(jù)寫(xiě)入液晶模塊
  71.         _nop_();
  72.         _nop_();
  73.         _nop_();
  74.         _nop_();  //空操作四個(gè)機(jī)器周期
  75.         E=1;  //E置高電平
  76.         _nop_();
  77.         _nop_();
  78.         _nop_();
  79.         _nop_();  //空操作四個(gè)機(jī)器周期
  80.         E=0;  //當(dāng)E由高電平跳變成低電平時(shí),液晶模塊開(kāi)始執(zhí)行命令
  81. }
  82. void LcdInitiate(void)  //對(duì)LCD的顯示模式進(jìn)行初始化設(shè)置
  83. {
  84.         delaynms(15);  //延時(shí)15ms,首次寫(xiě)指令時(shí)應(yīng)給LCD一段較長(zhǎng)的反應(yīng)時(shí)間
  85.         WriteInstruction(0x38);  //顯示模式設(shè)置:16x2顯示,5x7點(diǎn)陣,8位數(shù)據(jù)接口
  86.         delaynms(5);  //延時(shí)5ms,給硬件一點(diǎn)反應(yīng)時(shí)間
  87.         WriteInstruction(0x38);  //
  88.         delaynms(5);
  89.         WriteInstruction(0x38);  //連續(xù)三次,確保初始化成功
  90.         delaynms(5);
  91.         WriteInstruction(0x0c);  //顯示模式設(shè)置:顯示開(kāi),無(wú)光標(biāo),光標(biāo)不閃爍
  92.         delaynms(5);
  93.         WriteInstruction(0x06);  //顯示模式設(shè)置:光標(biāo)右移,字符不移
  94.         delaynms(5);
  95.         WriteInstruction(0x01);  //清屏幕指令,將以前的顯示內(nèi)容清除
  96.         delaynms(5);
  97. }
  98. void Display(unsigned char x)  //顯示小時(shí)
  99. {
  100.         unsigned char i,j;
  101.         i=x/10;  //取整運(yùn)算,求得十位數(shù)字
  102.         j=x%10;  //取余運(yùn)算,求得個(gè)位數(shù)字
  103.         WriteAddress(0x44);  //寫(xiě)顯示地址,將十位數(shù)字顯示在第2行第5列
  104.         WriteData(digit[i]);  //將十位數(shù)字的字符常量寫(xiě)入LCD
  105.         WriteData(digit[j]);  //將個(gè)位數(shù)字的字符常量寫(xiě)入LCD
  106. }
  107. void start()  //開(kāi)始數(shù)據(jù)傳送,開(kāi)始位
  108. {
  109.         SDA=1;  //SDA初始化為高電平“1”
  110.         SCL=1;  //開(kāi)始數(shù)據(jù)傳送時(shí),要求SCL為高電平“1”
  111.         _nop_();
  112.         _nop_();  //空操作兩個(gè)機(jī)器周期
  113.         SDA=0;  //SDA的下降沿被認(rèn)為是開(kāi)始信號(hào)
  114.         _nop_();
  115.         _nop_();
  116.         _nop_();
  117.         _nop_();  //空操作四個(gè)機(jī)器周期
  118.         SCL=0;  //SCL為低電平時(shí),SDA上數(shù)據(jù)才允許變化(即允許以后的數(shù)據(jù)傳遞)
  119. }
  120. void stop()  //結(jié)束數(shù)據(jù)傳遞
  121. {
  122.         SDA=0;  //SDA初始化為低電平“0”
  123.         _nop_();
  124.         _nop_();  //空操作兩個(gè)機(jī)器周期
  125.         SCL=1;  //結(jié)束數(shù)據(jù)傳送時(shí),要求SCL為高電平“1”
  126.         _nop_();
  127.         _nop_();
  128.         _nop_();
  129.         _nop_();  //空操作四個(gè)機(jī)器周期
  130.         SDA=1;  //SDA的上升沿被認(rèn)為是結(jié)束信號(hào)
  131. }
  132. unsigned char ReadData()  //從AT24Cxx讀取數(shù)據(jù),出口參數(shù)x,從AT24Cxx移入數(shù)據(jù)到MCU
  133. {
  134.         unsigned char i;
  135.         unsigned char x;  //存儲(chǔ)從AT24Cxx中讀出的數(shù)據(jù)
  136.         for(i=0;i<8;i++)
  137.         {
  138.                 SCL=1;  //SCL置為高電平
  139.                 x<<=1;  //將x中的各二進(jìn)位向左移一位
  140.                 x|=(unsigned char)SDA;  //將SDA上的數(shù)據(jù)通過(guò)按位“或”運(yùn)算存入x中
  141.                 SCL=0;  //在SCL的下降沿讀出數(shù)據(jù)
  142.         }
  143.         return(x);  //將讀取的數(shù)據(jù)返還
  144. }
  145. bit WriteCurrent(unsigned char y)  //向AT23Cxx的當(dāng)前地址寫(xiě)入數(shù)據(jù),入口參數(shù)y(存儲(chǔ)待寫(xiě)入的數(shù)據(jù)),在調(diào)用此數(shù)據(jù)寫(xiě)入函數(shù)前需首先調(diào)用開(kāi)始start(),所以SCL=0
  146. {
  147.         unsigned char i;
  148.         bit ack_bit;  //存儲(chǔ)應(yīng)答位
  149.         for(i=0;i<8;i++)  //循環(huán)移入8個(gè)位
  150.         {
  151.                 SDA=(bit)(y&0x80);  //通過(guò)按位“與”運(yùn)算將最高位數(shù)據(jù)送到S,因?yàn)閭魉蜁r(shí)高位在前,低位在后
  152.                 _nop_();  //空操作一個(gè)機(jī)器周期
  153.                 SCL=1;  //在SCL的上升沿將數(shù)據(jù)寫(xiě)入AT24Cxx
  154.                 _nop_();
  155.                 _nop_();  //空操作兩個(gè)機(jī)器周期
  156.                 SCL=0;  //將SCL重新置為低電平,以在SCL線形成傳送數(shù)據(jù)所需的8個(gè)脈沖
  157.                 y<<=1;  //將y中的各二進(jìn)位向左移一位
  158.         }
  159.         SDA=1;  //發(fā)送設(shè)備(主機(jī))應(yīng)在時(shí)鐘脈沖的高電平期間(SCL=1)釋放SDA線,以讓SDA線轉(zhuǎn)由接收設(shè)備(AT24Cxx)控制
  160.         _nop_();
  161.         _nop_();  //空操作兩個(gè)機(jī)器周期
  162.         SCL=1;  //根據(jù)上述規(guī)定,SCL應(yīng)為高電平
  163.         _nop_();
  164.         _nop_();
  165.         _nop_();
  166.         _nop_();;  //空操作四個(gè)機(jī)器周期
  167.         ack_bit=SDA;  //接收設(shè)備(AT24Cxx)向SDA送低電平,表示已經(jīng)接收到一個(gè)字節(jié),若送高電平,表示沒(méi)有收到,傳送異常
  168.         SCL=0;  //SCL為低電平時(shí),SDA上數(shù)據(jù)才允許變化(即允許以后的數(shù)據(jù)傳遞)
  169.         return  ack_bit;  //返回AT24Cxx答應(yīng)位
  170. }
  171. void WriteSet(unsigned char add,unsigned char dat)  //向AT24Cxx中的指定地址寫(xiě)入數(shù)據(jù),存儲(chǔ)地址add,存儲(chǔ)待寫(xiě)入數(shù)據(jù)dat
  172. //在指定地址add處寫(xiě)入數(shù)據(jù)WriteCurrent
  173. {
  174.         start();  //開(kāi)始數(shù)據(jù)傳遞
  175.         WriteCurrent(OP_WRITE);  //選擇要操作的AT24Cxx芯片,并告知要對(duì)其寫(xiě)入數(shù)據(jù)
  176.         WriteCurrent(add);  //寫(xiě)入指定地址
  177.         WriteCurrent(dat);  //向當(dāng)前地址(上面指定的地址)寫(xiě)入數(shù)據(jù)
  178.         stop();  //停止數(shù)據(jù)傳遞
  179.         delaynms(4);  //一字節(jié)的寫(xiě)入周期為1ms,最好延時(shí)1ms以上
  180. }
  181. unsigned char ReadCurrent()  //從AT24Cxx中的當(dāng)前地址讀取數(shù)據(jù),出口參數(shù)x
  182. {
  183.         unsigned char x;
  184.         start();  //開(kāi)始數(shù)據(jù)傳遞
  185.         WriteCurrent(OP_READ);  //選擇要操作的AT24Cxx芯片,并告知要讀取其數(shù)據(jù)
  186.         x=ReadData();  //將讀取的數(shù)據(jù)存入x
  187.         stop();  //停止數(shù)據(jù)傳遞
  188.         return x;  //返回讀取的數(shù)據(jù)
  189. }
  190. unsigned char ReadSet(unsigned char set_add)  //從AT24Cxx中的指定地址讀取數(shù)據(jù),入口set_add,出口x
  191. //在指定地址讀取
  192. {
  193.         start();  //開(kāi)始數(shù)據(jù)傳遞
  194.         WriteCurrent(OP_WRITE);  //選擇要操作的AT24Cxx芯片,并告知要對(duì)其寫(xiě)入數(shù)據(jù)
  195.         WriteCurrent(set_add);  //寫(xiě)入指定地址
  196.         return(ReadCurrent());  //從指定地址讀出數(shù)據(jù)并返回
  197. }
  198. void main(void)
  199. {
  200.         unsigned char sum;  //存儲(chǔ)計(jì)算值
  201.         unsigned char x;  //存儲(chǔ)從AT24Cxx讀出的值
  202.         LcdInitiate();  //調(diào)用LCD初始化函數(shù)
  203.         sum=0;  //將計(jì)算值初始化為0
  204.         while(1)  //無(wú)限循環(huán)
  205.         {
  206.                 if(S==0)  //如果該建被按下
  207.                 {
  208.                         delaynms(80);  //軟件消抖,延時(shí)80ms
  209.                         if(S==0)  //確實(shí)該建被按下
  210.                         sum++;  //計(jì)算值加1
  211.                         if(sum==99)  //如果計(jì)滿99
  212.                                 sum=0;  //清0,重新開(kāi)始計(jì)數(shù)
  213.                 }
  214.                 WriteSet(0x01,sum);  //將計(jì)件值寫(xiě)入AT24C02中的指定地址“0x01”
  215.                 x=ReadSet(0x01);  //從AT24C02中讀出計(jì)件值
  216.                 Display(x);  //將計(jì)件值用1602LCD顯示
  217.         }
  218. }
復(fù)制代碼

改了一下引腳在開(kāi)發(fā)板上運(yùn)行 目前仿真的液晶屏無(wú)法顯示了,大家自行修改一下吧.所有資料51hei附件下載:
ex69.zip (75.04 KB, 下載次數(shù): 169)



作者: mtk1625    時(shí)間: 2019-1-19 08:42
哥們 這個(gè)液晶屏 毫無(wú)反應(yīng)啊
作者: fanlin    時(shí)間: 2019-7-29 23:49
mtk1625 發(fā)表于 2019-1-19 08:42
哥們 這個(gè)液晶屏 毫無(wú)反應(yīng)啊

他程序里面的引腳與接線圖沒(méi)對(duì)應(yīng)上你仔細(xì)看下
作者: @yao123    時(shí)間: 2021-6-28 12:42
mtk1625 發(fā)表于 2019-1-19 08:42
哥們 這個(gè)液晶屏 毫無(wú)反應(yīng)啊

我的也沒(méi)有反應(yīng)
作者: 51hei團(tuán)團(tuán)    時(shí)間: 2021-7-20 04:43
我把引腳給修改好了一下,可以顯示了,大家看看還有什么問(wèn)題?我覺(jué)得還需要加個(gè)手工復(fù)位開(kāi)關(guān)吧,這樣手動(dòng)讓單片機(jī)重啟,而at24c02的數(shù)據(jù)會(huì)保持

51hei.png (10.73 KB, 下載次數(shù): 34)

51hei.png

我修改后的.7z

33.1 KB, 下載次數(shù): 25, 下載積分: 黑幣 -5






歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1