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

📄 wsmbus24c02.asm

📁 C8051F.rar
💻 ASM
字号:
;参考程序B:WSMBUS24C02.ASM程序清单如下:
;WSMBUS24C02.ASM程序功能:AT24C02读/写并显示在数码管上读/写地址的范围:00H--3FH
;用8255驱动四位LED数码管,显示存储单元的地址和内容,显示格式:
;存储器的地址	存储器单元的内容
;   00H---3FH	    10H---4FH
$include (C8051F020.inc)       ; SFR声明
 PPA 	    EQU 	8000H    ;8255的端口地址.用数码管显示AT24C02读/写的数据
 PPB 	    EQU 	8001H
 PPC 	    EQU 	8002H
 CWR        EQU   8003H
 AT24C02    EQU   0A0H        ; AT24C02芯片的写地址
;SMBus状态(SMB9STA):
 SMB_BUS_ERROR   EQU   00H  ;(所有方式)总线错误
 SMB_START       EQU   08H  
;(MT&MR)主收发器发送起始位成功.再将从机写地址送SMB0DAT
 SMB_RP_START    EQU   10H  
;(MT&MR)主收发器重复发送起始位成功,再将从机读地址送SMB0DAT
 SMB_MTADDACK    EQU   18H  
;(MT)主收发器发送从地址+W成功;收到 ACK(从机应答)
;再将从器件的子地址送入SMB0DAT
 SMB_MTADDNACK   EQU   20H  ;(MT)主收发器发送从地址+W成功;收到 NACK.
 SMB_MTDBACK     EQU   28H  ;(MT)主收发器发送数据字节成功;收到ACK(从机应答)
 SMB_MTDBNACK    EQU   30H  ;(MT)主发送器发送数据成功;收到NACK(从机无应答).
 SMB_MTARBLOST   EQU   38H  ;(MT)总线竞争失败
 SMB_MRADDACK    EQU   40H  ;(MR)主收发器发送从地址+R成功;收到 ACK(从机应答)
 SMB_MRADDNACK   EQU   48H  ;(MR)主收发器发送从地址+R成功;收到NACK
 SMB_MRDBACK     EQU   50H  ;(MR)主收发器接收数据成功;主机将AA清另 ,发送ACK
 SMB_MRDBNACK    EQU   58H  ;(MR)主收发器接收数据成功;主机发送NACK ,1'STO
DSEG						;	数据段
ORG       30H;
    TRANSMIT_BYTE: DS    1          ;保存SMBus待发送的字节
    RECEIVE_BYTE:  DS    1         ; 保存SMBus刚收到的字节
    SLA_ADD:       DS    1          ;保存从地址
    WRI_ADD:       DS    1         ; 保存从地址+ WRITE
    READ_ADD:      DS    1         ; 保存从地址+ READ
    MEM_ADD:       DS    1          ;要访问的EEPROM存储器地址
   ; 用于暂存数据的单元
    DATA_COUNT:    DS    1          ;计数器变量
    DATA_BYTE:     DS    1         ; 数据
    DATA_ADDR:     DS    1        ;  存储器地址
BSEG
ORG      00H
    RW:            DBIT  1           ;R/W命令位。L为READ,0为WRITE
    SM_BUSY:       DBIT  1          ;SMBus忙标志(软件保存)
    BYTE_SENT:     DBIT  1          ; 用于表示刚发送的字节。即
     ; BYTE_SENT为l表示是EEPROM地址; BYTE_SENT为0表示是数据字节
 CSEG                                 ;代码段
    ORG      00H         ;复位
   LJMP     MAIN
    ORG     03BH        ;SMBus中断向量
   LJMP    SMBus_ISR
;主程序
MAIN:   MOV  SP,#7H 
	    MOV    WDTCN,#0DEH       ;禁止看门狗定时器
        MOV    WDTCN,#0ADH;
        LCALL  PORT_Init ;初始化I/O端口及系统时钟
  ; 初始化SMBus
  MOV   SMB0CN,#04H          ; 配置 SMBus在确认周期发送 ACK
  MOV   SMB0CR,#0D8H  ; 设置时钟速率=100 kHz ,系统时钟为8MHZ.
  ORL   SMB0CN,#40H   ; 允许SMBus
  ORL    EIE1,#02H    ; 允许SMBus中断
  CLR    SM_BUSY      ; 为第一次传输清除SM_Busy标志
  SETB       EA       ;开中断
