|
- /*********************************************
- //程序功能:使用温度传感器DS18B20测量环境温度
- //接线方式:数码管的段选信号接I/O口的P0
- P0^0~P0^7对应A~G DP
- 位选为P2^0~P2^3对应SL3-SL0
- DS18B20接P2^7
- //作 者:吴超
- //日 期:2014/7/28
- **********************************************/
- #include <reg51.h>
- #include <intrins.h>
- typedef unsigned char uchar;
- typedef unsigned int uint;
- #define Disdata P0
- #define discan P2
- sbit DQ = P2^7; //DS18B20的输入输出端口
- sbit DIN = P0^7; //小数点的位置
- sfr P0M0 =0x94;
- sfr P0M1 =0x93; //P0端口设置推挽输出的地址
- uint h;
- uint temp; //温度值
- /**************温度小数部分用查表法***********/
- uchar code ditab[16]=
- {0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
- //数码管段选信号
- uchar code dis_7[12]={
- 0x3F, //"0"的字形表,0B00111111
- 0x06, //"1"的字形表,0B00000110
- 0x5B, //"2"的字形表,0B01011011
- 0x4F, //"3"的字形表,0B01001111
- 0x66, //"4"的字形表,0B01100110
- 0x6D, //"5"的字形表,0B01101101
- 0x7D, //"6"的字形表,0B01111101
- 0x07, //"7"的字形表,0B00000111
- 0x7F, //"8"的字形表,0B01111111
- 0x6F, //"9"的字形表,0B01101111
- 0x00, // 全灭消隐
- 0x40, //"-"的字形表,0B01000000
- };
-
- uchar code scan_con[4]={0xFE,0xFD,0xFB,0xF7}; //列扫描控制字
- uchar data temp_data[2]={0x00,0x00}; //读出温度暂放
- uchar data display[5]={0x00,0x00,0x00,0x00,0x00}; //显示单元数据,共4个数据和一个运算暂用
- /***********************************************************************
- //函数名称:delay(uint t)
- //函数功能:延时程序 1*t us 系统时钟工作在12MHZ下,机器周期为1/12 us
- _nop_()运行所需要时间为1个机器周期。do while函数占1个机器周期
- t--占1个机器周期,10个_nop_()占10机器周期,共占12个机器周期
- //入口参数:所要延时的时间 t t=n 就延时n us
- //返回参数:无
- ***********************************************************************/
- void delay(uint t)
- {
- do{
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();
- }while(t--);
- }
- /*********************************************************************
- //函数名称:scan()
- //函数功能:动态扫描显示温度值
- //入口参数:无
- //返回参数:无
- *********************************************************************/
- void scan()
- {
- char k;
- for(k=0;k<4;k++)
- {
- Disdata = dis_7[display[k]]; //选择温度值,段选
- if(k == 1)
- DIN = 1; //点亮小数点
- discan = scan_con[k]; //列扫描
- delay(300); //延时300us
- }
- }
- /************************************************************
- //函数名称:ow_reset(void)
- //函数功能:温度控制器复位。控制器Tx的复位脉冲的时间区间为480us~960us
-
- //入口参数:无
- //返回参数:无
- ************************************************************/
- void ow_reset(void)
- {
- char presence=1;
- while(presence)
- {
- while(presence)
- {
- DQ=1;delay(8); //从高拉倒低
- DQ=0;
- delay(550); //复位脉冲的时间区间在480us~960us之间,本次延时550 us,进入DS18B20等待时间15~60us
- DQ=1;
- delay(66); //66 us 进入存在脉冲
- presence=DQ; //presence=0 复位成功,继续下一步
- }
- delay(500); //延时500 us
- presence=~DQ;
- }
- DQ=1; //拉高电平
- }
- /*写命令程序*/
- void write_byte(uchar val)
- {
- uchar i;
- for(i=8;i>0;i--)
- {
- DQ=1;delay(2); //从高拉倒低
- DQ=0;delay(5); //5 us
- DQ=val&0x01; //最低位移出
- delay(66); //66 us
- val=val/2; //右移1位
- }
- DQ=1;
- delay(11); //延时11us
- }
- //
- /****************DS18B20读1字节函数************************/
- //从总线上取1个字节
- uchar read_byte(void)
- {
- uchar i;
- uchar value=0;
- DQ=1;
- delay(1); //延时 1us
- for(i=8;i>0;i--)
- {
- DQ=1;
- delay(2);
- value>>=1;
- DQ=0;delay(4); //4 us
- DQ=1;delay(4); //4 us
- if(DQ)
- value|=0x80;
- delay(66); //66 us
- }
- DQ=1;
- return value;
- }
- /****************读出温度函数************************/
- uint read_temp()
- {
- ow_reset(); //总线复位
- delay(2000);
- write_byte(0xcc); //发命令
- write_byte(0x44); //发转换命令
- ow_reset();
- delay(11);
- write_byte(0xcc); //发命令
- write_byte(0xbe);
- temp_data[0]=read_byte(); //读温度值的低字节
- temp_data[1]=read_byte(); //读温度值的高字节
- temp=temp_data[1];
- temp<<=8;
- temp=temp|temp_data[0]; // 两字节合成一个整型变量。
- return temp; //返回温度值
- }
- //
- /****************温度数据处理函数************************/
- //二进制高字节的低半字节和低字节的高半字节组成一字节,这个
- //字节的二进制转换为十进制后,就是温度值的百、十、个位值,而剩
- //下的低字节的低半字节转化成十进制后,就是温度值的小数部分
- /********************************************************/
- void work_temp(uint tem)
- {
- uchar n=0;
- if(tem>6348) // 温度值正负判断
- {
- tem=65536-tem;
- n=1; // 负温度求补码,标志位置1
- }
- display[4]=tem&0x0f; // 取小数部分的值
- display[0]=ditab[display[4]]; // 存入小数部分显示值
- display[4]=tem>>4; // 取中间八位,即整数部分的值
- display[3]=display[4]/100; // 取百位数据暂存
- display[1]=display[4]%100; // 取后两位数据暂存
- display[2]=display[1]/10; // 取十位数据暂存
- display[1]=display[1]%10; // 去个位数据暂存
- /******************符号位显示判断**************************/
- if(!display[3])
- {
- display[3]=0x0a; //最高位为0时不显示
- if(!display[2])
- {
- display[2]=0x0a; //次高位为0时不显示
- }
- }
- if(n)
- {
- display[3]=0x0b; //负温度时最高位显示"-"
- }
- }
- /****************主函数************************/
- void main()
- {
- P0M1 = 0x00;
- P0M0 = 0xFF; //P0端口设置成推挽输出
- Disdata=0x00; //初始化端口
- discan=0x00;
- for(h=0;h<4;h++) //开机显示"00.00"
- {
- display[h] = 0;
- }
- ow_reset(); //开机先转换一次
- write_byte(0xcc); //Skip ROM
- write_byte(0x44); //发转换命令
- for(h=0;h<100;h++) //开机显示"00.00"
- {
- scan();
- }
- while(1)
- {
- work_temp(read_temp()); //处理温度数据
- scan(); //显示温度值
- }
- }
复制代码
|
|