在.h里定义个DS18b20的引脚:
#define DQP33
extern u8MinusFlag ; //如果等于0 ,正数;等于1,负数
extern u32 Temp_18b20; //最终的温度,放大了10000倍
同时声明在.c里定义的2个变量是全局变量
@24.000MHz,480微秒
@24.000MHz,60微秒
@24.000MHz,1微秒
这么短的时间,用什么定时器,直接软件延时算啦!
接着我们写0:
//写逻辑0(输出0保持60us+,输出1保持1us+)
void DS18B20_Write_0(void)
{
DQ = 0;
Delay60us();
DQ = 1;
Delay1us();
Delay1us();
}
我们写0的意思的单片机向DS18B20写入逻辑0
写逻辑1和写0差不多:
//写逻辑1(输出0保持1us+,输出1保持60us+)
void DS18B20_Write_1(void)
{
DQ = 0;
Delay1us();
Delay1us();
DQ = 1;
Delay60us();
}
读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;
}
接着我们读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;
}
写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);
}
}
好了,基础底层函数都写好了,开始读温度:
//复位-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倍)
那么,读出来的温度,怎么显示在数码管上?
先写个函数:
void SEG_Show_U32(u32 num)
{
u8 i;
for(i=0;i<8;i++)
{
passward = num%10;
num /= 10;
}
}
我们先调用一下,把读到的温度值,写到数码管显示缓冲区数组!
这个放在主函数调用:
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}, //显示数码管
}
}
接着有个反复调试修改错误的过程
最终得到: