找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索

PIC16F873A單片機eeprom 24C02-24C64數(shù)據(jù)抄寫程序求助

查看數(shù): 2567 | 評論數(shù): 7 | 收藏 0
關(guān)燈 | 提示:支持鍵盤翻頁<-左 右->
    組圖打開中,請稍候......
發(fā)布時間: 2021-9-6 21:05

正文摘要:

   網(wǎng)上找的,PIC16F873A單片機eeprom 24C02-24C64數(shù)據(jù)抄寫程序,用MPLAB IDE編譯,報告一大堆錯誤,求助大蝦幫忙看看這個匯編程序到底錯在哪里?程序如下: ;****************I2C總線EPROM數(shù)據(jù)抄寫程序** ...

回復(fù)

ID:155507 發(fā)表于 2021-9-8 18:58
我給你來個 C 程序試試



  1. #include <pic.h>           //調(diào)用PIC16F87XA單片機的頭文件

  2. //根據(jù)選項,配置字應(yīng)該如下所示:
  3. //__CONFIG(HS&WRTEN&WDTDIS&BOREN&PWRTDIS&UNPROTECT&DUNPROT&DEBUGDIS&LVPDIS);

  4. //實際使用中,這樣太麻煩,對于默認選項,我們將其忽略掉:
  5. __CONFIG(HS&WDTDIS&LVPDIS);

  6. //---------------------------------------
  7. //1602液晶相關(guān)I/O設(shè)置
  8. #define E   RB3            //1602液晶的E腳接在RB3口上
  9. #define RW  RB4            //1602液晶的RW腳接在RB4口上
  10. #define RS  RB5            //1602液晶的RS腳接在RB5口上
  11. //---------------------------------------

  12. //---------------------------------------
  13. //軟件模擬IIC相關(guān)I/O設(shè)置
  14. #define SCL   RC3      //AT24C02的 SCL 引腳接于單片機的RC3引腳上
  15. #define SDA   RC4      //AT24C02的 SDA 引腳接于單片機的RC4引腳上
  16. //---------------------------------------

  17. //---------------------------------------
  18. //1602液晶寄存器設(shè)置
  19. unsigned char DISbuf;     //設(shè)置8位的unsigend char型寄存器用來暫存1602要顯示的內(nèi)容
  20. //---------------------------------------



  21. void Delay(void)
  22. {
  23.      unsigned char k;      //定義一個8位寄存器用來做延時用
  24.      for(k=0;k<50;k++);    //延時約50微秒
  25. }



  26. void IICstart(void)
  27. {
  28.      SDA=1;                //先將SDA=1,以準備在SCL=1時,將SDA=0
  29.      SCL=1;                //時鐘總線拉高
  30.      Delay();              //調(diào)用延時函數(shù),略作延時
  31.      SDA=0;                //SCL=1時,將SDA拉低即產(chǎn)生啟動信號
  32.      Delay();              //調(diào)用延時函數(shù),略作延時
  33.      SCL=0;                //將SCL=0,完成啟動信號操作
  34.      Delay();              //調(diào)用延時函數(shù),略作延時
  35. }



  36. void IICstop(void)
  37. {
  38.      SDA=0;                //先將SDA=0,以準備在SCL=1時,將SDA=1
  39.      SCL=1;                //時鐘總線拉高
  40.      Delay();              //調(diào)用延時函數(shù),略作延時
  41.      SDA=1;                //SCL=1時,將SDA拉高即產(chǎn)生停止信號
  42.      Delay();              //調(diào)用延時函數(shù),略作延時
  43.      SCL=0;                //將SCL=0,完成啟動信號操作
  44.      Delay();              //調(diào)用延時函數(shù),略作延時
  45. }



  46. void Write1Byte(unsigned char Buf1)
  47. {
  48.      unsigned char k;      //1個字節(jié)要分8次寫入,需要定義一個寄存器用來計數(shù)
  49.      for(k=0;k<8;k++)      //做一個8次的循環(huán),每次寫入1位,需要寫8次
  50.      {
  51.          if(Buf1&0x80)     //從最高位開始寫
  52.          {
  53.              SDA=1;        //如果欲寫入數(shù)據(jù)為1,就將數(shù)據(jù)線置1
  54.          }
  55.          else
  56.          {
  57.              SDA=0;        //如果欲寫入數(shù)據(jù)為0,就將數(shù)據(jù)線寫0
  58.          }
  59.          asm("NOP");       //略做延時
  60.          asm("NOP");       //略做延時
  61.          SCL=1;            //時鐘線做一個上升沿,將一位數(shù)據(jù)寫入
  62.          Buf1=Buf1<<1;     //數(shù)據(jù)左移一位,將下次要寫入的位數(shù)據(jù)移到最高位
  63.          asm("NOP");       //略做延時
  64.          SCL=0;            //將SCL=0,以準備通過上升沿將數(shù)據(jù)寫入
  65.          asm("NOP");       //略做延時
  66.      }
  67.      TRISC4=1;             //將RC4(SDA)設(shè)置為輸入狀態(tài)
  68.      asm("NOP");           //略做延時
  69.      SCL=1;                //將SCL=1,做個上升沿準備讀應(yīng)答信號
  70.      asm("NOP");           //略做延時
  71.      asm("NOP");           //略做延時
  72.      SCL=0;                //將SCL=0,結(jié)束應(yīng)答信號讀操作
  73.      TRISC4=0;             //將RC4(SDA)恢復(fù)為輸出狀態(tài)
  74. }



  75. unsigned char Read1Byte(void)
  76. {
  77.      unsigned char k;      //1個字節(jié)要分8次讀出,需要定義一個寄存器用來計數(shù)
  78.      unsigned char t=0;    //定義一個寄存器用保存讀出數(shù)據(jù)
  79.      TRISC4=1;             //將RC4(SDA)設(shè)置為輸入狀態(tài)
  80.      for(k=0;k<8;k++)      //做一個8次的循環(huán),每次讀入1位,需要讀8次
  81.      {
  82.          t=t<<1;           //數(shù)據(jù)左移一位,空出最低位以準備保存讀入的一位數(shù)據(jù)
  83.          SCL=1;            //將SCL=1,做個上升沿準備讀一位數(shù)據(jù)
  84.          asm("NOP");       //略做延時
  85.          asm("NOP");       //略做延時
  86.          if(SDA==1)        //讀一位數(shù)據(jù),并判斷
  87.          {
  88.              t=t|0x01;     //如果讀入數(shù)據(jù)為1,就將接收緩沖區(qū)最低一位置1
  89.          }
  90.          else
  91.          {
  92.              t=t&0xfe;     //如果讀入數(shù)據(jù)為0,就將接收緩沖區(qū)最低一位寫0
  93.          }
  94.          SCL=0;            //SCL恢復(fù)為0,結(jié)束一位數(shù)據(jù)讀操作
  95.          asm("NOP");       //略做延時
  96.          asm("NOP");       //略做延時
  97.      }
  98.      TRISC4=0;             //將RC4(SDA)恢復(fù)為輸出狀態(tài)
  99.      return t;             //將讀入的一個字節(jié)返回
  100. }



  101. void WriteAT24C02(unsigned char Address,unsigned char Databuf)
  102. {                          //直接調(diào)用本函數(shù)即可對AT24C02的Address地址寫Databuf
  103.     IICstart();            //IIC啟動信號

  104.     Write1Byte(0xA0);      //發(fā)送AT24C02的器件地址和寫信號

  105.     Write1Byte(Address);   //發(fā)送地址

  106.     Write1Byte(Databuf);   //發(fā)送數(shù)據(jù)

  107.     IICstop();             //產(chǎn)生IIC停止信號
  108. }



  109. unsigned ReadAT24C02(unsigned char Address)
  110. {                          //直接調(diào)用本函數(shù)即可從AT24C02的Address地址讀出數(shù)據(jù)返回
  111.     unsigned char buf;     //定義一個寄存器用來暫存讀出的數(shù)據(jù)
  112.     IICstart();            //IIC啟動信號

  113.     Write1Byte(0xA0);      //發(fā)送AT24C02的器件地址和寫信號

  114.     Write1Byte(Address);   //發(fā)送地址

  115.     IICstart();            //IIC啟動信號

  116.     Write1Byte(0xA1);      //發(fā)送AT24C02的器件地址和讀信號

  117.     buf=Read1Byte();//讀一個字節(jié)數(shù)據(jù)

  118.     IICstop();             //產(chǎn)生IIC停止信號

  119.     return(buf);           //將讀出數(shù)據(jù)返回
  120. }



  121. void Delay1602(unsigned int t)
  122. {
  123.      unsigned int k;      //定義一個16位寄存器用來做延時用
  124.      for(k=0;k<t;k++);    //延時
  125. }



  126. void LCD1602_busy(void)
  127. {
  128.      TRISD7=1;            //將RD7口設(shè)置為輸入口,為讀做準備
  129.      RS=0;                //RS=0、RW=1、E=1時,忙信號輸出到DB7,由RD7讀入
  130.      RW=1;                //RS=0、RW=1、E=1時,忙信號輸出到DB7,由RD7讀入
  131.      E=1;                 //RS=0、RW=1、E=1時,忙信號輸出到DB7,由RD7讀入
  132.      while(RD7==1);       //由RD7讀入1,表示1602液晶忙,需要等待
  133.      E=0;                 //讀完以后,恢復(fù)E的電平
  134.      TRISD7=0;            //將RD7口設(shè)置為輸出口
  135. }



  136. void LCD1602_Write_com(unsigned char combuf)
  137. {
  138.      RS=0;                //選擇指令寄存器
  139.      RW=0;                //選擇寫狀態(tài)
  140.      PORTD=combuf;        //將命令字通過RD口送至DB
  141.      E=1;                 //E高電平將命令字寫入1602液晶
  142.      asm("NOP");          //添加一個空操作,使高電平至少維持1us
  143.      E=0;                 //寫完以后,恢復(fù)E的電平
  144. }



  145. void LCD1602_Write_com_busy(unsigned char combuf)
  146. {
  147.      LCD1602_busy();            //調(diào)用忙檢測函數(shù)
  148.      LCD1602_Write_com(combuf); //調(diào)用忙檢測函數(shù)
  149. }



  150. void LCD1602_Write_data_busy(unsigned char databuf)
  151. {
  152.      LCD1602_busy();      //調(diào)用忙檢測函數(shù)
  153.      RS=1;                //選擇數(shù)據(jù)寄存器
  154.      RW=0;                //選擇寫狀態(tài)
  155.      PORTD=databuf;        //將命令字通過RD口送至DB
  156.      E=1;                 //E高電平將命令字寫入1602液晶
  157.      asm("NOP");          //添加一個空操作,使高電平至少維持1us
  158.      E=0;                 //寫完以后,恢復(fù)E的電平
  159. }



  160. void LCD1602_Write_address(unsigned char x,unsigned char y)
  161. {
  162.      x&=0x0f;             //列地址限制在0-15間
  163.      y&=0x01;             //行地址限制在0-1間
  164.      if(y==0)             //如果是第一行
  165.          LCD1602_Write_com_busy(x|0x80);        //將列地址寫入
  166.      else                 //如果是第二行
  167.          LCD1602_Write_com_busy((x+0x40)|0x80); //將列地址寫入
  168. }



  169. void LCD1602_init(void)
  170. {
  171.      Delay1602(1500);          //調(diào)用延時函數(shù)
  172.      LCD1602_Write_com(0x38);  //8位數(shù)據(jù)總線,兩行顯示模式,5*7點陣顯示
  173.      Delay1602(500);           //調(diào)用延時函數(shù)
  174.      LCD1602_Write_com(0x38);  //8位數(shù)據(jù)總線,兩行顯示模式,5*7點陣顯示
  175.      Delay1602(500);           //調(diào)用延時函數(shù)
  176.      LCD1602_Write_com(0x38);  //8位數(shù)據(jù)總線,兩行顯示模式,5*7點陣顯示
  177.      LCD1602_Write_com_busy(0x38);  //8位數(shù)據(jù)總線,兩行顯示模式,5*7點陣顯示
  178.      LCD1602_Write_com_busy(0x08);  //顯示功能關(guān),無光標
  179.      LCD1602_Write_com_busy(0x01);  //清屏
  180.      LCD1602_Write_com_busy(0x06);  //寫入新的數(shù)據(jù)后,光標右移,顯示屏不移動
  181.      LCD1602_Write_com_busy(0x0C);  //顯示功能開,無光標
  182. }



  183. void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
  184. {
  185.      LCD1602_Write_address(x,y);    //先將地址信息寫入
  186.      LCD1602_Write_data_busy(buf);  //再寫入要顯示的數(shù)據(jù)
  187. }



  188. void main(void)            //主函數(shù),單片機開機后就是從這個函數(shù)開始運行
  189. {

  190.     TRISB=0B11000111;      //初始化RB7-RB0的輸入輸出方向
  191.     TRISC=0B11100111;      //初始化RC7-RC0的輸入輸出方向
  192.     TRISD=0B00000000;      //初始化RD7-RD0的輸入輸出方向
  193.     PORTB=0B00000000;      //初始化RB7-RB0的數(shù)值
  194.     PORTC=0B00000000;      //初始化RC7-RC0的數(shù)值
  195.     PORTD=0B00000000;      //初始化RD7-RD0的數(shù)值

  196.     LCD1602_init();        //調(diào)用1602液晶初始化函數(shù)

  197.         DISbuf=ReadAT24C02(0x18);   //從AT24C02中地址0X18讀取數(shù)據(jù)
  198.           DISbuf++;                         //讀出數(shù)據(jù)+1
  199.           WriteAT24C02(0x18,DISbuf);  //將+1后的數(shù)據(jù)保存到0X18中

  200.         LCD1602_Disp(0,0,'-');   //-
  201.         LCD1602_Disp(1,0,'-');   //-
  202.         LCD1602_Disp(2,0,'A');   //A
  203.         LCD1602_Disp(3,0,'T');   //T
  204.         LCD1602_Disp(4,0,'2');   //2
  205.         LCD1602_Disp(5,0,'4');   //4   
  206.         LCD1602_Disp(6,0,'C');   //C         
  207.         LCD1602_Disp(7,0,'0');   //0
  208.         LCD1602_Disp(8,0,'2');   //2

  209.         LCD1602_Disp(10,0,'T');  //T
  210.         LCD1602_Disp(11,0,'E');  //E
  211.         LCD1602_Disp(12,0,'S');  //S
  212.         LCD1602_Disp(13,0,'T');  //T
  213.         LCD1602_Disp(14,0,'-');   //-
  214.         LCD1602_Disp(15,0,'-');   //-

  215.         LCD1602_Disp(0,1,'B');   //B
  216.         LCD1602_Disp(1,1,'o');   //o
  217.         LCD1602_Disp(2,1,'o');   //o
  218.         LCD1602_Disp(3,1,'t');   //t
  219.    
  220.         LCD1602_Disp(5,1,'t');   //t         
  221.         LCD1602_Disp(6,1,'i');   //i
  222.         LCD1602_Disp(7,1,'m');   //m
  223.         LCD1602_Disp(8,1,'e');   //e
  224.         LCD1602_Disp(9,1,'s');   //s
  225.         LCD1602_Disp(10,1,':');   //:
  226.   
  227.         LCD1602_Disp(12,1,DISbuf/100+0x30);            //顯示百位
  228.         LCD1602_Disp(13,1,(DISbuf%100)/10+0x30); //顯示十位
  229.         LCD1602_Disp(14,1,DISbuf%10+0x30);            //顯示個位
  230.     while(1)               //死循環(huán),單片機初始化后,將一直運行這個死循環(huán)
  231.     {

  232.     }
  233. }
