⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcf8574ab.asm

📁 c8051f020源代码39个 使用Silicon Labs IDE 调试器
💻 ASM
字号:

;实验29  程序PCF8574AB.ASM   
;用I2C(与SUNBUS兼容)虚拟总线的方法编程.调用I2C通用子程序软件包.
;程序功能:PCF8574是带SUMBUS总线的串口转并口的数据转换芯片.一个8位
;口连结8个开关(K1-K8)作输入,二个8位输出锁存口分别连结8个LED灯,指示二个8位
;输出.程序安排二个8位输出口锁存的数据电平相反.
; 运行参考程序,在连续输出三组数据:#0AAH,#55H;#0FH,#0F0H及#00H,#0FFH之后,
;处于输入状态,等待用户通过开关K1~K8输入数据并显示出来。  
$include (C8051F020.inc)      
 SLA1W          EQU   70H      ;PCF8574 A片写的节点地址(地址开关S1:000H)
 SLA1R          EQU   71H      ;PCF8574 A片读的节点地址 
 SLA2W          EQU   72H      ;PCF8574 B片写的节点地址 (地址开关S2:001H )    
 SLA2R          EQU   73H      ;PCF8574 B片读的节点地址 
 SLA3W          EQU   74H      ;PCF8574 C片写的节点地址 ((地址开关S3:010H)
 SLA3R          EQU   75H      ;PCF8574 C片读的节点地址 
 SLA            EQU   60H
 COM            EQU   17H
 SLAW           EQU   62H
 SLAR           EQU   63H
 NUMBYT        EQU   61H     ;被传送的字节数存放单元
 MTD            EQU   20H     ;发送数据缓冲区首地址
 MRD            EQU   30H     ;接收字节缓冲区首地址          
 VSCL           EQU   P0.1    ;模拟I2C总线时钟线
 VSDA           EQU   P0.0    ;模拟I2C总线数据线
               ORG    0
               SJMP   MAIN
MAIN:	      MOV    WDTCN,#0DEH  ;禁止看门狗定时器
              MOV    WDTCN,#0ADH;
			  MOV     XBR2,#40H  ;交叉开关使能
              ACALL    INITA     ;作为输入用的芯片应先初始化。
              ACALL    OUTPUT1   ;输出数据0AAH
              ACALL    DELAY     ;延时
              ACALL    OUTPUT2   ;输出数据55H
              ACALL    DELAY     ;延时
              ACALL    OUTPUT3   ;输出数据0FH
              ACALL    DELAY     ;延时
              ACALL    OUTPUT4   ;输出数据0F0H
              ACALL    DELAY     ;延时
ACALL    OUTPUT5   ;输出数据0H
ACALL    DELAY       ;延时
LOOP:       ACALL     PCFIO ;从输入器件U1读取开关K1~K8的状态数据并存入
             AJMP      LOOP  ;MRD中,再送U2,U3去。
OUTPUT1:   MOV       A,#0AAH      ;输出数据0AAH
             PUSH   ACC
            ACALL  WRITEB
             POP    ACC
             CPL    A
             ACALL  WRITEC
             RET
OUTPUT2:      MOV    A,#55H     ;输出数据55H
              PUSH   ACC
              ACALL  WRITEB
              POP    ACC
              CPL    A
              ACALL  WRITEC
              RET
OUTPUT3:      MOV    A,#0FH     ;输出数据0FH
              PUSH   ACC
              ACALL  WRITEB
              POP    ACC
              CPL    A
              ACALL  WRITEC
              RET
OUTPUT4:      MOV    A,#0F0H   ;输出数据0F0H
              PUSH   ACC
              ACALL  WRITEB
              POP    ACC
              CPL    A
              ACALL  WRITEC
              RET
OUTPUT5:      MOV    A,#0H   ;输出数据0H
              PUSH   ACC
              ACALL  WRITEB
              POP    ACC
              CPL    A
              ACALL  WRITEC
              RET             
PCFIO  :  ACALL  READA ;从输入器件U1读取开关K1~K8的状态数据并存入MRD中
          MOV   A,MRD
          MOV   B,A
          ACALL   WRITEB   ;将读入的数据送器件B
          MOV   A,B
          CPL   A          ;将读入的数据取反后送器件C
          ACALL  WRITEC
          RET
READA:   MOV    SLAW,#SLA1W    ;读A口
          MOV    SLAR,#SLA1R
WRA:     MOV   SLA,SLAR
          MOV   NUMBYT,#1
          LCALL RDNBYT
          RET                                 
INITA:   MOV    SLAW,#SLA1W      ;初始化:应置输入口锁存器为高电平
         MOV    SLAR,#SLA1R
         MOV    MTD,#0FFH
         MOV    SLA,SLAW
         MOV    NUMBYT,#1
         LCALL  WRNBYT 
         RET
WRITEB: MOV    SLAW,#SLA2W      ;将数据送器件B
         MOV    SLAR,#SLA2R
         ACALL   WRBC   
         RET
WRITEC: MOV    SLAW,#SLA3W     ;将数据送器件C
         MOV    SLAR,#SLA3R
         ACALL   WRBC   
         RET             
WRBC:   MOV    MTD,A
         MOV    SLA,SLAW
         MOV    NUMBYT,#1
         LCALL  WRNBYT
         RET           
 DELAY: MOV       R7,#50  ;5s
 DL2:   MOV       R6,#100                    ;100ms         
 DL1:   MOV       R5,#250                    ;1ms假定晶振为6MHZ
 DL0:   DJNZ      R5,DL0
        DJNZ      R6,DL1
        DJNZ      R7,DL2
        RET  
;发送一个字节数据(WRBYT)子程序,该子程序是向虚拟IIC总线的数据线VSDA上发送
;一个字节数据的操作。调用本子程序前将要发送的数据送入A中。占用资源:R0,C。        
WRNBYT: MOV          R3,NUMBYT
          LCALL    STAA             ;启动IIC总线
          MOV         A,SLA         ;发送SLAW字节
          LCALL       WRBYT
          LCALL       CACK          ;检查应答位
          JB          F0,WRNBYT     ;非应答位则重发
          MOV         R1,#MTD
  WRDA: MOV         A,@R1
          LCALL       WRBYT
          LCALL       CACK
          JB          F0,WRNBYT
          INC         R1
          DJNZ        R3,WRDA
          LCALL       STOP
          RET
;向被控器件发送N个字节数据(WRNBYT)子程序
WRBYT:   MOV	     R0,#08H       ;8为数据长度送R0中
   WLP:  RLC         A           ;发送数据左移,使发送位入C
         JC          WR1         ;判断发送"1"还是"0",发送"1"转WR1
         AJMP        WR0         ;发送"0"转WR0
  WLP1:  DJNZ         R0,WLP     ;8位是否发送完,未完转WLP
         RET                     ;8位发送完结束
   WR1:  SETB         VSDA       ;发送"1"程序段
         SETB        VSCL  
         NOP
         NOP
         CLR        VSCL
         CLR        VSDA
         AJMP       WLP1
  WR0:   CLR        VSDA         ;发送"0"程序段
         SETB       VSCL
         NOP
         NOP
         CLR    VSCL
         AJMP   WLP1
;通用N字节接收子程序(RDNBYT)
 RDNBYT:MOV        R3,NUMBYT
        LCALL      STAA               ;发送启动位
        MOV        A,SLA             ;发送寻址字节(读)
        LCALL      WRBYT
        LCALL      CACK              ;检查应答位
        JB         F0,RDNBYT         ;非正常应答时重新开始
RDN:    MOV        R1,#MRD           ;接收数据缓冲区首址MDR入R1
RDN1:   LCALL      RDBYT             ;读入一个字节到接收数据缓冲中
        MOV        @R1,A
        DJNZ       R3,ACK            ;N节读完否?未完转ACK
        LCALL      MNACK             ;N个字节读完发送非应答位
        LCALL      STOP              ;发送停止信号
        RET                         ;子程序结束
 ACK:   LCALL      MACK              ;发送应答位
        INC        R1                ;指向下一个接收数据缓冲单元
        SJMP       RDN1             ;转读入下一个字节数据
CACK:   SETB    VSDA                ;置VSDA为输入方式
        SETB    VSCL                ;使VSDA上数据有效
        CLR     F0                  ;预设F0=0
        MOV     C,VSDA              ;输入VSDA引脚状态
        JNC     CEND                ;检查VSDA状态,正常应答转CEND,且F0=0
        SETB    F0                  ;无正常应答,F0=1
CEND:  CLR     VSCL                ;子程序结束,使VSCL=0
        RET
MACK:  CLR       VSDA;发送应答位MACK子程序
        SETB      VSCL
        NOP
        NOP
        CLR       VSCL
        SETB      VSDA
	     RET
 MNACK: SETB        VSDA   ;发送非应答位 MNACK子程序
         SETB        VSCL
         NOP
         NOP
         CLR         VSCL
         CLR         VSDA
         RET
;从VSDA上接收一个字节数据(RDBYT)子程序,该子程序用来从VSDA上读取一个字节数据.执行本程序后,从VSDA上读取的一个字节存放在R2或A中。资源占用:R0,R2,C。
 RDBYT:  MOV	R0,#08H                ;8位数据长度如R0
   RLP:  SETB        VSDA            ;置VSDA为输入方式
         SETB       VSCL             ;使VSDA上数据有效
         MOV        C,VSDA           ;读入VSDA引脚状态
         MOV        A,R2             ;读入"0"程序段,由C拼装入R2中
         RLC        A
         MOV        R2,A
         CLR        VSCL             ;使VSCL=0可继续接收数据位
         DJNZ       R0,RLP           ;8位读完否?未读完转RLP
         RET
STAA:    SETB	 VSDA;启动STAA子程序
         SETB	 VSCL
         NOP  
         NOP
         CLR	 VSDA
         NOP
         NOP
         CLR   VSCL
         RET
 STOP:CLR	VSDA;停止(STOP)子程序
      SETB	VSCL
      NOP  
      NOP
      SETB	VSDA
      NOP
      NOP
      CLR       VSDA
      CLR       VSCL
      RET
END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -