找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3706|回复: 6
打印 上一主题 下一主题
收起左侧

单片机液位检测C语言,测量时 数据偏大 求大神帮忙矫正程序

[复制链接]
跳转到指定楼层
楼主
我是用的at89s52单片机,一个水位传感器,范围0~5mm和ADC0832数模转换芯片,进行液位测量时,测出的数据偏大而且大于3 的时候,结果保持在3.0.键盘是对预设值加减,有超限报警。实物图如下:






C语言程序如下,求大神矫正:
/**************************包含头文件*****************/
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
/******************端口定义****************************/
sbit CS=P3^5; //使能
sbit Clk=P2^1;//时钟
sbit DATO=P3^7; // 数据输出
sbit DATI=P3^6;//数据输入
sbit Buzzer=P2^0;
sbit SW1=P1^0;
sbit SW2=P1^1;
/******************定义全局变量****************************/
unsigned char dat=0x00;  //AD值
unsigned char count=0x00;   //定时器计数
unsigned char CH;     //通道变量
unsigned char dis[]={0x00,0x00,0x00};   //显示数值
unsigned Hmax;
bit Bjj(unsigned  Hmax);
/*************************共阳LED段码表*****************************/
unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};  //段码0-9
char code tablewe[]={0xdf,0xef,0xf7,0xfb};  // 位码P25-P22
/*******************************************************************
函数功能:AD转换子程序
入口参数:CH
出口参数:dat
*****************************************************/
unsigned char adc0832(uchar CH)
{
uchar i,test,adval;
adval=0x00;
test=0x00;
Clk=0;
DATI=1;
_nop_();
CS=0;
_nop_();
Clk=1;
_nop_();
if(CH==0x00)  //通道选择
{
  Clk=0;//1个下降沿DI=1
  DATI=1;  //通道0的第一位
_nop_();
  Clk=1;
  _nop_();
  Clk=0;
  DATI=0;  //通道0的第二位
  _nop_();
  Clk=1;
  _nop_();
}
else
{
  Clk=0;
  DATI=1;   //通道1的第一位
  _nop_();
  Clk=1;
  _nop_();
  Clk=0;
  DATI=1;  //通道1的第二位
  _nop_();
  Clk=1;
  _nop_();
}
Clk=0;
DATI=1;
for(i=0;i<8;i++)   //读取前8位的值
  {
   _nop_();
   adval<<=1;
   Clk=1;
   _nop_();
   Clk=0;
   if(DATO)
     adval|=0x01;
   else
     adval|=0x00;
   }
   for(i=0;i<8;i++)   //读取后8位的值
    {
     test>>=1;
     if(DATO)
        test|=0x80;
     else
         test|=0x00;
     _nop_();
     Clk=1;
     _nop_();
     Clk=0;
    }
    if(adval==test)    //比较前后8位的值,不同则舍去,若一直显示为0,请将改行去掉
       dat=test;
       _nop_();
       CS=1;     //释放ADC0832
       DATO=1;
       Clk=1;
       return dat;
}
/*********************************************************
函数功能:延时子程序
入口参数:
出口参数:
*********************************************************/
void delay(void)
{
   int k;
   for(k=10;k<500;k++);
}

/*********************************************************
函数功能:将0-255级换算成0.00-5.00的电压数值
入口参数:i
出口参数:
*********************************************************/
void convdata(uchar i)
{
   dis[0]=i/51;    //gewei
   dis[1]=(i%51)*10/51;  //小数点后1位
   dis[2]=((i%51)*10%51)*10%51; //小数点后2位
}

