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

📄 lm74saa1064.asm

📁 C8051F.rar
💻 ASM
字号:
;LM74SAA1064.ASM程序清单如下:2005.11.3
$include (C8051F020.inc)       ; SFR声明
    SAA1064ADR      EQU   070H        ; SAA1064芯片的写地址
   ; SMBus状态及其对应的偏移地址:
    SMB_BUS_ERROR   EQU   00H        ;(所有方式)总线错误
    SMB_START       EQU   08H       ; (MT&MR)已发送起始位
    SMB_RP_START    EQU   10H       ; (MT&MR)重复起始位
    SMB_MTADDACK    EQU   18H       ; (MT)已发送从地址+W;收到 ACK
    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)收到数据字节;已发送ACK 
    SMB_MRDBNACK    EQU   58H        ;(MR)收到数据字节;已发送NACK 
DSEG					            	;	数据段;
ORG       30H;
    SLA:           DS    1          ;保存从地址
    SLAW:          DS    1         ; 保存从地址+ WRITE
    SUBADR:        DS    1          ;要访问的器件SAA1064的子地址
   ; 用于暂存数据的单元
    COUNT:         DS    1          ;存放数据数目的单元
    DATA1:         DS    1         ; 存放数据的单元
    SUBADDR:       DS    1         ; 存放SAA1064的子地址SUBADR 
BSEG
ORG      20H
    RW:            DBIT  1           ;R/W命令位。l=READ,0=WRITE
    SM_BUSY:       DBIT  1          ;SMBus忙标志(软件保存)
    BYTE_SENT :    DBIT  1  
 CSEG                                 ;代码段
    ORG      00H         ;复位
   LJMP     MAIN
	ORG     033H        ;SPI中断向量
   LJMP    SPI_ISR
    ORG     03BH        ;SMBus中断向量
    LJMP    SMBus_ISR
	 ORG   100H
;主程序
MAIN:   MOV    SP,#7
	    MOV    WDTCN,#0DEH       ;禁止看门狗定时器
        MOV    WDTCN,#0ADH;
		LCALL  SPI_SMBUS_Init     ;初始化I/O端口
ABC:	LCALL   LM74             ;LM74采集温度值(16位数),存入40H,41H中
        CLR    SM_BUSY           ; 为第一次传输清除SM_Busy标志
        SETB       EA      
        MOV     SUBADDR,#00H ; 装入SAA1064的子地址(SUBADR=00H)
        MOV     COUNT,#6H    ; 装入待写数据块的长度
        MOV     SLA,#SAA1064ADR   ; 装入从器件的写地址(70H)
		MOV     R0,#7AH           ; R0做计数器用.从RAM 7AH单元开始
		MOV     A,#02               
		MOV      EIE1,A          ; 允许SMBus中断,不允许SPI中断
        LCALL   SEND ; SAA1064的发送子程序SEND 
		LCALL   DELY
		SJMP     MAIN; 运行一遍,再循环运行.
TAB:    DB  3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,39H,17H
;COM=#17H是SAA1064的控制命令 ;共阴极7段LED数码管的显示字形编码表;(0,1,2,3,4,5,6,7,8,9,C,COM)
;SAA1064的发送子程序SEND;
;SEND子程序向SAA1064写入六位数据(17H+三位温度值+字符"C").
; 依次连续写入6个数到SAA1064中去:17H+四位数字+"C"
;该子程序管理SM_BUSY位,设置 RW=WRITE,装载 SLAW,启动写操作。
SEND:           ;SEND子程序用中断方式向SAA1064写入六位数据(0,17H,及四位温度值)
     PUSH     ACC                  ;保存累加器
     JB       SM_BUSY,$            ;等待SMBus空闲
     CLR      RW                    ; RW= 0(写)
     MOV      A,SLA                 ; 取SLA_ADD到A 
     MOV      SLAW,A                ;将SLA_ADD+ WRITE保存到SLAW
	SETB     SM_BUSY                ; 占用SMBus
     SETB     STA                   ; 启动发送过程
     JB       SM_BUSY,$             ;等待发送结束(在中断中处理)
     POP      ACC     
	 RET               
;SMBus 中断程序
;在中断程序中实现对不同状态码的软件处理,SMBus状态码表被分成8字节的状态段,
;用状态码索引值查找表,寻找8字节的程序段,;从状态表的开始位置向下偏移,偏移量为;其状态代码值。每个状态用ORG命令起始。
    SMBus_ISR:
    PUSH     PSW                ; 保护现场
    PUSH     ACC                ; 
    PUSH     DPH                ;  
    PUSH     DPL                ; 
    MOV     A,SMB0STA ; 将当前SMBus状态装入累加器,每个状态对应一个地址偏移量
    MOV     DPTR,#SMB_STATE_TABLE    ; DPTR指向状态表的起始地址
    JMP    @A+DPTR                   ;转移到当前状态
;SMBuS状态表 
    SMB_STATE_TABLE:   ; SMB_BUS_ERROR总线错误. 
    ORG   SMB_STATE_TABLE+SMB_BUS_ERROR   ;1.( 状态寄存器SMB0STA =00H)
    SETB   STO         ; 停止位置1使硬件复位
    JMP   SMB_ISR_END    ; 中断返回
 ;SMB_START
;主发送器/接收器:已发送起始位,再发送读和写操作的存储器地址 
    ORG    SMB_STATE_TABLE+SMB_START      ; 2.( 状态寄存器SMB0STA =08H)
    MOV    SMB0DAT,SLAW            ; 装载从地址+ W
    CLR    STA                     ; 清除START位
    JMP    SMB_ISR_END             ; 中断返回
;SMB_RP_START
;主发送器/接收器:已发送重复起始位
;该状态只应在读操作期间出现,在已发出存储器地址,并得到确认之后发出
    ORG   SMB_STATE_TABLE+SMB_RP_START      ;3(状态寄存器SMB0STA =10H)
    CLR   STA                               ; 清除START位
    JMP   SMB_ISR_END
;SMB_MTADDACK
;主发送器:已发送从地址+WRITE,收到ACK
    ORG    SMB_STATE_TABLE+SMB_MTADDACK      ;4.( 状态寄存器SMB0STA =18H)
    MOV    SMB0DAT,SUBADDR                   ;装载存储器地址
    SETB   BYTE_SENT                   ;BYTE_SENT=1.存储器地址刚被发送出去。
JMP   SMB_ISR_END
;SMB_MTADDNACK
;主发送器:已发送从地址+WRITE,收到 NACK。从器件不应答
;用确认查询重试。发送 STOP+START
ORG    SMB_STATE_TABLE + SMB_MTADDNACK       ;5.( 状态寄存器SMB0STA =20H)
   SETB    STO
   SETB     STA
   JMP     SMB_ISR_END
;SMB_MTDBACK                                 ;6(状态寄存器SMB0STA =28H)
;主发送器:已发送数据字节;收到ACK。主机共需发送六个字节到SAA1064
;检查DATA_COUNT,六个字节送完否?送完了,就转DATA_SENT,传输结束 
;由于状态码的地址存放间隔只有8字节的空间。所以在指令码需要多于8字节的场合,
;程序要转到状态表以外的代码空间。
 ORG   SMB_STATE_TABLE+SMB_MTDBACK  
       DJNZ   COUNT,ADDRESS_SENT
	   JMP    DATA_SENT             
;SMB_MTDBNACK
;主发送器:已发送数据字节;收到NACK,从器件不应答
;用确认查询重试。发送STOP+START重试
   ORG   SMB_STATE_TABLE+SMB_MTDBNACK       ;7(状态寄存器SMB0STA =30H)
    SETB     STO
    SETB     STA
   JMP     SMB_ISR_END
; SMB_MTARBLOST
;以下是处理"SMB_MTDBACK"状态码的程序段。
;写SAA1064,则将待发送数据装入SMBODAT。
    ADDRESS_SENT:
	MOV     DPTR,#TAB   ;查表,找到显示的数据(字型码)
	MOV     A,@R0       ;RO初值=7AH
	MOVC    A,@A+DPTR   ;查表,找出RAM  7AH---7EH中的数据的字型码.
	CJNE    R0,#7CH,SS   ;在个位后面加小数点
	ADD     A,#80H
  SS: MOV     DATA1 ,A   
	  INC     R0  
      MOV     SMB0DAT,DATA1 ;将要显示的数据(字型码)送SAA1064
	  JMP     SMB_ISR_END            ; 中断返回
;这是一个写操作,数据字节已发出。传输过程结束。发送STOP,释放总线,中断返回
    DATA_SENT:
    SETB    STO                     ;发送STOP后中断返回
    CLR     SM_BUSY                ; 释放 SMBus
    JMP     SMB_ISR_END            ; 中断返回
;恢复寄存器,清除SI位,从中断返回
   SMB_ISR_END:
    CLR    SI
    POP    DPL 
    POP    DPH
    POP    ACC
    POP    PSW
    RETI
