单片机DS18b20温度传感器汇编语言转c语言,求解!

lisazhou_EE   2009-6-22 10:41 楼主
本人单片机学的是汇编语言,做了DS18B20的实验,想通过这个实验学习下c语言开发,有汇编程序,请高手对照写个c语言程序,让本人学习一下,万分感谢!DS18B20单总线数字式温度传感器实验,实验连线时QD连P1.0,串并转换实验孔 DIN  P3.0, CLK P3.1,LED两位显示,汇编源程序如下:
;单总线读写操作
;温度传感器DS1820 的汇编程序
;一次数据传输为四步:初始化、传送ROM命令、传送RAM命令、数据交换
;当命令者检测到器件存在时首先发送1个ROM命令
;总线信号:初始化、写1、写0、读信号
TEMPER_L                 DATA         36H                                        ;温度寄存器的低位
TEMPER_H                 DATA        35H                                        ;温度寄存器的高位
TEMPER_NUM                 DATA         60H                                        ;保存温度值
FLAG                         BIT         00H                                        ;器件是否存在的标志位,器件存在由软件置1,否则清0
DQ                                 BIT         P1.0       
                                ORG                0000H
                                AJMP        START
;
;*****************************************************************************
;                                /*主程序*/                                                                                                         *
;*****************************************************************************               
;       
                                ORG                0030H
START:                         MOV         SP,#70H
                                CALL         GET_TEMPER                        ;读取温度值
                                CALL         TEMPER_COV                        ;读取转换后的温度值
                                MOV                R0,A
                                CALL        DISP
                                CALL        DELAY
                                AJMP        START
;
;*****************************************************************************
;                                /*取得温度子程序*/                                                                                         *
;*****************************************************************************
;
GET_TEMPER:                SETB         DQ
                                CALL        CHECK                                ;
                                MOV         A,#0CCH                         ; 跳过ROM匹配(当总线上只有一个器件时可跳过读ROM命令)
                                CALL         DSWRITE                                ; 写入命令
                                MOV         A,#44H                                 ; 发出温度转换命令
                                CALL         DSWRITE
                                NOP
                                CALL         DELAY
                                CALL         DELAY
                                CALL        CHECK       
                                MOV         A,#0CCH                         ; 跳过ROM匹配
                                CALL         DSWRITE       
                                MOV         A,#0BEH                         ; 发出读温度命令
                                CALL         DSWRITE
                                CALL         DSREAD                                ;读取温度的低位
                                MOV                R0,#TEMPER_L
                                MOV                @R0,A                                ;存入TEMPER_L
                                CALL        DSREAD                                ;读取温度的低位
                                DEC                R0                                        ;存入TEMPER_H
                                MOV                @R0,A
                                RET
;
;*****************************************************************************
;        /*读DS18B20的程序,从DS18B20中读出一个字节的数据*/                                                 *
;*****************************************************************************
;       
DSREAD:                        MOV         R2,#8
READ1:                        CLR         C
                                SETB         DQ
                                NOP
                                NOP
                                CLR         DQ
                                NOP
                                NOP
                                NOP
                                SETB         DQ
                                MOV         R3,#01
                                DJNZ         R3,$
                                MOV         C,DQ
                                MOV         R3,#23
                                DJNZ        R3,$
                                RRC         A
                                DJNZ         R2,READ1
                                RET
;
;*****************************************************************************
;                                /*写DS18B20序子程序*/                                                                             *
;*****************************************************************************               
;       
DSWRITE:                MOV         R2,#8
                                CLR         C
WRITE1:                        CLR         DQ
                                MOV         R3,#6                                ;延时12US
                                DJNZ         R3,$
                                RRC                A
                                MOV         DQ,C
                                MOV         R3,#23                                ;46US
                                DJNZ         R3,$
                                SETB         DQ
                                NOP
                                DJNZ         R2,WRITE1
                                SETB         DQ
                                RET