復(fù)制代碼
ID:624769 發(fā)表于 2021-9-8 16:36
shumivan 發(fā)表于 2021-9-8 16:03
怎么還在用匯編,我已經(jīng)全忘完了,只會C了

要提高編程能力,匯編是必須要學(xué)會的, 可以平時不用, 但必須要會, debug的時候,有問題,看一眼編譯出來的匯編,立馬就能明白是什么原因造成的,不會的話,會走很多彎路, 然后,C語言里不好控制的時序問題,進到匯編跟砍瓜切菜一樣。
程序主體都用C, 有些地方(尤其是涉及底層操作的地方)用點匯編,我覺得還是比較有必要的。
ID:81196 發(fā)表于 2021-9-8 16:03
怎么還在用匯編,我已經(jīng)全忘完了,只會C了
ID:655665 發(fā)表于 2021-9-7 22:21
Y_G_G 發(fā)表于 2021-9-6 22:29
學(xué)PIC的本來就少,你還是用匯編的,而且一個漢字注釋都沒有,你覺得別人能看明白?
這是我以前寫的24C02的驗證 ...

謝謝您的回復(fù),受教了。最近在寫E2PROM復(fù)制器的程序,就是將兩個24C32,將其中一個里面的數(shù)據(jù),通過單片機復(fù)制到另一個里面去,可總是寫不好,思路一直混亂。請大神給指點個好的思路,按您的思路,我在重新寫程序。
ID:96682 發(fā)表于 2021-9-6 22:32
代碼不全吧
ID:401564 發(fā)表于 2021-9-6 22:29
學(xué)PIC的本來就少,你還是用匯編的,而且一個漢字注釋都沒有,你覺得別人能看明白?
這是我以前寫的24C02的驗證程序,已經(jīng)在開發(fā)板上實際驗證過的,你對比一下吧
我已經(jīng)好久沒有用PIC匯編了,指令都快忘記完了

    #include <p16f877a.inc>        ;包含了PIC16F877A的寄存器聲稱文件
    __CONFIG _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _BOREN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _CP_OFF;配置設(shè)置生成的代碼

    CBLOCK  020H                ;定義連續(xù)變量
    COUNT                        ;計數(shù)用的
    DEL1                        ;用在延時子程序中
    DEL2                        ;用在延時子程序中
    DEL3                        ;
    DISP_ADDR                        ;顯示地址用寄存器
    DISP_DATA                        ;顯示數(shù)據(jù)用寄存器
    LED_1                        ;七段碼的個位
    LED_10                        ;七段碼的十位
    LED_100                        ;七段碼的百位
    DIV_DATA                        ;除法用寄存器
    DATA_BUF                        ;數(shù)據(jù)寫入和讀出用的緩沖器
    SESHI                        ;測試用寄存器
    ENDC                        ;結(jié)束定義
#define    S1        PORTB,0                ;按置S1
#define    S2        PORTB,1                ;按置S2
#define    S3        PORTB,2                ;按置S3
#define           COM0        PORTD,0                ;
#define           COM1        PORTD,1                ;
#define           COM2        PORTD,2                ;
#define           COM3        PORTD,3                ;定義幾個顯示的RA端口
#define            CY        STATUS,0        ;C為標志位,減法有借位=0,無借位=1
#define            SCL        PORTD,4                ;時鐘信號線
#define            SDA        PORTD,7                ;數(shù)據(jù)信號線
#define            SDA_C   TRISD,7        ;數(shù)據(jù)方向控制寄存器   
          
        ORG        00H                ;
        NOP                        ;這條指令是仿真要有的
        GOTO        MAIN                ;跳過中斷子程序       
        ORG        020H                ;
MAIN        BSF        STATUS,RP0        ;RP0=1,RP1=0,指令選擇BANK1
        BCF        STATUS,RP1        ;
;===============================================================================       
;以下是針對BANK1的操作==========================================================
        MOVLW   0FFH                ;
        MOVWF        TRISB                ;PORTB        作為輸入
        BCF        OPTION_REG,7        ;啟用RB的上拉電阻
        BCF        INTCON,3        ;
        MOVLW        00H                ;
        MOVWF        TRISC                ;PORTC        作為輸出-數(shù)據(jù)
        MOVWF        TRISD                ;PORTD        作為輸出-位選
        CLRF        TRISE                ;RD工作于正常的IO模式