SPI_SMBUS_Init :
   ORL    OSCICN,#01H        ; 将内部振荡器频率设置为4MHz
   MOV    XBR0,#03;选择P0.0~P0.3分别为SPI接口的SCK、MISO、MOSI和NSS
	                 ;选择P0.4~P0.5分别为SMBUS总线的SDA,SCL
   MOV    XBR1,#0   
   MOV    XBR2 ,#40H;      允许功能选择开关和弱上拉
 ; 初始化SMBus程序段
   MOV   SMB0CN,#04H          ; 配置 SMBus在确认周期发送 ACK
   MOV   SMB0CR,#0ECH      ; 设置时钟速率=100 kHz(内部振荡器频率设置为4MHz)
   ORL   SMB0CN,#40H          ; 允许SMBus
MOV    A,#03
   MOV    EIE1,A              ; 允许SMBus中断,允许SPI中断
   MOV SPI0CFG ,#11000111B    ;选择在时钟的第2个边沿采样,
			                  ;SCK的空闲状态为高电平,移位数为8位
   MOV SPI0CN,#00000011B      ;允许主方式,允许SPI
   MOV SPI0CKR,#19 ;按照SPI0CKR的计算公式,选择SPI0CKR中的值应该为19
RET
LM74:  ;LM74采样温度值(二进制16位数)
 MOV   R4,#2            ;要从LM74读入的数据有两个字节
 SETB  EA			   ;CPU开中断
 MOV A,EIE1
 ANL   A,#01
 MOV EIE1,A      	   ;置ESPI0位为1,允许SPI申请中断          
 MOV   R1,#40H	 	     ;数据接收区首地址.
SETB    P0.7
ACALL  DEL0 
 CLR   P0.7
ACALL  DEL0 
 MOV  SPI0DAT,A	;启动SPI发送,产生SCK.
 ACALL  DEL0   ;中断服务程序从MISO端接收来自LM74的高8位(MOV  A,SPI0DAT)
MOV  SPI0DAT,A	;启动SPI发送,产生SCK
ACALL  DEL0    ;中断服务程序从MISO端接收来自LM74的低8位(MOV  A,SPI0DAT)
CJNE    R4,#0,LM74
 SETB   P0.7      
 LCALL  EXHH      ;整理温度数据
RET
SPI_ISR:PUSH   ACC
	    	PUSH   PSW
        CLR     SPIF
	    	MOV     A,SPI0DAT
        MOV     @R1	,A		 ;取下一个数
        INC     R1 
        DJNZ    R4,BACK 	      ;是否接收到2个数?未完转中断返回
        MOV     A,EIE1            ;已完,置ESPI0位为0,
        ANL     A,#0FEH
        MOV     EIE1,A      	 ;置ESPI0位为0,禁止SPI申请中断    
BACK:   POP     PSW
       	POP     ACC
	      RETI

       	POP     ACC
	      RETI

EXHH:    MOV  A,41H     ; 2x(41h)+2x(40h)
         RLC  A
         MOV  A,40H
         RL   A
         ADDC A,#0
         ACALL   EXCH   ;将温度值由二进制数转化为十进制数.
         MOV  7DH,#0    ;          
         MOV  A,41H
         ANL  A,#40H
         CJNE A,#40H,PP1     ;加小数点
         MOV  7DH,#5H
   PP1:  MOV  79H,#0
	     MOV   A,40H        ;从40H最高位位符号判别位,
		 ANL   A,#80H
		 CJNE  A,#80H,PP2   ; 正号:79H<--#0
		 MOV   79H,#40H     ;负号: 79H<--#40H ("-")
PP2:     RET 
EXCH  : MOV     B,#10    ;将温度值由二进制数转化为三位十进制数
        DIV     AB
        MOV     7CH,B  ;   7AH存百位数
        MOV     B,#10
        DIV     AB
        MOV     7AH,A  ;   7BH存十位数
        MOV     A,B
        MOV     7BH,A 
        MOV     A,7CH   ;   7CH存个位数
        MOV     7CH,A
		MOV     7EH,#0AH  ;SAA1064显示"C"字
		MOV     7AH,#0BH  ;当用SAA1064显示时,(TAB+0AH)=#17H,
		RET                   ;#17H是SAA1064的控制命令COM
DEL0:   MOV R6,#0FH
TM:     MOV R7,#0FFH
        DJNZ R7,$
        DJNZ R6,TM
        RET
;长延时子程序
DELY:MOV R5,#0FFH
TTM1: LCALL DEL0
      DJNZ R5,TTM1
      RET
      END

⌨️ 快捷键说明

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