; TESTW: 依次连续写入64个递增的数到EEPROM24C01中去
    MOV      DATA_BYTE,#10H        ;装入待写的数据
    MOV      DATA_ADDR,#00H      ; 装入待写数据的首地址
    MOV      DATA_COUNT,#040H    ; 装入待写数据块的长度
TESTW:        ;发送数据DATA_BYTE到存储器地址DATA_ADDR 
    MOV     SLA_ADD,#AT24C02         ; 装入从器件的写地址
    MOV     TRANSMIT_BYTE,DATA_BYTE ; 将待发送数据装入TRANSMIT_BYTE
    MOV     MEM_ADD,DATA_ADDR      ;  将存储器(EEPROM24C01)的地址装入 MEM_ADD
    LCALL   SEND                    ; 调用发送子程序
	INC     DATA_BYTE                   ;存入的数据递增
    INC     DATA_ADDR                  ;地址加1
    DJNZ    DATA_COUNT,TESTW          ; 计数器减1,不为0则循环到开始处
	; TESTR: 从EEPROM24C01中依次连续读出96个递增的数,并在数码管上显示出来.
    MOV      DATA_ADDR,#00H          ; 装入首地址
    MOV      DATA_COUNT,#40H         ; 装入数据块长度
TESTR:        ;发送DATA_BYTE到存储器地址DATA_ADDR 
     MOV     SLA_ADD,#AT24C02          ;装入从器件的写地址
     MOV     MEM_ADD,DATA_ADDR        ;将存储器地址装入 MEM_ADD
     LCALL   RECEIVE                  ; 调用接收子程序
     MOV     A,RECEIVE_BYTE           ;将接收到的字节装入累加器
	 LCALL   EXCH       ;将累加器A中的数(压缩的BCD码)存如7AH,7BH中.                  
	LCALL   DISPLED                  ;在数码管上显示刚读出来的数据  
    INC    DATA_ADDR                  ;地址加1
    DJNZ   DATA_COUNT,TESTR          ; 计数器减1,不为0则循环到开始处
    SJMP   $                         ; 运行结束,原地等待.
;发送子程序SEND;
;子程序SEND向EEPROM发送单字节
;假设从地址、存储器地址和要发送的数据已经装入到它们各自的变量中。
;该子程序管理SM_BUSY位,设置 RW=WRITE,装入 WRI_ADD,开始写操作。
     SEND:
     PUSH     ACC                  ;保存累加器
     JB       SM_BUSY,$            ;等待SMBus空闲
     CLR      RW                    ; RW= 0(写)
     MOV      A,SLA_ADD             ; 取SLA_ADD到A 
     MOV      WRI_ADD,A            ;将SLA_ADD+ WRITE保存到WRI_ADD 
	SETB     SM_BUSY             ; 占用SMBus
     SETB     STA                 ; 启动发送过程
     JB      SM_BUSY,$            ;等待发送结束(在中断中处理)
     POP     ACC     
		 RET               
; 接收子程序RECEIVE
;假设从地址和存储器已经装入到它们各自的变量中。
;该子程序管理 SM_BUSY位,设置 RW=READ,装入 READ_ADD和 WRI_ADD,启动传输过程。
;接收过程包括一个写待访问存储器地址的操作、一个重复起始位和一个读操作。 
RECEIVE:
    PUSH    ACC                ;保存累加器
    JB      SM_BUSY,$       ;等待 SMBus空闲
    SETB     RW                 ;RW= l(读)
    MOV     A,SLA_ADD         ;取SLA_ADD到A
    MOV     WRI_ADD,A         ;保存SLA_ADD+ WRITE到WRI_ADD
    MOV     A,SLA_ADD         
    ORL     A,#01              
    MOV     READ_ADD,A        ; 保存SLA_ADD+READ到 READ_ADD
    SETB     SM_BUSY            ; 占用SMBus
    SETB     STA                ; 启动发送过程
    JB      SM_BUSY,$        ;等待接收结束(在中断服务中处理)
    POP     ACC                ; 恢复累加器
    RET
;SMBus 中断程序
;用状态码SMB0STA值查找表,寻找8字节的程序段.
;从状态表的开始位置向下偏移,偏移量为其状态代码值(8的整数倍)。
    SMBus_ISR:
    PUSH     PSW                ; 保护现场
    PUSH     ACC                ; 
    PUSH     DPH                ;  
    PUSH     DPL                ; 
    MOV     A,SMB0STA  ; 将当前SMBus状态装入累加器;每个状态对应一个地址偏移量
    ANL      A,#7FH           ; 屏蔽最高位,因为使该位为 1的状态在本例
                                ; 中没有定义
    MOV     DPTR,#SMB_STATE_TABLE ; DPTR指向状态表的起始地址
    JMP    @A+DPTR                ;转移到当前状态
