YangHY 发表于 2026-2-11 11:10:19

在.h里定义个DS18b20的引脚:

#define DQP33

extern u8MinusFlag ;                        //如果等于0 ,正数;等于1,负数
extern u32 Temp_18b20;                        //最终的温度,放大了10000倍

同时声明在.c里定义的2个变量是全局变量


@24.000MHz,480微秒

@24.000MHz,60微秒

@24.000MHz,1微秒

这么短的时间,用什么定时器,直接软件延时算啦!

YangHY 发表于 2026-2-11 11:24:17

接着我们写0:

//写逻辑0(输出0保持60us+,输出1保持1us+)
void DS18B20_Write_0(void)
{
      DQ = 0;
      Delay60us();
      DQ = 1;
      Delay1us();
      Delay1us();
}


我们写0的意思的单片机向DS18B20写入逻辑0

YangHY 发表于 2026-2-11 11:31:02

写逻辑1和写0差不多:

//写逻辑1(输出0保持1us+,输出1保持60us+)
void DS18B20_Write_1(void)
{
        DQ = 0;
        Delay1us();
        Delay1us();
        DQ = 1;
        Delay60us();
}

YangHY 发表于 2026-2-11 11:32:44

读0,读1 就有点不同,要返回值:

//读逻辑0/1(输出0保持1us+,输出1保持1us+,读取当前电平,延时60us)
bit DS18B20_Read(void)
{
        bit state = 0;
       
        DQ = 0;
        Delay1us();
        Delay1us();       
        DQ = 1;
        Delay1us();
        Delay1us();       
        state = DQ;                //暂时保存这个DQ的数值
        Delay60us();
       
        return state;
}

YangHY 发表于 2026-2-11 11:50:21

接着我们读1个字节:

/读1字节(先读到的是低位,后读到的是高位)
u8 DS18B20_ReadByte(void )
{
        u8 i;
        u8 dat=0;                                //数据暂存,
       
        for(i=0;i<8;i++)                //循环读取八次
        {
                dat >>= 1;
                if( DS18B20_Read() )        //如果读回来的是逻辑1   //0000 0000->1000 0000 -> 0100 0000
                {
                        dat |= 0x80;
                }
                else
                {
                }
        }
        return dat;
}

YangHY 发表于 2026-2-11 11:50:50

写1个字节:

//写1字节(先输出低位,在输出高位)
void DS18B20_WriteByte( u8 dat )
{
        u8 i;
        for(i=0;i<8;i++)
        {
                if( dat & 0x01 )        //最低位是1.发逻辑1电平
                {
                        DS18B20_Write_1();
                }
                else                                //否则.发逻辑0电平
                {
                        DS18B20_Write_0();
                }
                dat >>= 1;                        //dat = (dat>>1);
        }
}

YangHY 发表于 2026-2-11 12:06:50

好了,基础底层函数都写好了,开始读温度:

//复位-CCH-44H-等待-复位-CCH-BEH-读取2字节温度数据-换算)
void DS18B20_ReadTemp(void)
{
      u8 TempH = 0;
      u8 TempL = 0;
      u16 Temp = 0;
//---------------------发送检测命令---------------------      
      DS18B20_Reset();                        //1.发送复位命令
      DS18B20_WriteByte(0xcc);      //2.跳过ROM命令
      DS18B20_WriteByte(0x44);      //3.开始转化命令
      while( !DQ );                              //4.等待这个引脚变成高电平
      
//---------------------发送读取命令---------------------      
      DS18B20_Reset();                        //1.发送复位命令
      DS18B20_WriteByte(0xcc);      //2.跳过ROM命令
      DS18B20_WriteByte(0xBE);      //3.开始转化命令      
      TempL = DS18B20_ReadByte(); //读取低字节温度
      TempH = DS18B20_ReadByte(); //读取高字节温度      
      
      if( TempH & 0x80 )                        //如果最高位是1,这个就是负数
      {
                MinusFlag = 1;
                Temp = (((u16)TempH << 8) | ((u16)TempL << 0));
                Temp = (~Temp) +1;
                Temp_18b20 = (u32)Temp*625;   //最终的温度,放大了10000倍,就可以用整型变量
      }
      else
      {
                MinusFlag = 0;
                Temp = (((u16)TempH << 8) | ((u16)TempL << 0));
                Temp_18b20 = (u32)Temp*625;   //最终的温度,放大了10000倍,就可以用整型变量
      }
}

注意把浮点数改成32位整数的技巧,并且保证不会溢出(放大了10000倍)

YangHY 发表于 2026-2-11 12:41:01

那么,读出来的温度,怎么显示在数码管上?

先写个函数:

void SEG_Show_U32(u32 num)
{
        u8 i;
        for(i=0;i<8;i++)
        {
                passward = num%10;
                num /= 10;
        }
}

YangHY 发表于 2026-2-11 12:46:09

我们先调用一下,把读到的温度值,写到数码管显示缓冲区数组!

这个放在主函数调用:

void main(void)
{
        Sys_init();                                                                                //系统初始化
        usb_init();                                     //USB CDC 接口配置

    IE2 |= 0x80;                                    //使能USB中断
        Timer0_Init();                                                                        //定时器初始化
//        Init_595();
//        INT1_Init();                                                                        //外部中断1初始化
//        P3_IO_Init();                                                                        //IO中断初始化
//        P4_IO_Init();
       
        //TIM1_Count_Init();
        Timer1_Init();
       
    EA = 1;                                                                                        //IE |= 0X80;
       
        P40 = 0;
       
        while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置
//        WDT_CONTR = 0X24;
       
        while(1)
        {
               
      if (bUsbOutReady)                                                        //如果接收到了数据
      {
            //USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
                       
            usb_OUT_done();                                                        //
      }
                Task_Pro_Handler_Callback();                                //执行功能函数
               
                SEG_Show_U32(Temp_18b20);   //循环的把Temp_18b20的值写入passward,要来显示{0,1,   1,   SEG_Task},           //显示数码管

        }
}

YangHY 发表于 2026-2-11 12:55:30

接着有个反复调试修改错误的过程

最终得到:

页: 86 87 88 89 90 91 92 93 94 95 [96] 97 98 99 100 101 102 103 104
查看完整版本: 第一课 序言《AI8051U的特点》