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

📄 wsaa1064.asm

📁 C8051F系列单片机外围电路功能模块程序
💻 ASM
字号:
;参考程序B :WSAA1064.ASM程序功能:向显示器SAA1064送数据
;显示0,1,2,3四位数要显示的数据在70H--7BH中.
$include (C8051F020.inc)         
 SAA1064ADR      EQU   070H        ; SAA1064芯片的写地址
   ;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
    SUBADDR:       DS    1         ;要访问器件的子地址
   ; 用于暂存数据的单元
    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  
 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端口及时钟
        CLR    SM_BUSY          ;为第一次传输清除SM_Busy标志
        SETB       EA   
		MOV    R1,#50H   
; SAA1064W: 依次连续写入5个数到SAA1064中去:17H,3FH,06H,5BH,4FH
        MOV     SUBADDR,#00H ; 装入SAA1064的子地址(SUBADR=00H)
        MOV     DATA_COUNT,#6H         ; 装入待写数据块的长度
        MOV     SLA_ADD,#SAA1064ADR    ; 装入从器件的写地址
		MOV     R0,#0                  ; R0做计数器用
        LCALL   SEND   
		CLR   EA                       ; 调用数据发送子程序
    	SJMP   $                       ; 运行结束,原地等待.
TAB:    DB  17H,4fH,5bH ,06H,3FH;送显示器SAA1064的数据,显示3,2,1,0四位数
;发送子程序SEND;
;SEND子程序执行一次向SAA1064写入六位数据(0,17H,4FH,5BH,06H,3FH)的过程。
;该子程序管理SM_BUSY位,设置 RW=WRITE,装载 SLAW,启动写操作。
     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保存到SLAW
	 SETB     SM_BUSY             ; 占用SMBus
     SETB     STA                 ; 启动发送过程
     JB       SM_BUSY,$            ;等待发送结束(在中断中处理)
     POP      ACC     
	 RET               
;SMBus 中断程序 ,处理SMBUS 中断
    SMBus_ISR:
    PUSH     PSW                ; 保护现场
    PUSH     ACC                ; 
    PUSH     DPH                ;  
    PUSH     DPL                ; 
    MOV    A,SMB0STA ;将当前状态(SMB0STA)装入累加器.每个状态对应一个地址偏移量 ;    ANL      A,#7FH     ; 屏蔽最高位
    MOV    @R1,A       ;在50H---60H中存放SMB0STA和SMB0DAT,可查看中断路径
	INC    R1
	MOV    @R1,SMB0DAT;
	INC    R1                              
    MOV     DPTR,#SMB_STATE_TABLE ; DPTR指向状态表的起始地址
    JMP    @A+DPTR                ;转移到当前状态
;SMBuS状态表                      ;(SMB0STA  =00H)
    SMB_STATE_TABLE: ; SMB_BUS_ERROR总线错误(对所有方式)
     ORG   SMB_STATE_TABLE+SMB_BUS_ERROR    
    SETB   STO         ; 停止位置1,使硬件复位
    JMP   SMB_ISR_END    ; 中断返回
 ;SMB_START     ;                  (SMB0STA  =08H)
 ;主发送器/接收器发送起始位成功.再将从机写地址送SMB0DAT并清除START位.
    ORG    SMB_STATE_TABLE+SMB_START        
    MOV    SMB0DAT,WRI_ADD        ; 装载从地址+ W````
    CLR    STA                     ; 清除START位
    JMP    SMB_ISR_END             ; 中断返回
;SMB_RP_START                    ;(SMB0STA  =10H)
;主发送器/接收器发送重复起始位成功.再将从机读地址送SMB0DAT并清除START位.
    ORG   SMB_STATE_TABLE+SMB_RP_START      
    MOV   SMB0DAT,READ_ADD         ;装载从地址+ R
    CLR   STA                      ; 清除START位
    JMP   SMB_ISR_END
;SMB_MTADDACK                      (SMB0STA  =18H)
;主发送器(MT)发送从地址+W成功;收到 ACK,再将要发的子地址送入SMB0DAT.
 ORG    SMB_STATE_TABLE+SMB_MTADDACK      
 MOV    SMB0DAT,SUBADDR          ;装载从器件的子地址到SMB0DAT.
 SETB   BYTE_SENT ;BYTE_SENT=1.在下一次中断调用时存储器地址刚被发送