/*********************************************************
函数功能:数码管显示子程序
入口参数:
出口参数:
*********************************************************/
void display(void)
{
P2=0xff;
P0=tab[dis[0]]&0x7f;;    //显示个位和小数点
P2=0xef;
delay();

P0=tab[dis[1]];       //显示小数点后1位
P2=0xf7;
delay();

P0=tab[dis[2]];      //显示小数点后2位
P2=0xfb;
delay();

P0=tab[Hmax];
P2=0x7f;
delay();
}
/*********************************************************
函数功能:主函数
入口参数:
出口参数:
*********************************************************/
void main(void)
{
   P2=0xff;   //端口初始化
   P0=0xff;
   delay();
   CH=0x00;   //选择通道0或1
   Hmax=3; //上限值
   TMOD=0x01; //设置中断
   TH0=(65536-50000)/256; //定时器1初值定时50ms
   TL0=(65536-50000)%256;
   IE=0x82;
   TR0=1;
   while(1)   //主循环
   {
     dat=adc0832(CH);
     convdata(dat);   //数据转换
     display();       //显示数值
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:205345 发表于 2017-5-28 16:05 | 只看该作者
急求急求!
回复

使用道具 举报

板凳
ID:123289 发表于 2017-5-28 21:51 | 只看该作者
1、液位检测的原理是什么?
2、液位是如何围成电压信号的?
能说清楚以上两点,估计问题就解决得差不多了。
回复

使用道具 举报

地板
ID:205345 发表于 2017-5-29 12:43 | 只看该作者
yzwzfyz 发表于 2017-5-28 21:51
1、液位检测的原理是什么?
2、液位是如何围成电压信号的?
能说清楚以上两点,估计问题就解决得差不多了 ...

是一种简单易用的水位传感器,该传感器的工作原理是通过电路板上一系列裸露的印刷平行导线测量水量的大小。水量越多,就会有更多的导线被联通,随着导电的接触面积增大,输出的电压就会逐步上升。
但是实际检测的时候,刚测量ad转换得到的数据就有100了,最多也就180. 0~255的测量范围达不到。
所以我先测出整数位对应的数字量,然后分为五段了。虽然还是有偏差,但是整数位测出来比较准确了
回复

使用道具 举报

5#
ID:7485 发表于 2017-5-29 15:54 | 只看该作者
“      刚测量ad转换得到的数据就有100了,最多也就180. 0~255的测量范围达不到  ”是什么意思?
程序是自己写的吗?
许多这类的测量,传感器给出的信号一般不可能刚刚和和理想的结果相对应,往往是一个线性数值(有时仅仅是一个相关的曲线),需要通过程序用一个系数进行矫正。有时还要进行插值计算。
回复

使用道具 举报

6#
ID:205345 发表于 2017-5-29 18:26 | 只看该作者
ahshmj 发表于 2017-5-29 15:54
“      刚测量ad转换得到的数据就有100了,最多也就180. 0~255的测量范围达不到  ”是什么意思?
程序是 ...

我用的是ADC0832芯片,它是8位的,经过转换就是0~255.我又改了一下程序,虽然还是有误差,但是整数位测量的比较准确了
void convdata(uchar i)
{
/*  dis[0]=i/100; //gewei
   dis[1]=((i)%100)/10;  //小数点后1位
   dis[2]=((i)%100)%10; //小数点后2位*/      //AD转换值检测,测出整数位对应的8位数据
  
if((110<dat)&&(dat<=140))
  { dis[0]=(i-110)/30; //gewei
   dis[1]=((i-110)%30)*10/30;  //小数点后1位
   dis[2]=(((i-110)%50)*10%30)*10%30; //小数点后2位   //0~1mm
  }
  if((140<dat)&&(dat<=160))
  { dis[0]=((i-140)/20)+1; //gewei
   dis[1]=((i-140)%20)*10/20;  //小数点后1位
   dis[2]=(((i-140)%20)*10%18)*10%20; //小数点后2位   //1~2mm
  }
  if((160<dat)&&(dat<=170) )
  { dis[0]=((i-160)/10)+2; //gewei
   dis[1]=((i-160)%10)*10/10;  //小数点后1位
   dis[2]=(((i-160)%10)*10%6)*10%10; //小数点后2位    //2~3mm
}
    if((170<dat)&&(dat<=175))
  { dis[0]=((i-170)/5)+3; //gewei
   dis[1]=((i-170)%5)*10/5;  //小数点后1位
   dis[2]=(((i-170)%5)*10%5)*10%5; //小数点后2位       //3~4mm
}
    if((175<dat)&&(dat<=180))
  { dis[0]=((i-175)/5)+4; //gewei
   dis[1]=((i-175)%5)*10/5;  //小数点后1位
   dis[2]=(((i-175)%5)*10%5)*10%5; //小数点后2位        4~5mm
   }
}
回复

使用道具 举报

7#
ID:257481 发表于 2017-12-4 23:33 | 只看该作者
楼主来一份
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表