;以下是針對BANK0的操作==========================================================
        BCF        STATUS,RP0        ;選擇BANK0
        CLRF        PORTC                ;
        CLRF        PORTD
;===============================================================================
        MOVLW        D'123'                ;默認數(shù)據(jù)是000
        MOVWF        DISP_DATA
        MOVLW        D'8'                ;默認地址是0
        MOVWF        DISP_ADDR
;===============================================================================       
LOOP        BTFSS        S1        ;按鍵1是1就跳過下一條指令
        CALL        S1_DISP        ;調(diào)用S1處理程序
        BTFSS        S2        ;S2沒有按下就跳過下一條指令
        CALL        S2_DISP        ;按下就調(diào)用S2處理子程序
        BTFSS        S3        ;S3沒有按下就跳過下一條指令
        CALL        S3_DISP        ;按下就中用S3處理子程序
        CALL        DISPLAY        ;顯示
        GOTO        LOOP        ;主程序在這循環(huán)
;===============================================================================       
READ_DATA;讀出一個字節(jié)----------------------------------------------------------
        BCF        SCL            ;
        BSF        SDA            ;SDA1
        BSF        SCL            ;            1
        BCF        SDA            ;SDA1>>0,起始信號
        BCF        SCL            ;
        ;-----------------------------------------------------------------------
        MOVLW        0A0H            ;0A0H為寫命令,完整的輸入8個位的地址
        CALL        WRITE_BYTE  ;寫入"寫"模式指令
        MOVFW        DISP_ADDR   ;寫入地址
        CALL        WRITE_BYTE  ;
        ;-----------------------------------------------------------------------
        BCF        SCL            ;
        BSF        SDA            ;SDA1
        BSF        SCL            ;               
        BCF        SDA            ;SDA1>>0,起始信號
        BCF        SCL            ;
        ;-----------------------------------------------------------------------
        MOVLW        0A1H            ;0A1H為讀命令,完整的輸入8個位的地址
        CALL        WRITE_BYTE  ;寫入"寫"模式指令
        CALL        READ_BYTE   ;讀出一個字節(jié)
        MOVWF        DISP_DATA
        ;-----------------------------------------------------------------------
        BCF        SCL            ;
        BCF        SDA            ;SDA0
        BSF        SCL            ;
        BSF        SDA            ;SDA0>>1,停止信號
        BCF        SCL            ;
        BCF        SDA
        RETURN