JMP   SMB_ISR_END
;SMB_MTADDNACK                       (SMB0STA  =20H)
;主发送器(MT)发送从地址+W成功;收到 NACK,用确认查询重试。发送 STOP+START
ORG    SMB_STATE_TABLE + SMB_MTADDNACK       
   SETB    STO
   SETB    STA
   JMP     SMB_ISR_END
;SMB_MTDBACK                            (SMB0STA  =28H)
;主发送器(MT)发送数据字节成功;收到ACK(从机应答) 
;检查BYTE_SENT:如果为1,说明刚发出的是存储器地址;为0,刚发出的是数据字节    
 ORG   SMB_STATE_TABLE+SMB_MTDBACK
    DJNZ   DATA_COUNT,ADDRESS_SENT
 JBC   BYTE_SENT,ADDRESS_SENT  ;如果BYTE_SENT=1,清除该位并转到
                               ;ADDRESS_SENT去执行状态表以外的处理程序
    JMP   DATA_SENT            ; 如果BYTE_SENT=0,数据刚被发出,
                               ; 传输过程完成,转到传输结束
;SMB_MTDBNACK                ;(SMB0STA  =30H)
;主发送器(MT)发送数据成功;收到NACK,用确认查询重试。发送STOP+START重试
   ORG   SMB_STATE_TABLE+SMB_MTDBNACK       
   SETB     STO
   SETB     STA
   JMP     SMB_ISR_END
; SMB_MTARBLOST      ;(SMB0STA  =38H);竞争失败.重新启动传输.
   ORG    SMB_STATE_TABLE+SMB_MTARBLOST     
    SETB     STO
    SETB     STA
   JMP     SMB_ISR_END
; SMB_MRADDACK                          ;(SMB0STA  =40H)
;(MR)主收发器发送从地址+R成功;收到 ACK(从机应答).主机发送ACK.
   ORG     SMB_STATE_TABLE+SMB_MRADDACK      
  SETB   AA   ;主机发送ACK,转入SMB_MRDBACK 	
  JMP     SMB_ISR_END
; SMB_MRADDNACK                   ;(SMB0STA  =48H)
;(MR)主收发器发送从地址+R成功;收到NACK(从机无应答),发送重复起始位重试
   ORG      SMB_STATE_TABLE+SMB_MRADDNACK   
			SETB    STA
            JMP    SMB_ISR_END
;SMB_MRDBACK                    (SMB0STA  =50H)
;(MR)主收发器接收数据成功;主机发送ACK .
  ORG    SMB_STATE_TABLE+SMB_MRDBACK       
	MOV    RECEIVE_BYTE, SMB0DAT
	CLR    AA ;主机发NACK(清除AA),下一次中断来时转入;SMB_MRDBNACK(58H)
	CLR    SM_BUSY;
    JMP     SMB_ISR_END
;SMB_MRDBNACK                  ;(SMB0STA  =58H)
;(MR)主收发器接收数据成功;主机发送NACK 
;读操作完成。读数据寄存器并发送STOP
      ORG     SMB_STATE_TABLE+SMB_MRDBNACK     
      MOV    RECEIVE_BYTE, SMB0DAT
      SETB    STO
	  SETB    AA       ;主机发ACK,为下一次传输置位AA
      CLR    SM_BUSY;
      JMP    SMB_ISR_END
    ADDRESS_SENT:
		MOV     DPTR,#TAB   ;查表,找到显示的数据(字型码)
		MOV     A,R0
		MOVC    A,@A+DPTR     
        MOV     DATA_BYTE ,A   
		INC     R0  
        MOV     SMB0DAT,DATA_BYTE ;将要显示的数据(字型码)送SAA1064
	    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
PORT_Init :
   ORL    OSCICN,#05H ;内部振荡器频率设置为4MHz,选择内部振荡器频率作系统时钟
   MOV    P0MDOUT,#00         ;P0口为开漏方式
   MOV    XBR0,#01H      ;通过功能选择开关将将SDA接P0.0引脚,SCL接P0.1引脚
   MOV    XBR2 ,#40H;         允许功能选择开关和弱上拉
 ; 初始化SMBus程序段
   MOV   SMB0CN,#04H          ; 配置 SMBus在确认周期发送 ACK(SDA线为低电平)
   MOV   SMB0CR,#0ECH         ; 设置时钟速率=100 kHz (系统时钟为4MHZ)
   ORL   SMB0CN,#40H          ; 允许SMBus
   ORL    EIE1,#02H           ; 允许SMBus中断
   RET
END


⌨️ 快捷键说明

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