本次设计采用TLC1543作为模数转换芯片,STC89C51系列单片机作为主控制器芯片,采集来自变送器(集成传感器)信号线端的电压(依据不同的传感器,可转换为相应的量值输出)。
采集到的数据可实现两种方式传输:1、通过Zigbee实现串口透传(无线传输)
2、串口(RS-232)传输(有线)。
软件平台:keil
本设计在8路模拟输入端(AI0~AI7)共地接入了250欧姆的精密电阻,可以采集到传感器的输出电压(0~5V),再通过欧姆定律,得到相应的输出电流。
根据单片机串口传输的字节要求,传输的数据格式设置为十六进制,并且为了得到较准确的电压输出,将电压放大10倍(考虑到十六进制转换为带小数的十进制较复杂。比如处理:实际输出电压为3.5V,处理后的为35V,对应的十六进制为23)。
为了区分采集到的每一路数据,在每路8位十六进制数据之后加上通道标志(8路分别是F0~F7),且数据每隔一秒钟(可修改)送至串口,通过有线或者无线的方式传输。
C语言代码如下:
1、main.c
#include <reg51.h>
#include "channel.h"
#include "math.h"
int Channel8_Data[8]={0,0,0,0,0,0,0,0};
uchar i,j,k,q;
uint t2;
uchar keyNum;
unsigned char datas[5] = {0, 0, 0, 0, 0};
void Display( int);
void delay(uint);
void flag(uint);
uchar Key_Scan();
void delay1ms(uint);
void UsartConfiguration(); //"串口通信初始化"
void main()
{
UsartConfiguration();
while(1)
{
// for(j=0;j<1;j++)
// {
// delay1ms(20);//"延迟200ms"
//Channel8_Data[j]=Ad_vldata(j);
int a=Ad_vldata(4);
// }
// for(i=0;i<8;i++)
// {
// switch(i)
// {
/* case(0):
if(port0==0)
{
//Display((Channel8_Data[0]*0.04098-4)*4.375-20);flag(0);delay1ms(1000);break; //"温度 没乘以100"
Display((Channel8_Data[0]*10.000));flag(0);delay1ms(1000);break; //"输出电流*10 4——>40"
}
else
break;
case(1):
if(port1==0)
{
//Display((Channel8_Data[1]*0.06944-4)*125); //"CO2"
Display((Channel8_Data[1]*0.04));flag(1);delay1ms(1000);break;
}
else
break;
*/
// case(1):
// if(port2==0)
// {
//Display((Channel8_Data[2]*0.04098-4)*0.0625); //"大气湿度"
// Display((Channel8_Data[0]*0.1));//flag(2);
Display(a);
//Channel8_Data[0]=0;
delay1ms(1000);//break;
// }
// else
// break;
/* case(3):
if(port3==0)
{
//Display((Channel8_Data[3]*0.04098-4)*0.0625); //"土壤湿度"
Display((Channel8_Data[3]*0.04));flag(3);delay1ms(1000);break;
}
else
break;
case(4):
if(port4==0)
{
//Display((Channel8_Data[4]*0.04098-4)*4.375-20); //"土壤温度"
Display((Channel8_Data[4]*0.04));flag(4);delay1ms(1000);break;
}
else
break;
case(5):
if(port5==0)
{
//Display((Channel8_Data[5]*0.04098-4)*937.5); //"盐分电导率"
Display((Channel8_Data[5]*0.04));flag(5);delay1ms(1000);break;
}
else
break;
case(6):
if(port6==0)
{
//Display((Channel8_Data[6]*0.04098-4)*12500);flag(6);delay1ms(1000);break; //"照度"
Display((Channel8_Data[6]*0.04));flag(6);delay1ms(1000);break;
}
else
break;
case(7):
if(port7==0)
{
//Display((Channel8_Data[7]*0.04098-4)*0.875);flag(7);delay1ms(1000);break; //"PH "
Display((Channel8_Data[7]*0.04));flag(7);delay1ms(1000);break;
}
else
break;
*/
//}
}
delay1ms(10000);
}
void delay1ms(uint y)
{
uint x;
for( ; y>0; y--)
{
for(x=110; x>0; x--);
}
}
void Scan_Switch()
{
}
void Display( int tt)
{
long int temp;
temp=tt+0.5;
/* if(temp< 0)
{
SBUF='-'; //"SBUF在左边,则为发送缓冲区"
while(!TI); //"等待发送完毕"
TI=0;
temp=temp-1; //"处理温度"
temp=~temp;
}
else
{
SBUF='+';
while(!TI);
TI=0;
}
*/
//"将转化好的温度分别放入数组中,并通过串口传输" //"temp传送过的值是实际值*100"
datas[0] = temp / 1000000;
datas[1] = temp % 1000000 / 100000;
datas[2] = temp % 100000 / 10000;
datas[3] = temp % 10000 / 1000;
datas[4] = temp % 1000 / 100;
//"小数点后2位"
datas[5] = temp % 100 / 10;
datas[6] = temp % 10;
SBUF = '0'+datas[0];
while (!TI);
TI = 0;
SBUF = '0'+datas[1];
while (!TI);
TI = 0;
SBUF = '0'+datas[2]; //"datas[2]为个位 '0'可用于温度补偿"
while (!TI);
TI = 0;
SBUF = '0'+datas[3];
while (!TI);
TI = 0;
SBUF = '0'+datas[4];
while (!TI);
TI = 0;
SBUF = '.';
while (!TI);
TI = 0;
SBUF = '0'+datas[5];
while (!TI);
TI = 0;
SBUF = '0'+datas[6];
while (!TI);
TI = 0;
/* t2=tt%100;
SBUF = t2;
while (!TI);
TI = 0;
SBUF = 255;
while (!TI);
TI = 0;
*/
}
void flag(uint l)
{
SBUF = 240+l;
while (!TI);
TI = 0;
}
void UsartConfiguration() //"串口和定时器初始化"
{
SCON=0X40;
TMOD=0X20;
PCON=0X00;
TH1=0XFD;
TL1=0XFD;
// ES=1;
// EA=1;
TR1=1; //"使能定时器1"
}
2、channel.c
#include <reg51.h>
#include "channel.h"
#include "intrins.h"
#include "math.h"
uint Ad_vldata(uchar port)
{
uint ad=0;
uint i;
uchar al=0,ah=0;
AD_clk=0;
AD_cs=0;
//"取高四位地址 "
port<<=4;
for(i=0;i<4;i++)
{
AD_add=(bit)(port&0x80); //"AD_add为AD地址寄存器"
AD_clk=1;
AD_clk=0;
port<<=1;
}
//"补全剩下的6个时钟周期"
for(i=0;i<6;i++)
{
AD_clk=1;
AD_clk=0;
//_nop_(); //???
}
//"10时钟周期完成地址的输送,下面直接采集数据即为当前值"
//"等待转换 "
AD_cs=1;
for(i=0;i<20;i++)
{
_nop_();
}
AD_cs=0;
_nop_();_nop_();_nop_();_nop_();
//_nop_();
//"获得测量的值"
for(i=0;i<2;i++)
{
AD_dat=1;
AD_clk=1;
ah<<=1;
if(AD_dat) ah|=0x01;
AD_clk=0;
}
for(i=0;i<8;i++)
{
AD_dat=1;
AD_clk=1;
al<<=1;
if(AD_dat) al|=0x01;
AD_clk=0;
}
//" 结束 "
AD_cs=1;
ad=(uint)ah;
ad<<=8;
ad|=(uint)al;
ad=(ad*0.004887)*100; //"(ad*0.004887)实际电压值,转化要*100,为了要测试输出电压"
// ad=ad*5/1024*100;
return(ad);
}
3.头文件部分代码
sbit AD_eoc=P3^7;
sbit AD_clk=P3^6;
sbit AD_add=P3^5; //D_IN
sbit AD_dat=P3^4; //D_OUT
sbit AD_cs=P3^3;
/*sbit port0=P1^0;
sbit port1=P1^1;
sbit port2=P1^2;
sbit port3=P1^3;
sbit port4=P1^4;
sbit port5=P1^5;
sbit port6=P1^6;
sbit port7=P1^7;
*/