四、例程(例程均为自己编写且验证通过)
/*****使用单片机为AT89C52;数值测量值用八段数码管显示;温度测量范围为-40.0~80.0摄氏度,湿度测量范围为0~99.9%;测量数据可精确到小数点后一位*****/
- #include<reg52.h>
- #include<intrins.h>
-
- typedef unsigned char uchar;
- typedef unsigned int uint;
-
-
- #define DELAY_TIME 5
-
-
- uchar value[5];
- uint temp,hum;
-
- sbit w1=P2^0;
- sbit w2=P2^1;
- sbit w3=P2^2;
- sbit w4=P2^3;
- sbit Bus=P2^4;
- //P3温度,P1湿度
-
- void Delay10us(void);//10us延时函数
- void Delay20us(void);//20us延时函数
- void Delay1ms(void);//1ms延时函数
- void Read_value(void);//读值子函数
- void Show(uint x,y);//显示子函数
-
-
-
- void main()
- {
- uint i;
- for(i=0;i<2000;i++)
- {
- Delay1ms();
- }
-
- Read_value();//读值
-
- hum=value[0]*256+value[1];//计算湿度值
- temp=(value[2]&0x7f)*256+value[3];//如果温度为负值,则&0x3f去掉符号位后再计算;若为正值则无影响
-
- Show(temp,hum);
- }
-
-
-
-
-
-
- /***********************10us延时函数*****************************/
- void Delay10us()
- {
- uchar i;
- i=2;
- while(--i);
-
- }
- /***********************20us延时函数*****************************/
- void Delay20us(void) //误差 0us
- {
- unsigned char a,b;
- for(b=3;b>0;b--)
- for(a=1;a>0;a--);
- }
-
-
-
- /***********************1ms延时函数*****************************/
- void Delay1ms() //误差 0us
- {
- unsigned char a,b,c;
- for(c=1;c>0;c--)
- for(b=142;b>0;b--)
- for(a=2;a>0;a--);
- }
- /************************读值函数******************************/
- void Read_value()
- {
- uchar i,j=0,mask;
- Bus=0;//主机拉低总线至少1ms(20ms)
- for(i=0;i<20;i++)
- {
- Delay1ms();
- }
- Bus=1;//主机主动拉高20us
- while(Bus);//等待从机拉低总线
- while(!Bus);//度过从机拉低时间
- while(Bus);//度过从机拉高时间
-
- while(j<5)
- {
- mask=0x80;
- for(i=0;i<8;i++)
- {
- while(!Bus);//度过数据位的低电平
- Delay20us();//延迟40us后进行电平检测
- Delay20us();
- if(Bus==0)
- {
- value[j]&=(~mask);
- }
- else
- {
- value[j]|=mask;
- }
- mask>>=1;
- while(Bus);//度过剩余高电平(如果是1的话)
- }
- j++;
- }
- }
-
-
-
- /**********************显示函数*************************************/
- void Show(uint x,y)
- {
- char duan1[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//段码
- char duan2[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
- while(1)
- {
- w1=1;//小数位
- w2=0;
- w3=0;
- w4=0;
- Delay10us();
- P3=duan1[x%10];
- P1=duan1[y%10];
- Delay1ms();
- P3=0xff;
- P1=0xff;
-
-
- w1=0;//个位
- w2=1;
- w3=0;
- w4=0;
- Delay10us();
- P3=duan2[(x/10)%10];
- P1=duan2[(y/10)%10];
- Delay1ms();
- P3=0xff;
- P1=0xff;
-
- w1=0;//十位
- w2=0;
- w3=1;
- w4=0;
- Delay10us();
- P3=duan1[(x/100)%10];
- P1=duan1[(y/100)%10];
- Delay1ms();
- P3=0xff;
- P1=0xff;
-
- w1=0;//百位
- w2=0;
- w3=0;
- w4=1;
- Delay10us();
- if(value[2]>127)//即温度最高位为1,表示负值
- {
- P3=0xbf;//显示负号
- }
- else
- {
- P3=duan1[(x/1000)%10];
- }
- P1=duan1[(y/1000)%10];
- Delay1ms();
- P3=0xff;
- P1=0xff;
- }
- }
注意:该例程在Proteus仿真中已验证通过。但在Proteus仿真中,即使温湿度值没有问题也存在校验错误的情况,因此在该例程中没有加校验函数。实际使用中,可通过判断value[4]是否等于value[0]+value[1]+value[2]+value[3]的方式进行校验,若相等则校验成功。
|