;===============================================================================
WRITE_DATA;寫入一個字節(jié)---------------------------------------------------------
        BCF        SCL            ;
        BSF        SDA            ;SDA1
        BSF        SCL            ;            1
        BCF        SDA            ;SDA1>>0,起始信號
        BCF        SCL            ;
        ;-----------------------------------------------------------------------
        MOVLW        0A0H            ;0A0H為寫命令,完整的輸入8個位的地址
        CALL        WRITE_BYTE  ;寫入"寫"模式指令
        MOVFW        DISP_ADDR   ;寫入地址
        CALL        WRITE_BYTE  ;
        MOVFW        DISP_DATA
        CALL        WRITE_BYTE
;-----------------------------------------------------------------------
        BCF        SCL            ;
        BCF        SDA            ;SDA0
        BSF        SCL            ;
        BSF        SDA            ;SDA0>>1,停止信號
        BCF        SCL            ;
        BCF        SDA
        RETURN
;===============================================================================
READ_BYTE;讀一個字節(jié)處理程序***************************************************
            BSF                STATUS,RP0  ;選擇BANK1
            BSF                SDA_C            ;SDA作為輸入
            BCF                STATUS,RP0  ;選擇BANK0
            MOVLW        D'8'
            MOVWF        COUNT            ;要讀出的字節(jié)是8
            BCF                SCL            ;時鐘0
R_B_LOOP    BCF                CY            ;
            BSF                SCL            ;時鐘上升沿
            BTFSC        SDA            ;是0就跳過下一條指令
            BSF                CY            ;是1,置位緩沖器的0位
            RLF                DATA_BUF,F  ;左移一次,從最高位開始讀出
            BCF                SCL            ;時鐘下降
            DECFSZ        COUNT,F            ;檢測是否完成了8個字節(jié)
            GOTO        R_B_LOOP    ;
            MOVFW        DATA_BUF    ;讀取到的數(shù)據(jù)保存到W
            BSF                STATUS,RP0  ;選擇BANK1
            BCF                SDA_C            ;SDA作為輸出
            BSF                SDA            ;
            BSF                SCL            ;
            BCF                SCL            ;
            BCF                SDA            ;
            BCF                STATUS,RP0  ;選擇BANK0
RETURN
;===============================================================================
WRITE_BYTE;寫入一個字節(jié)*********************************************************
            BSF                STATUS,RP0  ;選擇BANK1
            BCF                SDA_C            ;SDA作為輸出
            BCF                STATUS,RP0  ;選擇BANK0
            MOVWF        DATA_BUF    ;
            MOVLW        D'8'            ;
            MOVWF        COUNT            ;
            BCF                SCL            ;時鐘0
W_B_LOOP    BCF                SDA            ;清除輸出線
            BTFSC        DATA_BUF,7  ;最高位如果是0就跳過下一條指令
            BSF                SDA            ;最高位是1,置位D_I
            CALL        DELAY_5MS   ;延時5mS
            BSF                SCL            ;時鐘上升
            CALL        DELAY_5MS
            BCF                SCL            ;時鐘下降
            CALL        DELAY_5MS
            RLF                DATA_BUF,F  ;左移一次,
            DECFSZ        COUNT,F            ;檢測是否傳送完成8個字節(jié)
            GOTO        W_B_LOOP    ;沒有,跳去循環(huán)
            ;應(yīng)答---------------------------------------------------------------
            BSF                SDA
            BSF                STATUS,RP0  ;選擇BANK1
            BSF                SDA_C            ;SDA作為輸入
            BCF                STATUS,RP0  ;選擇BANK0
            BSF                SCL            ;
            CALL        DELAY_5MS   ;延時5mS
            BTFSC        SDA            ;SDA為0就跳過下一條指令
            GOTO        $-1            ;SDA為1,跳動循環(huán)
            BSF                STATUS,RP0  ;選擇BANK1
            BCF                SDA_C            ;SDA作為輸出
            BCF                STATUS,RP0  ;選擇BANK0
            BCF                SCL            ;
            BCF                SDA
RETURN
;===============================================================================
;按一下,數(shù)據(jù)顯示就加1               
S1_DISP;S1處理程序**************************************************************
            BTFSS        S1
            GOTO        $-1
            INCF        DISP_DATA,F ;數(shù)據(jù)加1,保存到F
            CALL        WRITE_DATA  ;寫入數(shù)據(jù)
            CALL        DELAY_5MS
            CALL        READ_DATA   ;再讀出數(shù)據(jù)
RETURN
;===============================================================================       
S2_DISP;S2處理程序**************************************************************
            BTFSS        S2
            GOTO        $-1
            DECF        DISP_DATA,F ;數(shù)據(jù)減1,保存到F
            CALL        WRITE_DATA  ;寫入數(shù)據(jù)
            CALL        DELAY_5MS
            CALL        READ_DATA   ;再讀出數(shù)據(jù)
RETURN
;===============================================================================
;按一下,地址就加1,最大顯示到9   
S3_DISP        ;S2處理程序*************************************************************
            BTFSS        S3
            GOTO        $-1
            INCF        DISP_ADDR,F        ;地址的值加1
            MOVLW        D'10'                ;10傳送到W
            SUBWF        DISP_ADDR,W        ;地址-W,結(jié)果保存到W
            BTFSC        CY                ;c進位為1,地址的值就是大于等于9了
            CLRF        DISP_ADDR        ;地址清零
            CALL        READ_DATA        ;再讀出數(shù)據(jù)