;SMBuS状态表 
    SMB_STATE_TABLE:
     ORG   SMB_STATE_TABLE+SMB_BUS_ERROR    ;( SMB0STA=00H),ERROR总线错误
    SETB   STO         ; 停止位置1使硬件复位
    JMP   SMB_ISR_END    ; 中断返回
 ;SMB_START,主发送器/接收器已发送起始位,R/W位总是为0(W),因先写存储器地址 
    ORG    SMB_STATE_TABLE+SMB_START        ; (SMB0STA=08H)
    MOV    SMB0DAT,WRI_ADD        ; 装载从地址+ W
    CLR    STA                     ; 清除START位
    JMP    SMB_ISR_END             ; 中断返回
;SMB_RP_START
;主发送器/接收器:已发送重复起始位
    ORG   SMB_STATE_TABLE+SMB_RP_START      ;( SMB0STA=10H)
    MOV   SMB0DAT,READ_ADD         ;装载从地址+ R
    CLR   STA                      ; 清除START位
    JMP   SMB_ISR_END
;SMB_MTADDACK,主发送器:已发送从地址+WRITE,收到ACK
    ORG    SMB_STATE_TABLE+SMB_MTADDACK      ;( SMB0STA=18H)
    MOV    SMB0DAT,MEM_ADD          ;装载存储器地址
    SETB   BYTE_SENT ;BYTE_SENT=1.在下一次中断调用时存储器地址刚被发送
JMP   SMB_ISR_END
;SMB_MTADDNACK
;主发送器:已发送从地址+WRITE,收到 NACK。从器件不应答
;用确认查询重试。发送 STOP+START
ORG    SMB_STATE_TABLE+SMB_MTADDNACK       ;( SMB0STA=20H)
   SETB    STO
   SETB     STA
   JMP     SMB_ISR_END
;SMB_MTDBACK   ;(SMB0STA=28H)
;主发送器:已发送数据字节;收到ACK。该状态在读和写操作中都要用到.
;检查BYTE_SENT:如果为1,则说明刚发出的是存储器地址;为0,刚发出的是数据字节
    ORG   SMB_STATE_TABLE+SMB_MTDBACK
	  JBC   BYTE_SENT,ADDRESS_SENT  ;如果BYTE_SENT=1,清除该位并转到
                          ;ADDRESS_SENT去执行状态表以外的处理程序
      JMP   DATA_SENT               ; 如果BYTE_SENT=0,数据刚被发出,
                                  ; 传输过程完成,转到传输结束
;SMB_MTDBNACK
;主发送器:已发送数据字节;收到NACK,从器件不应答
;用确认查询重试。发送STOP+START重试
   ORG   SMB_STATE_TABLE+SMB_MTDBNACK       ;( SMB0STA=30H)
    SETB     STO
    SETB     STA
   JMP     SMB_ISR_END
; SMB_MTARBLOST
;主发送器:竞争失败,不应发生此情况。如果发生,重新启动传输
   ORG    SMB_STATE_TABLE+SMB_MTARBLOST      ;( SMB0STA=38H)
    SETB     STO
    SETB     STA
   JMP     SMB_ISR_END
; SMB_MRADDACK
;主接收器:从地址+READ已发送。收到ACK
;设置为在下一次传输后发送NACK,因为那将是最后的字节
    ORG     SMB_STATE_TABLE+SMB_MRADDACK      ;9(40H)
    CLR     AA                   ;在确认周期发送NACK
   JMP     SMB_ISR_END
; SMB_MRADDNACK
;主接收器:已发送从地址+READ。收到 NACK
;从器件不应答。发送重复起始位重试
   ORG     SMB_STATE_TABLE+SMB_MRADDNACK       ;( SMB0STA=48H)
      SETB    STA
      JMP    SMB_ISR_END
;SMB_MRDBACK
;主接收器:已收到数据字节, ACK已发送
;不应出现,因为 AA已在前一状态被清除。如果发生,发送 STOP
     ORG    SMB_STATE_TABLE+SMB_MRDBACK        ;( SMB0STA=50H)
     SETB     STO
     JMP     SMB_ISR_END
;SMB_MRDBNACK
;主接收器:已收到数据字节。已发送 NACK 
;读操作完成。读数据寄存器并发送STOP
      ORG     SMB_STATE_TABLE+SMB_MRDBNACK      ;( SMB0STA=58H)
      MOV    RECEIVE_BYTE, SMB0DAT
      SETB    STO
      SETB    AA                      ; 为下一次传输置位AA
      CLR    SM_BUSY;
      JMP    SMB_ISR_END
