[转]在C中调用汇编写的ds18b20驱动代码

jackxiang 2008-12-26 11:25 | |
一个usb系统,其控制芯片的程序是C写的,现在想加入温度传感器,已有现成的汇编代码(伟纳ME300A+产品提供)


          TEMPL   DATA  26H
          TEMPH   DATA  27H

          FLAG1 EQU 38H  ;是否有ds18b20
          DATE_LINE EQU P3.6 ;接到ds18b20数据线引脚
;**************************************************
          ORG 0000H
MAIN:     MOV SP,#30H
START:    CALL RESET
          SETB P3.2
          CALL RESET
          JNB FLAG1,MAIN
          MOV A,#0CCH         ; 跳过ROM匹配
          CALL WRITE
          MOV A,#044H         ; 发出温度转换命令
          CALL WRITE
          CALL RESET
          MOV A,#0CCH         ; 跳过ROM匹配
          CALL WRITE
          MOV A,#0BEH         ; 发出读温度命令
          CALL WRITE
          CALL READ           ; 将读出的温度数据保存到26H/27H
          ;CALL CONVTEMP
          ;CALL DISPBCD
          ;CALL DISP1
          JMP MAIN
;*************************************************
RESET:  SETB DATE_LINE
        NOP
        CLR DATE_LINE
        MOV R0,#0D6H           ;主机发出延时642微秒的复位低脉冲
        MOV R1,#03H
TSR1:   DJNZ R0,$
        MOV R0,#0D6H
        DJNZ R1,TSR1
        SETB DATE_LINE        ;然后拉高数据线
        NOP
        NOP
        NOP
        MOV R0,#4AH
TSR2:   JNB DATE_LINE,TSR3   ;等待DS18B20回应
        DJNZ R0,TSR2
        JMP TSR4             ; 延时
TSR3:   SETB FLAG1           ; 置标志位,表示DS1820存在
        JMP TSR5
TSR4:   CLR FLAG1            ; 清标志位,表示DS1820不存在
        JMP TSR7
TSR5:   MOV R0,#06BH
TSR6:   DJNZ R0,$            ; 时序要求延时一段时间
TSR7:   SETB DATE_LINE
        RET
;********************************************************************
WRITE:  MOV R2,#8            ;一共8位数据
        CLR CY
WR1:
        CLR DATE_LINE        ;开始写入DS18B20总线要处于复位(低)状态
        MOV R3,#10
        DJNZ R3,$            ;总线复位保持16微妙以上
        RRC A                ;把一个字节DATA 分成8个BIT环移给C
        MOV DATE_LINE,C      ;写入一个BIT
        MOV R3,#2EH
        DJNZ R3,$            ;等待46微妙
        SETB DATE_LINE       ;重新释放总线
        NOP
        DJNZ R2,WR1          ;写入下一个BIT
        SETB DATE_LINE
        RET
;******************************************************
READ:    MOV R4,#2            ; 将温度高位和低位从DS18B20中读出
         MOV R1,#26H          ; 存入26H 27H
RE00:    MOV R2,#8
RE01:    CLR CY
         SETB DATE_LINE
         NOP
         NOP
         CLR DATE_LINE        ;读前总线保持为低
         NOP
         NOP
         NOP
         SETB DATE_LINE       ;开始读总线释放
         MOV R3,#18           ;延时18微妙
         DJNZ R3,$
         MOV C,DATE_LINE      ;从DS18B20总线读得一个BIT
         MOV R3,#46
         DJNZ R3,$            ;等待46微妙
         RRC A                ;把读得的位值环移给A
         DJNZ R2,RE01         ;读下一个BIT
         MOV @R1,A
         INC R1
         DJNZ R4,RE00
         RET

            END

代码就三个函数,reset,write,read。分别是没有参数和返回值、有参数没返回值、无参数有返回值。为了研究相应的C函数的结构,可以编译一个C程序看看


#pragma SRC
void ds18b20_reset()
{

}
void ds18b20_write( char sz)
{

}
int ds18b20_read(  )
{
int nTpr;
return nTpr;
}

用Keil 的c51编译

c51 test.c

可以得到一个TEST.SRC的文件
; thermometer.SRC generated from: thermometer.c
; COMPILER INVOKED BY:
;        D:\Keil\C51\BIN\c51.exe thermometer.c


NAME THERMOMETER

?PR?ds18b20_reset?THERMOMETER            SEGMENT CODE
?PR?_ds18b20_write?THERMOMETER           SEGMENT CODE
?DT?_ds18b20_write?THERMOMETER           SEGMENT DATA OVERLAYABLE
?PR?ds18b20_read?THERMOMETER             SEGMENT CODE
?DT?ds18b20_read?THERMOMETER             SEGMENT DATA OVERLAYABLE
PUBLIC ds18b20_read
PUBLIC _ds18b20_write
PUBLIC ds18b20_reset

RSEG  ?DT?ds18b20_read?THERMOMETER
?ds18b20_read?BYTE:
       nTpr?241:   DS   2

RSEG  ?DT?_ds18b20_write?THERMOMETER
?_ds18b20_write?BYTE:
         sz?140:   DS   1
; #pragma SRC
; void ds18b20_reset()

RSEG  ?PR?ds18b20_reset?THERMOMETER
ds18b20_reset:
   ; SOURCE LINE # 2
; {
   ; SOURCE LINE # 3
;  
; }
   ; SOURCE LINE # 5
