[求助] 单片机程序出错wenduji123.asm(211): error A45: UNDEFINED SYMBOL (PASS-2) 求指教

hanqiankun   2013-12-4 18:59 楼主
TEMP1  EQU  5AH        ; 符号位和百位公用的存放单元
    TEMP2  EQU  5BH        ; 十位存放单元
    TEMP3  EQU  5CH        ; 个位存放单元
    TEMP4  EQU  5DH        ;
    TEMP5  EQU  5EH
    TEMP6  EQU  5FH        ; 数据临时存放单元
    TEMP7  EQU  60H
    TEMP8  EQU  61H
    ORG  0000H
    AJMP  MAIN
    ORG  0020H
MAIN:
    MOV  SP,#70H     
    LCALL  INT             ; 调用DS18B20初始化函数
MAIN1:
    LCALL  GET_TEMP      ; 调用温度转换函数
    LCALL  CHULI          ; 调用温度计算函数
    LCALL  DISP            ; 调用温度显示函数
    AJMP  MAIN1           ; 循环
    INT:
L0:
    SETB  P3.7              ; 先释放DQ总线
    MOV  R2,#250           ; 给R2赋延时初值,同时可让DQ保持高电平2us
L1:
    CLR  P3.7               ; 给DQ一个复位低电平
    DJNZ  R2,L1            ; 保持低电平的时间至少为480us
    SETB  P3.7              ; 再次拉高DQ释放总线
    MOV  R2,#25      
L2:
    DJNZ   R2,L2            ; 保持15us-60us
    CLR  C
    ORL  C,P3.7              ; 判断是否收到低脉冲
    JC  L0
    MOV  R6,#100
L3:
    ORL  C,P3.7             
    DJNZ  R6,L3              ; 存在低脉冲保持保持60us-240us
    JC  L0                    ; 否则继续从头开始,继续判断
    SETB  P3.7  
    RET                       ; 调用温度转换函数
    GET_TEMP:
    CLR  PSW.4
    SETB  PSW.3              ; 设置工作寄存器当前所在的区域
    CLR  EA                ; 使用DS18B20前一定要禁止任何中断
    LCALL  INT             ; 初始化DS18B20
    MOV  A,#0CCH          ; 送入跳过ROM命令
    LCALL  WRITE
    MOV  A,#44H            ; 送入温度转换命令
    LCALL  WRITE
    LCALL  INT             ; 温度转换完成,再次初始化18b20
    MOV  A,#0CCH          ; 送入跳过ROM命令
    LCALL  WRITE
    MOV  A,#0BEH          ; 送入读温度暂存器命令
    LCALL  WRITE
    LCALL  READ   
    MOV  TEMP4,A          ; 读出温度的低字节存在TEMP4
    LCALL  READ
    MOV  TEMP5,A          ; 读出温度的高字节存在TEMP5
    SETB  EA
    RET
    CHULI : MOV  A,TEMP5    ; 将温度的高字节取出
JNB  ACC.7,ZHENG        ; 判断最高位是否为0,为0则表示温度为正,则转到ZHENG
    MOV  A,TEMP4            ; 否则温度为负,将温度的低字节取出
    CPL  A                    ; 求反
    INC  A                    ; 加1
    MOV  TEMP8,A            ; 存到TEMP8中
    ANL  A,#0FH              ; 保留低四位
    LCALL  MULD            ; 调用乘以625子程序
    LCALL  HB2              ; 调用双字节16进制数转换成BCD码子程序
    MOV  A,R4               ; 将结果的千位百位取出
    ANL  A,#0F0H             ; 保留千位
    SWAP  A                  ;
    MOV  TEMP7,A            ; 把小数结果保存在TEMP7中
    MOV  A,TEMP4            ; 再次取出温度的低字节
    ANL  A,#0FFH             ; 判断是否为0
    JZ  XX                    ; 为0则转到XX执行
    MOV  A,TEMP5            ;
    CPL  A                    ; 不为0则直接将温度的高字节取反
    SJMP  YY              
XX:
    MOV  A,TEMP5        ; 为0则求补码
    CPL  A                    ;
    INC  A                    ;