RETURN
;===============================================================================
;顯示程序***********************************************************************       
DISPLAY            BCF                STATUS,RP0  ;選擇BANK0
            CLRF        LED_1
            CLRF        LED_10
            CLRF        LED_100
;除法部分-----------------------------------------------------------------------   
            MOVFW        DISP_DATA   ;送顯示數(shù)據(jù)到W
DIV_100            MOVWF        DIV_DATA    ;W的值保存到寄存器
            MOVLW        D'100'            ;W等于100
            SUBWF        DIV_DATA,W  ;數(shù)據(jù)減去100,結(jié)果保存在W
            BTFSS        STATUS,C    ;C是1就跳過下一條指令,C=1,F就是大,還可以再減法
            GOTO        DIV_10            ;C=0,F已經(jīng)小于100,跳轉(zhuǎn)到減10
            INCF        LED_100,F   ;F大,百位加1
            GOTO        DIV_100            ;再去減一次
;-------------------------------------------------------------------------------            
DIV_10            MOVLW        D'10'            ;W等于10
            SUBWF        DIV_DATA,W  ;DIV_DATRA-10=
            BTFSS        STATUS,C    ;C=1,DIV_DATA就比W大
            GOTO        DIV_1            ;
            INCF        LED_10,F    ;
            MOVWF        DIV_DATA    ;W數(shù)據(jù)保存到寄存器
            GOTO        DIV_10            ;
;-------------------------------------------------------------------------------            
DIV_1            MOVFW        DIV_DATA
            MOVWF        LED_1
;顯示部分-----------------------------------------------------------------------
            MOVFW        LED_1            ;數(shù)據(jù)送到W
            CALL        TAB_LED            ;查表
            MOVWF        PORTC            ;W送到端口
            BCF                COM0            ;低電平,亮燈
            CALL        DELAY_5MS   ;延時5mS
            BSF                COM0            ;高電平,關(guān)燈
        ;-----------------------------------------------------------------------
            MOVFW        LED_10            ;
            CALL        TAB_LED            ;查表
            MOVWF        PORTC            ;
            BCF                COM1            ;
            CALL        DELAY_5MS   ;
            BSF                COM1            ;
        ;-----------------------------------------------------------------------
            MOVFW        LED_100            ;
            CALL        TAB_LED            ;查表
            MOVWF        PORTC            ;
            BCF                COM2            ;
            CALL        DELAY_5MS   ;
            BSF                COM2            ;
        ;-----------------------------------------------------------------------
            MOVFW        DISP_ADDR   ;顯示地址
            CALL        TAB_LED            ;查表
            MOVWF        PORTC            ;
            BCF                COM3            ;
            CALL        DELAY_5MS   ;
            BSF                COM3            ;
        ;-----------------------------------------------------------------------       
RETURN                                    ;
;===============================================================================
;5mS延時程序********************************************************************
DELAY_5MS   MOVLW        3H
            MOVWF        DEL3
            MOVLW        D'2'            ;
            MOVWF        DEL1            ;
LOOP_5MS1   MOVLW        D'1'            ;
            MOVWF        DEL2            ;
LOOP_5MS2   DECFSZ        DEL2,F            ;
            GOTO        LOOP_5MS2   ;100x2=200uS
            DECFSZ        DEL1,F            ;
            GOTO        LOOP_5MS1   ;
            DECFSZ        DEL3
            GOTO        LOOP_5MS1   ;       
RETURN                                    ;             
;===============================================================================
;BCD碼的表**********************************************************************
TAB_LED            
            ADDWF        PCL,F        ;把W的內(nèi)容疊加到PCL程序計數(shù)器上
            RETLW        0FCH        ;0
            RETLW        060H        ;1
            RETLW        0DAH        ;2
            RETLW        0F2H        ;3
            RETLW        066H        ;4
            RETLW        0B6H        ;5
            RETLW        0BEH        ;6
            RETLW        0E0H        ;7
            RETLW        0FEH        ;8
            RETLW        0F6H        ;9
            END

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

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表