RET  
; END OF ds18b20_reset

; void ds18b20_write( char sz)

RSEG  ?PR?_ds18b20_write?THERMOMETER
_ds18b20_write:
   ; SOURCE LINE # 6
MOV   sz?140,R7
; {
   ; SOURCE LINE # 7
;
; }
   ; SOURCE LINE # 9
RET  
; END OF _ds18b20_write

; int ds18b20_read(  )

RSEG  ?PR?ds18b20_read?THERMOMETER
ds18b20_read:
USING 0
   ; SOURCE LINE # 10
; {
   ; SOURCE LINE # 11
;  int nTpr;
;  return nTpr;
   ; SOURCE LINE # 13
MOV   R6,nTpr?241
MOV   R7,nTpr?241+01H
; }   ; SOURCE LINE # 14
?C0003:
RET  
; END OF ds18b20_read

END

其中write函数用下划线前缀做了修饰,表示函数将通过寄存器传递参数。

最后给出改造后可以用与c程序的ds18b20代码:

; thermometer.SRC generated from: thermometer.c
; COMPILER INVOKED BY:
;        D:\Keil\C51\BIN\c51.exe thermometer.c


NAME THERMOMETER

          DATE_LINE EQU P1.4 ;接到ds18b20数据线引脚

?PR?ds18b20_reset?THERMOMETER            SEGMENT CODE
?PR?_ds18b20_write?THERMOMETER           SEGMENT CODE
;?DT?_ds18b20_write?THERMOMETER           SEGMENT DATA OVERLAYABLE
?PR?ds18b20_read?THERMOMETER             SEGMENT CODE
?DT?ds18b20_read?THERMOMETER           SEGMENT DATA OVERLAYABLE
PUBLIC ds18b20_read
PUBLIC _ds18b20_write
PUBLIC ds18b20_reset

;RSEG  ?DT?_ds18b20_write?THERMOMETER
;?_ds18b20_write?BYTE:
;         sz?140:   DS   1

RSEG  ?DT?ds18b20_read?THERMOMETER
?ds18b20_read?BYTE:
       nTpr?241:   DS   2

; #pragma SRC
; void ds18b20_reset()

RSEG  ?PR?ds18b20_reset?THERMOMETER
ds18b20_reset:
   ; SOURCE LINE # 2
; {
SETB DATE_LINE
        NOP
        CLR DATE_LINE
        MOV R0,#0D6H           ;主机发出延时642微秒的复位低脉冲
        MOV R1,#03H
TSR1:   DJNZ R0,$
        MOV R0,#0D6H
        DJNZ R1,TSR1
        SETB DATE_LINE        ;然后拉高数据线
        NOP
        NOP
        NOP
        MOV R0,#4AH
TSR2:   JNB DATE_LINE,TSR3   ;等待DS18B20回应
        DJNZ R0,TSR2
        JMP TSR4             ; 延时
TSR3:   SETB c           ; 置标志位,表示DS1820存在
        JMP TSR5
TSR4:   CLR c            ; 清标志位,表示DS1820不存在
        JMP TSR7
TSR5:   MOV R0,#06BH
TSR6:   DJNZ R0,$            ; 时序要求延时一段时间
TSR7:   SETB DATE_LINE

;  
; }
   ; SOURCE LINE # 5
RET  
; END OF ds18b20_reset

; void ds18b20_write( char sz)

RSEG  ?PR?_ds18b20_write?THERMOMETER
_ds18b20_write:
   ; SOURCE LINE # 6
MOV   a,R7
; {
MOV R2,#8            ;一共8位数据
        CLR CY
WR1:
        CLR DATE_LINE        ;开始写入DS18B20总线要处于复位(低)状态
        MOV R3,#10
        DJNZ R3,$            ;总线复位保持16微妙以上
        RRC A                ;把一个字节DATA 分成8个BIT环移给C
        MOV DATE_LINE,C      ;写入一个BIT
        MOV R3,#2EH
        DJNZ R3,$            ;等待46微妙
        SETB DATE_LINE       ;重新释放总线
        NOP
        DJNZ R2,WR1          ;写入下一个BIT
        SETB DATE_LINE;
; }
   ; SOURCE LINE # 9
RET  
; END OF _ds18b20_write

; int ds18b20_read(  )

RSEG  ?PR?ds18b20_read?THERMOMETER
ds18b20_read:
USING 0
   ; SOURCE LINE # 10
; {
MOV R4,#2            ; 将温度高位和低位从DS18B20中读出
         MOV R1,#nTpr?241          ; 存入26H 27H
RE00:    MOV R2,#8
RE01:    CLR CY
         SETB DATE_LINE
         NOP
         NOP
         CLR DATE_LINE        ;读前总线保持为低
         NOP
         NOP
         NOP
         SETB DATE_LINE       ;开始读总线释放
         MOV R3,#18           ;延时18微妙
         DJNZ R3,$
         MOV C,DATE_LINE      ;从DS18B20总线读得一个BIT
         MOV R3,#46
         DJNZ R3,$            ;等待46微妙
         RRC A                ;把读得的位值环移给A
         DJNZ R2,RE01         ;读下一个BIT
         MOV @R1,A
         INC R1
         DJNZ R4,RE00;

MOV   R6,nTpr?241
MOV   R7,nTpr?241+01H
;}   ; SOURCE LINE # 13
RET  
; END OF ds18b20_read

END

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/1532/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!

评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]