;
;*****************************************************************************
;                                /*温度转换程序*/                                                                                         *
;*****************************************************************************               
;       
TEMPER_COV:                MOV         A,#0F0H                       
                                ANL         A,TEMPER_L                         ; 舍去温度低位中小数点后的四位温度数值
                                SWAP         A
                                MOV         TEMPER_NUM,A
                                MOV         A,TEMPER_L
                                JNB         ACC.3,TEMPER_COV1        ; 四舍五入去温度值,
                                INC         TEMPER_NUM                        ;D3为1则加1,为0则舍去
TEMPER_COV1:        MOV         A,TEMPER_H                        ; 高位
                                ANL         A,#07H                                ;温度寄存器的高字节只有后3位有效
                                SWAP         A
                                ORL         A,TEMPER_NUM                ; 拼装
                                MOV         TEMPER_NUM,A                 ; 保存变换后的温度数据
                                CALL         BIN_BCD
                                RET
;       
;*****************************************************************************
;                                /*检查器件是否存在子程序*/                                                                         *
;*****************************************************************************               
;       
CHECK:                        CALL         DSINIT                                ; 初始化
                                JB                 FLAG,CHECK1                        ; 检查标志位判断器件是否存在
                                AJMP         CHECK                                 ; 若DS18B20不存在则继续检测
CHECK1:                        CALL         DELAY1
                                RET               
;               
;*****************************************************************************
;                                /*BCD码转换子程序*/                                                                                         *
;*****************************************************************************                       
;       
BIN_BCD:                MOV         DPTR,#TEMP_TAB
                                MOV         A,TEMPER_NUM
                                MOVC         A,@A+DPTR
                                MOV         TEMPER_NUM,A
                                RET
;                               
;*****************************************************************************
;                                /*初始化子程序程序*/
;初始化时序是由总线发出一个复位信号,然后由器件发                                                         *
;出一个应答信号,表示该器件存在,并准备好开始工作
;*****************************************************************************               
;
DSINIT:                        SETB         DQ
                                NOP
                                CLR         DQ                                        ;总线发一个复位信号
                                MOV         R0,#80H
                                DJNZ         R0,$                                ; 延时
                                SETB         DQ                                        ;拉高总线准备检测
                                MOV         R0,#25H                         ;延时
                                DJNZ         R0,$
                                JNB         DQ,INIT2                        ;检测是否有应答信号,有应答信号跳转
                                AJMP         INIT3                                 ; 延时
INIT2:                        SETB         FLAG                                 ; 置标志位,表示DS1820存在
                                AJMP         INIT4
INIT3:                        CLR         FLAG                                 ; 清标志位,表示DS1820不存在
                                AJMP         INIT5
INIT4:                        MOV         R0,#6BH                
                                DJNZ         R0,$                                ; 延时
INIT5:                        SETB         DQ                                        ;拉高总线
                                RET
;                               
;*****************************************************************************
;                                /*配置程序*/                                                                                                 *
;*****************************************************************************                       
;       
RE_CONFIG:                JB                 FLAG,RE_CONFIG1                ; 若DS18B20存在,转RE_CONFIG1
                                RET
RE_CONFIG1:                MOV         A,#0CCH                         ; 发SKIP ROM命令
                                CALL         DSWRITE
                                MOV         A,#4EH                                 ; 发写暂存存储器命令
                                CALL         DSWRITE
                                MOV         A,#00H                                 ; TH(报警上限)中写入00H
                                CALL         DSWRITE
                                MOV         A,#00H                                 ; TL(报警下限)中写入00H
                                CALL         DSWRITE       
                                MOV         A,#7FH                                 ; 选择12位温度分辨率
                                CALL        DSWRITE       
                                RET               