;状态表结束: 
;检查RW位确定处理方法。如果为读,则转到RW_READ,如果为写,则将待发送数据装入SMBODAT。
    ADDRESS_SENT:
    JB     RW,RW_READ
    MOV    SMB0DAT,TRANSMIT_BYTE   ;装入数据
    JMP    SMB_ISR_END              ;中断返回
;对于地址字节刚发出的状态。重复发送START,启动存储器读操作
    RW_READ:
    SETB      STA                    ;重复发送START
    JMP      SMB_ISR_END            ;中断返回
;写操作,数据字节已发出。传输过程结束。发送STOP,释放总线,中断返回
    DATA_SENT:
    SETB    STO                     ;发送STOP后中断返回
    CLR     SM_BUSY                ; 释放 SMBus
    JMP     SMB_ISR_END            ; 中断返回
;SMBus ISR exit
;恢复寄存器,清除SI位,从中断返回
   SMB_ISR_END:
    CLR    SI
    POP    DPL 
    POP    DPH
    POP    ACC
    POP    PSW
    RETI
EXCH:MOV     B,A
		ANL     A,#0FH
		MOV     74H,A
		MOV     A,B  
		SWAP    A
        ANL     A,#0FH
		MOV     73H,A
		MOV     A,B
		MOV     A,DATA_ADDR 
		MOV     B,A
		ANL     A,#0FH
		MOV     71H,A
		MOV     A,B  
		SWAP    A
        ANL     A,#0FH
		MOV     70H,A
		MOV     A,B
		MOV     72H,#15H
		RET
;显示功能子程序,显示2个字节,被显示的字节在7AH,7BH中
DISPLED: ACALL  PORT_Init
  ACALL   C8255 ;8255初始化,为显示数据作准备
  MOV	R2,#01H
	MOV	R5,#5
	MOV	R0,#70H
DSP1:	MOV	DPTR,#PPB
	MOV	A,R2
	MOVX	@DPTR,A
	MOV	A,@R0
	CJNE  A,#15H,SS
	AJMP   DSP2
SS:  ANL  A,#0FH
DSP2:	MOV	DPTR,#BCD
     	MOVC	A,@A+DPTR
        MOV	DPTR,#PPC
        MOVX	@DPTR,A
	    ACALL   DEL0
	    MOV	A,R2
    	RL	A
	    MOV	R2,A
	    INC	R0
	    DJNZ	R5,DSP1
	    MOV	DPTR,#PPB
    	MOV	A,#0H
    	MOVX	@DPTR,A
	    RET
BCD:    DB      3FH,06H,5BH,4FH ;显示数值,0,1,2,3
        DB      66H,6DH,7DH,07H           ;4,5,6,7
	    DB 	7FH,6FH,77H,7CH           ;8,9,A,B
	    DB 	39H,5EH,79H,71H           ;C,D,E,F
	    DB 	73H,3EH,31H,6EH           ;P,U,Z,Y
	    DB      0FFH,00H                  ;8,灭     
C8255:
	MOV	A,#80H      ; 设置PC口,PB口为输出,PA口为输入
	MOV 	DPTR,#CWR       ;#8003H为8255的控制寄存器地址
	MOVX	@DPTR,A
	RET
PORT_Init :
   ORL    OSCICN,#06H  ; 将内部振荡器频率设置为8MHz
   MOV    P0MDOUT,#00  ;P0口为开漏方式
   MOV    XBR0,#01H  ;通过功能选择开关将将SDA接P0.0引脚,SCL接P0.1引脚
   MOV   XBR2 ,#40H;      允许功能选择开关和弱上拉
   MOV   P74OUT ,#0FFH;   P4,P5,P6,P7为推拉式输出
   MOV   EMI0CF ,#2cH
;EMIF工作在地址/数据复用方式,只用外部存储器,ALE高/低脉宽占1个SYSCLK周期
  MOV   EMI0TC ,#6cH;地址建立/保持时间占0个SYSCLK周期,/WR和/RD占12个周期
RET
LDELAY:MOV  R4,#2H
LDE:   ACALL  DEL0
			 DJNZ   R4,LDE
			 RET
DEL0:MOV R7,#06FH    ;延时子程序
TM:  MOV R6,#0FFH
     DJNZ R6,$
     DJNZ R7,TM
     RET
    END
	

⌨️ 快捷键说明

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