YY:
    ANL  A,#0FH           ; 保留高字节的低四位
    SWAP  A                   ; 将其换到高4位
    MOV  R5,A                 ; 暂时保存于R5中
    MOV  A,TEMP8             ; 取出求反后的低位字节
    ANL  A,#0F0H              ; 取其高4位
    SWAP  A                   ; 将其换到低4位
    ORL  A,R5                  ; 合并成温度的整数部分
    MOV  TEMP6,A             ; 将整数部分存到TEMP6中
    LCALL  HBCD              ; 调用一字节的16进制数转换BCD数的子程序
    MOV  TEMP1,#0BH          ; 将"-"号的段选值存到符号位
    MOV  A,TEMP2             ; 取出十位
    CJNE  A,#00H,NEXT   
    MOV  TEMP2,#0CH          ; 十位为0不显示
    RET              
    ZHENG:  MOV  A,TEMP4    ; 将温度的低字节取出
    ANL  A,#0FH                ; 保留低四位
    LCALL  MULD              ; 调用乘以625子程序
    LCALL  HB2                ; 调用双字节16进制数转换成BCD码子程序
    MOV  A,R4                 ; 将结果的千位百位取出
    ANL  A,#0F0H               ; 保留千位
    SWAP  A                    ;
    MOV  TEMP7,A             ; 把小数结果保存在TEMP7中
    MOV  A,TEMP4             ; 再次取出温度的低字节
    ANL  A,#0F0H               ; 保留高4位
    SWAP  A                    ; 换到低4位
    MOV  R5,A                  ; 暂时保存于R5中
    MOV  A,TEMP5             ; 取出温度的高字节
    ANL  A,#0FH                ; 保留低4位
    SWAP  A                    ; 换到高4位
    ORL  A,R5                  ; 合并成温度的整数部分
    MOV  TEMP6,A              ; 整数部分存到TEMP6中
    LCALL  HBCD               ; 单字节的16进制数转换成BCD码
    MOV  A,TEMP1              ; 取出百位
    CJNE  A,#00H,NEXT          ; 百位不为0则转NEXT
    MOV  TEMP1,#0CH           ; 为0则不显
    MOV  A,TEMP2              ; 取出十位
    CJNE  A,#00H,NEXT   
    MOV  TEMP2,#0CH           ; 十位为0也不显
    NEXT:  RET                  ; 小数部分乘以625转换子程序
    MULD:
    MOV  B,#71H
    MUL  AB
    MOV  R7,A
    MOV  R6,B   
    MOV  B,#02H
    MUL  AB
    ADD  A,R6
    MOV  R6,A
    RET                          ; 写字节到18b20子程序
    WRITE:                          
    MOV  R3,#8                  ; 一个字节共8位
    WR1:  SETB P3.7             ; 先释放总线
    MOV  R4,#8
    RRC  A                     ; 把要写的字节的最低位右环移到C中
    CLR  P3.7                   ; 写开始
WR3:
    DJNZ R4,WR3          ; 保持低电平0-15us,等待
    MOV  P3.7,C                 ; 将C中的位写到DQ总线上
    MOV  R4,#20        
    DJNZ  R4,$                   ; 18b20在15us-60us期间对DQ总线进行采样
    DJNZ  R3,WR1               ; 判断8位是否写完,没完则继续写下一位
    RET                         ; 从18b20里读取一个字节子程序
    READ:                     
    MOV  R6,#8                  ; 一个字节有8位
RE1:
    SETB P3.7                ; 先释放总线
    NOP
    CLR  P3.7                    ; 拉低总线,读前总线保持为低
    NOP                          ; 保持1-2us
    MOV  R4,#4                  ; 设置读时间隙
    SETB  P3.7                   ; 读开始
RE2:
    DJNZ R4,RE2            ; 产生读时间隙
    MOV  C,P3.7                 ; 将总线上的位读到C
    MOV  R5,#30                 ;
    DJNZ  R5,$                   ; 持续60us
    RRC  A                      ; 将C里的位右环移到A里
    DJNZ  R6,RE1                ; 读下一位
    SETB  P3.7
    RET                          ; 单字节16进制数转换成BCD码子程序
HBCD:
    MOV  A,TEMP6
    MOV  B,#10
    DIV   AB
    MOV  TEMP3,B               ; 将个位存到TEMP3
    MOV  B,#10        
    DIV  AB
    MOV  TEMP2,B               ; 将十位存到TEMP2
    MOV  TEMP1,A               ; 将百位存到TEMP1
    RET                          ; 双字节的16进制数转换成BCD码子程序
HB2:
    CLR  A
    MOV  R3,A
    MOV  R4,A
    MOV  R5,A
    MOV  R2,#10H
HB3:
    MOV  A,R7
    RLC  A
    MOV  R7,A
    MOV  A,R6
    RLC  A
    MOV  R6,A
    MOV  A,R5
    ADDC  A,R5
    DA  A
    MOV  R5,A
    MOV  A,R4
    ADDC  A,R4
    DA  A
    MOV  R4,A
    MOV  A,R3
    ADDC  A,R3
    MOV  R3,A
    DJNZ  R2,HB3
    RET                                ; 显示子程序
DISP:
    MOV  DPTR,#DISPTAB
    MOV  R0,#4
DP1:
    MOV  R1,#140
LOOP:
    MOV  A,TEMP7             ; 取出小数部分
    MOVC  A,@A+DPTR                ; 取出相应的字型码
    MOV  P1,A                         ; 显示在数码管上
    SETB  P3.0                         ; 数码管位选
    ACALL  DELAY100                 ; 延时
    CLR  P3.0                          ; 清数码管位选
    MOV  A,TEMP3                     ; 取个位
    MOVC  A,@A+DPTR      
    ANL  A,#7FH                        ; 显示小数点
    MOV  P1,A       
    SETB  P3.1
    ACALL DELAY100
    CLR  P3.1
    MOV  A,TEMP2                      ; 取十位
    MOVC  A,@A+DPTR
    MOV  P1,A
    SETB  P3.2
    ACALL  DELAY100
    CLR  P3.2
    MOV  A,TEMP1                       ; 取符号位或百位
    MOVC  A,@A+DPTR
    MOV  P1,A
    SETB  P3.3
    ACALL  DELAY100
    CLR  P3.3
    DJNZ  R1,LOOP                      ; 循环显示
    DJNZ  R0,DP1
    RET
DELAY100:
    MOV R7,#180              ; 延时
    DJNZ R7,$
    RET
DISPTAB:
    DB  0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH,0BFH,0FFH
    END

回复评论 (1)

程序中的标点符号要拼音模式下的。
点赞  2013-12-4 21:19
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复