DS18B20测温显示,proteus仿真。
Written by jinsongliang
具体程序如下
Main.c:
#include #include"lib51v3.c" #include"18b20.c" #include"segv3.c" void main (void) { unsigned char disp[5]={10,0,0,14,2}; signed char temp=0; while(1) { /*1、读取温度值*/ temp=Get_Temputer(); //2、显示前处理*/ if(temp<0) {disp[0]=13; temp=-temp; disp[1]=temp/10; disp[2]=temp%10; } else {disp[0]=temp/100; disp[1]=temp/10-disp[0]*10; disp[2]=temp%10; if(!disp[0]) //百位数不为0则显示,若要显示0,可将其注释掉 disp[0]=10; } //3、显示*/ Seg_Display(disp); } } Lib51v3.c void Delay_Nus (unsigned char n) { while(n--); //for (;n>0;n--); } 18b20.c: /****************************************************************** 时序很重要,移植时注意延时函数 ******************************************************************/ #define B20_PORT P1 //此处可以设置I/O口 #define B20_CHANNEL 0 #define R_B20_CHANNEL() B20_PORT&(1< #define TEMPUTER_CONVERT 0x44 #define READ_ROM 0xBE //one /* 初始化函数,失败会返回1,初始化过程见注释 若单片机读到了数据线上的低电平“0”后,还要做延时, 其延时的时间从单片机发出的高电平算起最少要480微秒。 之后单片机将数据线再次拉高到高电平“1”后结束。 */ static unsigned char Init_18b20 (void) { unsigned char x=0; W_B20_CHANNEL_1(); //1、从单片机拉高数据线开始 Delay_Nus(8); //6*n useconds lib51v3.c W_B20_CHANNEL_0(); Delay_Nus(81); W_B20_CHANNEL_1(); //2、单片机拉低数据线480us以上,拉高数据线,释放 Delay_Nus(14); //3、之后ds18b20,15~60us以后反应,拉高数据线 x=R_B20_CHANNEL(); //4、单片机读取数据线 if(x) return x; Delay_Nus(20); return x; //x=0代表复位成功 } //two static void Write_18b20(unsigned char w_data) { unsigned char i; unsigned char temp; for(i=0;i<8;i++) { W_B20_CHANNEL_1(); temp=w_data&(1<<0); W_B20_CHANNEL_0(); //单片机从高到低,拉低1us以上,并在15us内产生写间隙 B20_PORT=temp< w_data>>=1; } W_B20_CHANNEL_1(); Delay_Nus(4); } //three static unsigned char Read_18b20(void) { unsigned char i; unsigned char temp; unsigned char r_data=0x00; for(i=0;i<8;i++) { r_data>>=1; W_B20_CHANNEL_1(); W_B20_CHANNEL_0(); //从高到低15us内,再到高,产生读间隙 Delay_Nus(1); W_B20_CHANNEL_1(); temp=B20_PORT<<(7-B20_CHANNEL); //读数据,从低位开始 temp&=(1<<7); r_data+=temp; Delay_Nus(8); //整个读一位过程在60~120us } W_B20_CHANNEL_1(); return r_data; } //four /* 若要读出当前的温度数据我们需要执行两次工作周期, 第一个周期为复位、跳过ROM指令、执行温度转换存储器操作指令、等待500uS温度转换时间。 紧接着执行第二个周期为复位、跳过ROM指令、执行读RAM的存储器操作指令、读数据 (最多为9个字节,中途可停止,只读简单温度值则读前2个字节即可) */ signed char Get_Temputer (void)//读取温度值,返回的带符号字符型-55到+127;128无法显示,初始化失败会显示00.C { unsigned char tem_h,tem_l; signed char temp; if(Init_18b20()==0) //复位18b20 { Write_18b20(SKIP_ROM); //跳过ROM Write_18b20(TEMPUTER_CONVERT); //温度变换 } else return temp=0; //Delay_Nus(100); if(Init_18b20()==0) //复位18b20 { Write_18b20(SKIP_ROM); //跳过ROM Write_18b20(READ_ROM); //读暂存存储器 } else return temp=0; tem_l=Read_18b20(); //读数据 tem_h=Read_18b20(); /* 只要高字符的低四位和低字符的高四位,温度范围0~99,temp为补码,直接由unsigned char 赋值给 signed char 内容不变,代表的值改变 */ temp=(tem_h<<4)+(tem_l>>4); return temp; } Segv3.c: #define COMMON_ANODIC 0 //共阳数码管 #define COMMON_CATHODAL 1 //共阴数码管 #define SEG_CATEGORY 0 //选择共阳数码管 #define SEG8_A ~(1<<0) //段A亮时为0,属共阳数码管 #define SEG8_B ~(1<<1) #define SEG8_C ~(1<<2) #define SEG8_D ~(1<<3) #define SEG8_E ~(1<<4) #define SEG8_F ~(1<<5) #define SEG8_G ~(1<<6) #define SEG8_DP ~(1<<7) #define SEG8_CHAR_0 ~(SEG8_G&SEG8_DP) #define SEG8_CHAR_1 ~(SEG8_A&SEG8_D&SEG8_E&SEG8_F&SEG8_G&SEG8_DP) #define SEG8_CHAR_2 ~(SEG8_C&SEG8_F&SEG8_DP) #define SEG8_CHAR_3 ~(SEG8_E&SEG8_F&SEG8_DP) #define SEG8_CHAR_4 ~(SEG8_A&SEG8_D&SEG8_E&SEG8_DP) #define SEG8_CHAR_5 ~(SEG8_B&SEG8_E&SEG8_DP) #define SEG8_CHAR_6 ~(SEG8_B&SEG8_DP) #define SEG8_CHAR_7 ~(SEG8_D&SEG8_E&SEG8_F&SEG8_G&SEG8_DP) #define SEG8_CHAR_8 ~SEG8_DP #define SEG8_CHAR_9 ~(SEG8_E&SEG8_DP) #define SEG8_CHAR_ ~0 #define SEG8_CHAR_E ~(SEG8_B&SEG8_C&SEG8_DP) #define SEG8_CHAR_R ~(SEG8_A&SEG8_B&SEG8_C&SEG8_D&SEG8_F&SEG8_DP) #define SEG8_CHAR_SUB ~(SEG8_A&SEG8_B&SEG8_C&SEG8_D&SEG8_E&SEG8_F&SEG8_DP) //#define SEG8_CHAR_A //#define SEG8_CHAR_B #define SEG8_CHAR_C ~(SEG8_B&SEG8_C&SEG8_G&SEG8_DP) //#define SEG8_CHAR_D //#define SEG8_CHAR_F //#define SEG8_CHAR_H #if SEG_CATEGORY==COMMON_ANODIC static const unsigned char SEG8_CODE[]={ SEG8_CHAR_0, SEG8_CHAR_1, SEG8_CHAR_2, SEG8_CHAR_3, SEG8_CHAR_4, SEG8_CHAR_5, SEG8_CHAR_6, SEG8_CHAR_7, SEG8_CHAR_8, SEG8_CHAR_9, SEG8_CHAR_, //SEG8_CODE[10] SEG8_CHAR_E, //SEG8_CODE[11] SEG8_CHAR_R, //SEG8_CODE[12] SEG8_CHAR_SUB, //SEG8_CODE[13] SEG8_CHAR_C //SEG8_CODE[14] }; #else static const unsigned char SEG8_CODE[]={ ~SEG8_CHAR_0, ~SEG8_CHAR_1, ~SEG8_CHAR_2, ~SEG8_CHAR_3, ~SEG8_CHAR_4, ~SEG8_CHAR_5, ~SEG8_CHAR_6, ~SEG8_CHAR_7, ~SEG8_CHAR_8, ~SEG8_CHAR_9, ~SEG8_CHAR_, //SEG8_CODE[10] ~SEG8_CHAR_E, //SEG8_CODE[11] ~SEG8_CHAR_R, //SEG8_CODE[12] ~SEG8_CHAR_SUB, //SEG8_CODE[13] ~SEG8_CHAR_C //SEG8_CODE[14] }; #endif #define SEG8_SLECT_PORT P3 //此处可以设置I/O口 #define BIT0 0 #define BIT1 1 #define BIT2 2 #define BIT3 3 #define SEG8_BIT0_ON() SEG8_SLECT_PORT|=(1< void Seg_Display (char *p) { unsigned char temp[4]; temp[0]=SEG8_CODE[*p++]; temp[1]=SEG8_CODE[*p++]; temp[2]=SEG8_CODE[*p++]; temp[3]=SEG8_CODE[*p++]; if(*p<4) #if SEG_CATEGORY==COMMON_ANODIC temp[*p]&=SEG8_DP; #else temp[*p]|=~SEG8_DP; #endif { unsigned char i; for(i=0;i<150;i++) { SEG8_CODE_PORT = temp[0]; SEG8_BIT0_ON(); Delay_Nus(6); //lib51v1.c SEG8_BIT0_OFF(); SEG8_CODE_PORT = temp[1]; SEG8_BIT1_ON(); Delay_Nus(6); SEG8_BIT1_OFF(); SEG8_CODE_PORT = temp[2]; SEG8_BIT2_ON(); Delay_Nus(6); SEG8_BIT2_OFF(); SEG8_CODE_PORT = temp[3]; SEG8_BIT3_ON(); Delay_Nus(6); SEG8_BIT3_OFF(); } } }下载本文