;               
;*****************************************************************************
;                                /*显示子程序*/                                                                                                 *
;*****************************************************************************
;
DISP:                        MOV                A,R0                                ;转换结果低位
                                ANL                A,#0FH
                                ACALL        DSEND                                ;显示
                                MOV                A,R0
                                SWAP        A
                                ANL                A,#0FH                                ;转换结果高位
                                ACALL        DSEND                                ;显示
                                RET
DSEND:                        MOV                DPTR,#SGTB1
                                MOVC        A,@A+DPTR                        ;取字符
                                MOV                SBUF,A
                                JNB                TI,$
                                CLR                TI               
                                RET
;       
;*****************************************************************************
;                                /*延时程序*/                                                                                                 *
;*****************************************************************************       
;               
DELAY:                        MOV                R7,#00H
DELAY0:                        MOV                R6,#00H
                                DJNZ        R6,$
                                DJNZ        R7,DELAY0
                                RET
DELAY1:                 MOV         R7,#20H                               
                                DJNZ         R7,$
                                RET
;       
;*****************************************************************************
;                                /*字符编码*/                                                                                                 *
;*****************************************************************************
;                               
SGTB1:                     DB             03H                         ;0
                                   DB             9FH                         ;1
                                   DB             25H                         ;2
                                  DB             0DH                         ;3
                                  DB             99H                          ;4
                                 DB             49H                          ;5
                                 DB             41H                          ;6
                                   DB             1FH                         ;7
                                   DB             01H                          ;8
                                   DB             09H                          ;9
                                   DB             11H                          ;A
                                   DB             0C1H                          ;B
                                   DB             63H                         ;C
                                   DB             85H                         ;D
                                  DB             61H                          ;E
                                   DB             71H                         ;F
                                   DB             00H                               
TEMP_TAB:                DB 00H,01H,02H,03H,04H,05H,06H,07H
                                DB 08H,09H,10H,11H,12H,13H,14H,15H
                                DB 16H,17H,18H,19H,20H,21H,22H,23H
                                DB 24H,25H,26H,27H,28H,29H,30H,31H
                                DB 32H,33H,34H,35H,36H,37H,38H,39H
                                DB 40H,41H,42H,43H,44H,45H,46H,47H
                                DB 48H,49H,50H,51H,52H,53H,54H,55H
                                DB 56H,57H,58H,59H,60H,61H,62H,63H
                                DB 64H,65H,66H,67H,68H,69H,70H,71H
                                DB 72H,73H,74H,75H,76H,77H,78H,79H
                                DB 80H,81H,82H,83H,84H,85H,86H,87H
                                DB 88H,89H,90H,91H,92H,93H,94H,95H
                                DB 96H,97H,98H,99H
                                END

回复评论 (19)

这可真是舍本求末

既然汇编是LZ写的,按流程用C重写比较好
点赞  2009-6-22 10:51
这正好是一个学习的好机会,

汇编已经写好了,那流程图应该没问题吧,

根据流程图,用C语言写,应该是很快的。
点赞  2009-6-22 10:54
关键问题是单片机下c怎么写,怎么控制都不清楚,c语言学的也不怎么好,还请各位写出个例子看下。
点赞  2009-6-22 10:57
1-Wire协议,GPIO模拟。

Google一下,好像很多这样的程序。
点赞  2009-6-22 12:12
可以一步一步的写吗,第一步,设置堆栈仍然放在汇编里,然后ljmp到main中,在main中

do{ xxxxxxxxxxxx } while( 1 );
点赞  2009-6-22 14:08
要的话我这里又写好的程序,在PROTUES中仿真过,还有温度报警上下限是在,如果要的话请发邮件到306146412@qq.com
点赞  2009-6-22 19:53
飘过
点赞  2009-6-22 22:43
这里是部分程序,希望对你有帮助!!!!!!!!!!!!!!!!要的话可以发邮件给我!!!!!!!!!


#include
#include


/****************************************************************************
函数功能:数码管显示子程序
入口参数:k
出口参数:
****************************************************************************/
void display(unsigned char k)                //参数传递进来时单精度被转化为unsigned char
{
        int s=(int)((temperature-k)*10);//取得temperature值的小数点后一位数字
        if(k>=0&&k<10)
        {
                led1=0;               //第一位数码管灭
                               
                P0=tabx[k%10];       //将温度值个位数显示在第二位数码管
        led2=1;
                delay(400);
        led2=0;

                                                        //将温度值小数点后一位数显示在第三位数码管
                P0=tab;                                        //显示小数点后一位
                led3=1;
                delay(400);
        led3=0;
        
                                                       
                P0=0xc6;             //第四位数码管显示字符"C",表示摄氏度℃
                led4=1;
                delay(400);
        led4=0;
        }
        else if(k<100&&k>=10)
        {                                       
                P0=tab[k/10];    //将温度值十位数显示在第一位数码管
                led1=1;
                delay(400);
        led1=0;

                                                       
                P0=tabx[k%10];  //将温度值个位数显示在第二位数码管
                led2=1;
                delay(400);
        led2=0;

                                               
                P0=tab;                //将温度值小数点后一位数显示在第三位数码管                       
                led3=1;
                delay(400);
        led3=0;
     
                                                       
                P0=0xc6;       //第四位数码管显示字符"C",表示摄氏度℃
                led4=1;
                delay(400);
        led4=0;

        }
        else                 //若超过测量范围,则数码管灭
        {
                led1=0;led2=0;led3=0;led4=0;
        }               
       
}

/****************************************************************************
函数功能:按键扫描程序
入口参数:                                             
出口参数:                                                 
****************************************************************************/
void button(void)
{
        if(k1==0)
        {
                blueled=0;                //除了ds18b20的工作灯(黄灯)亮之外,其余灯灭
                greenled=1;               
                RT_flag=1;                //启动温度读取与转换函数ReadTemperature()
                BZ_flag=1;                //启动蜂鸣器扫描函数speaker()
                ds18b20_flag=1;                //ds18b20标志位为1
                EX0=0;                        //关外部中断0
                EX1=0;                        //关外部中断1
        }
       
        else if(k2==0)
        {
                greenled=0;           //除了设置报警值时的状态灯(绿灯)亮之外,其余灯灭
                blueled=1;       
                RT_flag=0;
                BZ_flag=0;
                temperature=30.0;        //进入设置报警值时,初始显示30℃
                EX0=1;                                //开外部中断1
                EX1=1;                                //开外部中断1
        }
        else
                return;
}

/****************************************************************************
函数功能:蜂鸣器扫描程序
入口参数:B_flag                                             
出口参数:                                                 
****************************************************************************/
void speaker(unsigned char B_flag)
{
        if(B_flag)
        {
                if(temperature>TH)  
           {buzzer=0; redled=0; yellowled=1;} //温度大于上限值,启动蜂鸣器,红灯亮,报警
        else if(temperature            {buzzer=0; yellowled=0; redled=1;} //温度大于下限值,启动蜂鸣器,黄灯亮,报警
        else
           {buzzer=1; yellowled=1; redled=1;}
               
        }
        else
                return;          
}



/****************************************************************************
函数功能:DS18B20初始化子程序
入口参数:                                             
出口参数:                                                 
****************************************************************************/
void Init_DS18B20(void)
{
        unsigned char result_18b20;        //用来存储DQ的脉冲
        do{
        DQ=0;                                                 //拉低总线,发出复位脉冲
        delay_18b20(25);                         //延时530us
        DQ=1;                                                 //释放总线,等待ds18b20的应答脉冲
        delay_18b20(5);                                 //等待110us
        result_18b20=DQ;                         //读取ds18b20的应答脉冲
        delay_18b20(15);                         //等待周期结束
        }while(result_18b20==1);         //若ds18b20无应答,则继续发复位脉冲
}

/****************************************************************************
函数功能:向DS18B20读一字节数据
入口参数:
出口参数:dat
****************************************************************************/
unsigned char ReadOneChar(void)
{
        unsigned char i,j;
        unsigned char dat=0;
        for(i=8;i>0;i--)
        {
                  dat>>=1;                        //右移一位
                  DQ=0;                                 //拉低总线
                 for(j=2;j>0;j--);        //延时4us
                  DQ=1;                                //释放总线,以让DS18B20把数据传输到单总线上
                  for(j=4;j>0;j--);        //延时8us
                  if(DQ==1)                        //读取ds18b20发来的数据,从低位读起
                  dat|=0x80;                        //将读到的数据保存在d中
                  delay_18b20(2);                //延时等待读周期结束
                  DQ=1;
        }
          return(dat);                        //返回读到的数据
}

/****************************************************************************
函数功能:向DS18B20写一字节数据
入口参数:d
出口参数:
****************************************************************************/
void WriteOneChar(unsigned char dat)
{
   unsigned char i,j;
   for(i=8;i>0;i--)
   {
                DQ=0;                                //拉低总线
                for(j=2;j>0;j--);        //延时4us
                DQ=dat&0x01;                //主机在总线上写数据传送到ds18b20
                delay_18b20(3);                //延时等待写周期结束
                DQ=1;                                //重新将总线拉高
                  dat>>=1;                        //右移一位
   }
}

/****************************************************************************
函数功能:向DS18B20读温度值并转换成实际温度
入口参数:R_flag
出口参数:
****************************************************************************/
void ReadTemperature(unsigned char R_flag)
{
        if(R_flag==1)
        {
                unsigned char n;
                Init_DS18B20();                 //初始化ds18b20       
                WriteOneChar(0xcc);         //发送读指令跳过rom                       
                WriteOneChar(0x44);         //发送指令启动温度转换       
                Init_DS18B20();                 //初始化ds18b20       
                WriteOneChar(0x55);         //发送读指令匹配rom
                if(ds18b20_flag==1)                        //若K1键被按下,则选择ds18b20工作
                {
                        for(n=0;n<8;n++)  
                        WriteOneChar(id[n]);    //发送64 bit ID
                }
               
                WriteOneChar(0xbe);         //发送指令开始读取温度       
                tempL=ReadOneChar();         //读取温度值低位
                tempH=ReadOneChar();         //读取温度值高位
                Init_DS18B20();                 //再发送一次复位脉冲,终止温度的读取
                temperature=((tempH*256)+tempL)*0.0625;           //转换成实际温度
        }
        else
                return;
}                               
点赞  2009-6-23 19:38
建议LZ找本书,从最简单的学起会更好,这么长的汇编转成C语言后与不好看.
点赞  2009-7-1 10:22
好东西!可以参考啦1
点赞  2009-6-30 17:58
很有用的回答,正急需要。
点赞  2009-9-21 18:56
学习了
点赞  2009-9-22 21:05
网上找源代码,很多的啊
点赞  2009-9-30 19:42
我当初和LZ的情况一样,最后自己慢慢写几个c程序就会了,不难的~
点赞  2009-10-7 15:38
如果你要学c,找几个源码来读读就会了,再看看书,几天上手
点赞  2009-10-6 10:13
W
点赞  2009-10-14 09:43
我问一下 "ironshieh"这位朋友:
for(n=0;n <8;n++)  
WriteOneChar(id[n]);    //发送64 bit ID
这64位ID是指ds18b20中的什么呀?
最好把ID值列出来,谢谢.
点赞  2009-10-14 09:46
我也有代码 C语言很简单  有一个郭天祥的单片机C语言 视频教程 我建议你去看看 看了以后你就知道怎么样写了c语言的单片机了
点赞  2009-10-16 11:20
学习了,不错的帖子!谢谢各位了!
点赞  2009-12-14 18:26
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复