|
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
ADC用的TLC2543
单片机源程序如下:- #include <reg51.h>
- #include "lcd.h"
- #include "UART.h"
- #include "Delay.h"
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define ulong unsigned long
- #define NACK 0
- #define ACK 1
- #define MEASURE_TEMP 0x03 //000 0001 1
- #define MEASURE_HUMI 0x05 //000 0010 1
- #define STATUS_REG_W 0x06 //000 0011 0
- #define STATUS_REG_R 0x07 //000 0011 1
- #define RESET 0x1E //000 1111 0
- ulong volt;//测量的电压值
- sbit Data=P2^3; //定义数据线
- sbit CLK=P3^3;//定义时钟信号口
- sbit DIN=P3^4;//定义2543数据写入口
- sbit DOUT=P3^5;//定义2543数据读取口
- sbit CS=P3^2;//定义2543片选信号口
- sbit Data_P = P2^4; // SHT11传感器的数据管脚
- sbit Sck_P = P2^3; // SHT11传感器的时钟管脚
- sbit BEEP =P2^5;
- uchar tmpe,h;
- uchar rec_dat[9]; //用于显示的接收数据数组
- uchar temp_max = 50;
- ulong C2_max = 7500000;
- ulong LUX_max = 8500000;
- ulong C2_now = 0;
- ulong LUX_now = 0;
- unsigned char temp; // 保存温度
- unsigned char humi; // 保存湿度
- enum { TEMP,HUMI };
- typedef union //定义共用同类型
- {
- unsigned int i;
- float f;
- }value;
- int display = 0;
- void delay(uchar ms)
- { // 延时子程序
- uchar i;
- while(ms--)
- {
- for(i = 0;i<250;i++);
- }
- }
- char ShtWriteByte(unsigned char value)
- {
- unsigned char i,error=0;
- for(i=128;i>0;i>>=1) // 高位为1,循环右移
- {
- if (i&value)
- Data_P=1; // 和要发送的数相与,结果为发送的位
- else
- Data_P=0;
- Sck_P=1;
- _nop_(); // 延时3us
- _nop_();
- _nop_();
- Sck_P=0;
- }
- Data_P=1; // 释放数据线
- Sck_P=1;
- error=Data_P; // 检查应答信号,确认通讯正常
- _nop_();
- _nop_();
- _nop_();
- Sck_P=0;
- Data_P=1;
- return error; // error=1 通讯错误
- }
- char ShtReadByte(unsigned char ack)
- {
- unsigned char i,val=0;
- Data_P=1; // 释放数据线
- for(i=0x80;i>0;i>>=1) // 高位为1,循环右移
- {
- Sck_P=1;
- if(Data_P)
- val=(val|i); // 读一位数据线的值
- Sck_P=0;
- }
- Data_P=!ack; // 如果是校验,读取完后结束通讯
- Sck_P=1;
- _nop_(); // 延时3us
- _nop_();
- _nop_();
- Sck_P=0;
- _nop_();
- _nop_();
- _nop_();
- Data_P=1; // 释放数据线
- return val;
- }
- void ShtTransStart(void)
- {
- Data_P=1;
- Sck_P=0;
- _nop_();
- Sck_P=1;
- _nop_();
- Data_P=0;
- _nop_();
- Sck_P=0;
- _nop_();
- _nop_();
- _nop_();
- Sck_P=1;
- _nop_();
- Data_P=1;
- _nop_();
- Sck_P=0;
- }
- void ShtConnectReset(void)
- {
- unsigned char i;
- Data_P=1; //准备
- Sck_P=0;
- for(i=0;i<9;i++) //DATA保持高,SCK时钟触发9次,发送启动传输,通迅即复位
- {
- Sck_P=1;
- Sck_P=0;
- }
- ShtTransStart(); //启动传输
- }
- char ShtMeasure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
- {
- unsigned error=0;
- unsigned int i;
- ShtTransStart(); // 启动传输
- switch(mode) // 选择发送命令
- {
- case 1 : // 测量温度
- error+=ShtWriteByte(0x03);
- break;
- case 2 : // 测量湿度
- error+=ShtWriteByte(0x05);
- break;
- default:
- break;
- }
- for(i=0;i<65535;i++)
- if(Data_P==0)
- break; // 等待测量结束
- if(Data_P)
- error+=1; // 如果长时间数据线没有拉低,说明测量错误
- *(p_value) =ShtReadByte(1); // 读第一个字节,高字节 (MSB)
- *(p_value+1)=ShtReadByte(1); // 读第二个字节,低字节 (LSB)
- *p_checksum =ShtReadByte(0); // read CRC校验码
- return error; // error=1 通讯错误
- }
- void CalcSHT11(float *p_humidity ,float *p_temperature)
- {
- const float C1=-4.0; // 12位湿度精度 修正公式
- const float C2=+0.0405; // 12位湿度精度 修正公式
- const float C3=-0.0000028; // 12位湿度精度 修正公式
- const float T1=+0.01; // 14位温度精度 5V条件 修正公式
- const float T2=+0.00008; // 14位温度精度 5V条件 修正公式
- float rh=*p_humidity; // rh: 12位 湿度
- float t=*p_temperature; // t: 14位 温度
- float rh_lin; // rh_lin: 湿度 linear值
- float rh_true; // rh_true: 湿度 ture值
- float t_C; // t_C : 温度 ℃
- t_C=t*0.01 - 40; //补偿温度
- rh_lin=C3*rh*rh + C2*rh + C1; //相对湿度非线性补偿
- rh_true=(t_C-25)*(T1+T2*rh)+rh_lin; //相对湿度对于温度依赖性补偿
- *p_temperature=t_C; //返回温度结果
- *p_humidity=rh_true; //返回湿度结果
- }
- unsigned char TempCorrect(int temp)
- {
- if(temp<0) temp=0;
- if(temp>970) temp=970;
- if(temp>235) temp=temp+10;
- if(temp>555) temp=temp+10;
- if(temp>875) temp=temp+10;
- temp=(temp%1000)/10;
- return temp;
- }
- unsigned char HumiCorrect(unsigned int humi)
- {
- if(humi>999) humi=999;
- if((humi>490)&&(humi<951)) humi=humi-10;
- humi=(humi%1000)/10;
- return humi+4;
- }
- void ReadShtData()
- {
- value humi_val,temp_val; // 定义两个共同体,一个用于湿度,一个用于温度
- unsigned char error; // 用于检验是否出现错误
- unsigned char checksum; // CRC
- unsigned int temp1,humi1; // 临时读取到的温湿度数据
- error=0; //初始化error=0,即没有错误
- error+=ShtMeasure((unsigned char*)&temp_val.i,&checksum,1); //温度测量
- error+=ShtMeasure((unsigned char*)&humi_val.i,&checksum,2); //湿度测量
- if(error!=0) //如果发生错误,系统复位
- ShtConnectReset();
- else
- {
- humi_val.f=(float)humi_val.i; //转换为浮点数
- temp_val.f=(float)temp_val.i; //转换为浮点数
- CalcSHT11(&humi_val.f,&temp_val.f); //修正相对湿度及温度
- temp1=temp_val.f*10;
- temp=TempCorrect(temp1);
- humi1=humi_val.f*10-50;
- humi=HumiCorrect(humi1);
- humi1=humi1-1;
- }
- }
- void read2543(uchar addr)
- {
- uint ad=0;
- uchar i;
- CLK=0;
- CS=0;//片选段,启动2543
- addr<<=4;//对地址位预处理
- for(i=0;i<12;i++) //12个时钟走完,完成一次读取测量
- {
- if(DOUT==1)
- ad=ad|0x01;//单片机读取ad数据
- DIN=addr&0x80;//2543读取测量地址位
- CLK=1;
- ;;;//很短的延时
- CLK=0;//产生下降沿,产生时钟信号
- ;;;
- addr<<=1;
- ad<<=1;//将数据移位准备下一位的读写
- }
- CS=1;//关2543
- ad>>=1;
- volt=ad;//取走转换结果
- volt=volt*1221;//例子的满量程为5V,转换分辩率为12位(2的12次方=4096) 。即最大值是255,5/4096=1221mV,即例子中的1V代表实际1221mV
- }
- void main(void)
- {
- LcdInit();
- ShtConnectReset();
- UART_Init();
-
- while(1)
- {
- ReadShtData();
- DisplayListChar(4,0,"temp:");
- DisplayOneChar(10,0,(char)(temp/10+'0'));
- DisplayOneChar(11,0,(char)(temp%10+'0'));
- DisplayOneChar(12,0,(char)(' '));
- DisplayOneChar(13,0,(char)('C'));
- Uart1Send( 'T' );
- Uart1Send( (char)(temp/10+'0') );
- Uart1Send( (char)(temp%10+'0') );
-
- read2543(0);//调用2543驱动程序测量地址为
- LUX_now=volt*2;
- DisplayListChar(0,1,"ZD:");
- DisplayOneChar(3,1,(char)(volt*2/1000000+'0'));
- DisplayOneChar(4,1,(char)((volt*2/100000)%10+'0'));
- DisplayOneChar(6,1,(char)('%'));
- Uart1Send( 'Z' );
- Uart1Send( (char)(volt*2/1000000+'0') );
- Uart1Send( (char)((volt*2/100000)%10+'0') );
- read2543(1);//调用2543驱动程序测量地址为
- C2_now=volt*2;
- DisplayListChar(10,1,"PH:");
- DisplayOneChar(13,1,(char)(volt*2/1000000+'0'));
- DisplayOneChar(14,1,(char)('.'));
- DisplayOneChar(15,1,(char)((volt*2/100000)%10+'0'));
- Uart1Send( 'P' );
- Uart1Send( (char)(volt*2/1000000+'0') );
- Uart1Send( '.' );
- Uart1Send( (char)((volt*2/100000)%10+'0') );
-
- if(LUX_now>LUX_max || C2_now>C2_max || temp>temp_max)
- {
-
- BEEP=0;
- }else
- {
- BEEP=1;
- }
- }
- }
复制代码 下载:
|
-
-
软件.rar
73.95 KB, 下载次数: 23, 下载积分: 黑币 -5
-
-
硬件.rar
92.29 KB, 下载次数: 20, 下载积分: 黑币 -5
评分
-
查看全部评分
|