很久以前写的一个应用于51上面的多功能控制采集系统的..学习板内核程序


作者:李金浩

单片机:At89S52

连接类型:232 |485 接口

校验方式:checksum

开发环境:keil C


仅供参考学习,请勿用于商业开发.


/***************************************************************************************
 * 作者:李金浩                                                                         *
 * E-MAIL:LTSoft918@163.com                                                            *
 * QQ:67260745                                                                         *
 * 晶振:11.0592M   波特率:19200     At89S52                                           *
 *                                                                                     * 
 * 模块地址设定:由P0口设定,模块地址用于多机通信
 * =================================================================================== *
 *     0        1              2            3         4            5         6         *
 * |---------------------------------------------------------------------------------| *
 * |[操作符] | [port]|    [位号]       | [数据]  | 模块地址 |CheckSUM  |固定结束符   | *
 * |---------+-------+-----------------+---------+----------+----------+-------------| *
 * |错误:0xFF| XX    |        XX       |    XX   |    XX    |  XX      |    0x7e     | * 
 * |---------+-------+-----------------+---------+----------+----------+-------------| *
 * |写:0x01  | 0~3   | 0~7|8为完全数据 |  数据   |    XX    |  XX      |    0x7e     | *
 * |---------+-------+-----------------+---------+----------+----------+-------------| *
 * |读:0x02  | 0~3   | 0~7|8为完全数据 |    XX   |    XX    |  XX      |    0x7e     | *
 * |---------+-------+-----------------+---------+----------+----------+-------------| *
 * |EA:0x03  |  XX   |00:写 .. 01读取  | 00(01)  |    XX    |  XX      |    0x7e     | * 
 * |---------------------------------------------------------------------------------| *

 

 *==========================TLC1549数据采集============================================*
 *  ADCLK=P2^0                                                                         *
 *  ADOUT=P2^1                                                                         *
 *  ADCS=P2^2                                                                          *
 *     0        1              2            3         4            5         6         *
 * |---------------------------------------------------------------------------------| *
 * |[操作符] |采集次数 |      高位     |   低位  | 模块地址  | CheckSUM |固定结束符  | *
 * |---------+---------+---------------+---------+-----------+----------+------------| *
 * |AD:0x04  |  XX     |       XX      |    XX   |    XX     |   XX     |   0x7e     | *
 * |---------------------------------------------------------------------------------| *
 
                        GetAD_With_VOL_Filter:软件滤波采集
 *      0        1              2            3         4            5         6         *
 * |----------------------------------------------------------------------------------| *
 * |[操作符] |  空     |      高位     |   低位  | 模块地址  | CheckSUM | 固定结束符  | *
 * |---------+---------+---------------+---------+-----------+----------+-------------| *
 * |AD:0x05  |  XX     |       XX      |    XX   |    XX     |  XX      |    0x7e     | *
 * |----------------------------------------------------------------------------------| *

                            8路切换采集 ---CD4051_PickVol
   CD4051---8选1模拟开关芯片
   sbit CD4051_A=P1^1;
   sbit CD4051_B=P1^2;                                          
   sbit CD4051_C=P1^3; 
   sbit CD4051_INH=P1^4; //CD4051_INH为1时,,所有通导都不导通
 * |----------------------------------------------------------------------------------|
 * |     0        1              2            3         4            5         6      | *
 * |----------------------------------------------------------------------------------| *
 * |[操作符] |  选通编号 |      高位     |   低位  | 模块地址  | CheckSUM | 固定结束符| *
 * |---------+-----------+---------- ----+---------+-----------+----------+-----------| *
 * |AD:0x06  |  XX       |       XX      |    XX   |    XX     |  XX      |    0x7e   | *
 * |----------------------------------------------------------------------------------| *
                                 0x07:8路巡检采集CD4051_LoopPickVol
 * |----------------------------------------------------------------------------------|
 * |     0        1              2            3         4            5         6      | *
 * |----------------------------------------------------------------------------------| *
 * |[操作符] | 最大通道数|      高位     |   低位  | 模块地址  | CheckSUM | 固定结束符| *
 * |---------+-----------+---------- ----+---------+-----------+----------+-----------| *
 * |AD:0x07  |  XX       |       XX      |    XX   |    XX     |  XX      |    0x7e   | *
 * |----------------------------------------------------------------------------------| *
 *======================================================================================*
 
 
 *===============================AT24C04串行EEPROM操作==================================*
 *  sbit  SDA=P2^3;//SDA                                                                *
 *  sbit  SCL=P2^4;//SCL                                                                *
 *  sbit  WP=P2^5;//WP                                                                  *
 *      0        1              2            3         4            5         6         *
 * |----------------------------------------------------------------------------------| *
 * |[操作符] |  地址   |      数据     |  片地址 | 模块地址  | CheckSUM | 固定结束符  | *
 * |---------+---------+---------------+---------+-----------+----------+-------------| *
 * |读:0x08  |  XX     |       XX      |    XX   |    XX     |  XX      |    0x7e     | *
 * |---------+---------+---------------+---------+-----------+----------+-------------| *
 * |写:0x09  |  XX     |       XX      |    XX   |    XX     |  XX      |    0x7e     | *
 * |----------------------------------------------------------------------------------| *
 *======================================================================================*

 *===================================4位数码管理显示====================================*
 *                                 SetLedData()                                         *
 * P0.0-P0.3==》显示的数据发送至74ls47                                                  *
 * P0.4-P0.7==》数码管选择                                                              *
 * uchar LED_BIT[4]; //用于显示的每一位数据码的内容                             *
 * uchar LED_NUM[]={0x00,0x10,0x20,0x40,0x80};//选择显示位                      *
 *      0        1              2            3         4            5         6         *
 * |-----------------------------------------------------------------------------------|*
 * |[操作符] |  LEDNUM | 显示内容数据 | 开启/关闭 | 模块地址  | CheckSUM | 固定结束符  |*
 * |---------+---------+--------------+-----------+-----------+----------+-------------|*
 * |读:0x0A  |    XX   |       XX     |    XX     |    XX     |  XX      |    0x7e     |*
 * |---------+---------+--------------+-----------+-----------+----------+-------------|*
 * 开启/关闭===>0x00,关闭定时器中断                                                     * 
 *          ===>0x01,开启定时器中断                                                     *
 *======================================================================================*

 *==================================容量测试============================================*
 *                              TestCapCount()                                          *
 *电容充电控制:                                                                         *
 *     P0.0=1 断开                                                                      *
 *     P0.1=0 闭合                                                                      *
 *      0        1              2            3         4            5         6         *
 * |----------------------------------------------------------------------------------| *
 * |[操作符] |  数据位1   | 数据位2    | 数据位3 | 模块地址  | CheckSUM | 固定结束符  | *
 * |---------+------------+------------+---------+-----------+----------+-------------| *
 * | 0x0b    |    XX      |     XX     |   XX    |   XX      |   XX     |   0x7e      | *
 * |----------------------------------------------------------------------------------|
 *                                   {上位机下传指令}
   测量方式:0==>电量测方式   继电器自动开关
            1==>电压采集方式 继电器等到放电结完后才关      
 *      0        1              2            3         4            5         6         *
 * |-----------------------------------------------------------------------------------| *
 * |[操作符] | 测量方式   |充电延时倍数|  采集间隔| 模块地址  | CheckSUM | 固定结束符  | *
 * |---------+------------+------------+----------+-----------+----------+-------------| *
 * | 0x0b    |    XX      |     XX     |   XX     |   XX      |   XX     |   0x7e      | *
 * |-----------------------------------------------------------------------------------|
 ****************************************************************************************

 *                                   时序采集--{上位机下传指令}
                                     PluckPulse();
 *      0        1              2            3         4            5         6         *
 * |------------------------------------------------------------------------------------| *
 * |[操作符] | 定时器起动 |     TH0    |     TL0   | 模块地址  | CheckSUM | 固定结束符  | *
 * |---------+------------+------------+-----------+-----------+----------+-------------| *
 * | 0x0c    |    XX      |     XX     |     XX    |   XX      |   XX     |   0x7e      | *
 * |------------------------------------------------------------------------------------|
                                  
上传为无格式方式=====注意。。。。与现在的采集处理分开
 ****************************************************************************************

 *                                   PWM输出--{上位机下传指令}
                                     PWM(); P2_7口
 *      0        1              2            3         4            5         6         *
 * |------------------------------------------------------------------------------------| *
 * |[操作符] | 定时器起动 |    TH0     |   TL0     | 模块地址  | CheckSUM | 固定结束符  | *
 * |---------+------------+------------+-----------+-----------+----------+-------------| *
 * | 0x0d    |    XX      |     XX     |   XX      |   XX      |   XX     |   0x7e      | *
 * |------------------------------------------------------------------------------------|

 ****************************************************************************************


 *==========================未实现功能,网络接收模块选通 ===============================*
 * 2004-6-1                                                                             *
 *  当主机发送该指令时,下位如接收到的起始地址与自己相同,则进行相关操作                *
 *                      当操作完成后,将起始地址加1,指向下一个模块地址,发送            *
 *                      出去。其它模块接收到后重复先前的模块的作业...                   *
 *                      直到:起始地址=结束地址,则完成本次作业。                        *
 *                      起始地址与自己不同,则只接收不做其它操作。                       *
 * 该功能暂时未实际实行,假定中。。。。。HOHO...                                        *
 *      0        1              2            3         4            5         6         *
 * |----------------------------------------------------------------------------------| *
 * |[操作符] |  起始地址  | 结束地址   |   空位  | 模块地址  | CheckSUM | 固定结束符  | *
 * |---------+------------+------------+---------+-----------+----------+-------------| *
 * | 0x0e    |    XX      |     XX     |   XX    |   XX      |   XX     |   0x7e      | * 
 **************************************************************************************/

#include <stdio.h>
#include <REGX51.H>
#include "iic.h"

#define uchar unsigned char
#define uint  unsigned int

uint Timer_Pro_Flag=0;//0为显示处理,1为时序采集处理

sbit TEST_CAP_VOL_CRLT=P1^0;//用于控制外部继电器
sbit PWM_Pin=P3^7;//PWM输出
sbit IrDA_in_Pin=P1^0;//红外脉冲输入检测脚

bit PWMFlag=0;
uchar OLD_TH0,OLD_TL0;


#define MAXCMD_LENGTH 7

#define AD_VOL_PER 1.04058             //正常采集时的电压校准值
#define AD_Loop_PickVol_PER 1.04058 //CD4051循环采集时的电压校准值

sbit WDTRST=0xA6;//At89S5x看门狗寄存器
sbit ADCLK=P2^0;
sbit ADOUT=P2^1;
sbit ADCS=P2^2;
//--------------------------
/************CD4051---8选1模拟开关芯片*****************/
/*
|------------------------------------------------------|
|                       4 2 1        |
|-----------------------------------------------|------|
|端口  |           INH  C B A       |       |      |
|------/ 7 6 5 4 3 2 1 0   | 正值  | 取反 |
| 通道 |--------------------------------|-------|------|
|------|...............|8   4   2   1   |       |      |
|------|---------------|----------------|-------|------|
|  0   |0 0 0 0 0 0 0 0 | 0x00 | 0xff |
|  1   |0 0 0 0 0 0 1 0 | 0x02 | 0xf7 | 
|  2   |0 0 0 0 0 1 0 0 | 0x04 | 0xfb | 
|  3   |0 0 0 0 0 1 1 0 | 0x06 | 0xf3 | 
|  4   |0 0 0 0 1 0 0 0 | 0x08 | 0xfd |
|  5   |0 0 0 0 1 0 1 0 | 0x0A | 0xf8 |
|  6   |0 0 0 0 1 1 0 0 | 0x0C | 0xf9 |
|  7   |0 0 0 0 1 1 1 0 | 0x0e | 0xf1 |
|---------------------------------------|-------|------|

*/
uchar  CD4051_NUM[]={0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0e}; //0~7编码
sbit CD4051_A=P1^1;
sbit CD4051_B=P1^2;                                          
sbit CD4051_C=P1^3; 
sbit CD4051_INH=P1^4; //CD4051_INH为1时,,所有通导都不导通

bit CD4051_Vol_Conver_Flag=0; //0时为正常采集,1为CD4051循环采集
//--------------------------
//LED显示
//--------------------------
uchar LedCount=0;
uchar LED_BIT[5]; //用于显示的每一位数据码的内容
uchar LED_NUM[]={0x00,0x10,0x20,0x40,0x80};//选择显示位
//--------------------------------------------------------

void SendByte(unsigned char word)

 TI=0;
 SBUF=word;
 while(TI==0);
 TI=0;
}

uchar ComBuf[MAXCMD_LENGTH];//用于保存串口的数据

/*---少量延时---*/
void delay(uint t)
{
 uint i=0;
 for(;i<=t;i++);
}

void Pluckdelay(uint t)
{
 uint i=0,j;
 for(;i<=t;i++)
  for(j=1;j<=1000;j++);  
}
/*=================================
     ComBuf[5]加入CheckSUM校验码
  算法:0x01+not(字节1+字节2+...+字节N)
=================================*/
void SetCheckSUM()
{
  ComBuf[5]=0x01+~(ComBuf[0]+ComBuf[1]+ComBuf[2]+ComBuf[3]+ComBuf[4]);
}
/*=============================================================
     检测上位机发送来的ComBuf[5]checksum校验码和计算后的是否相等
  正确则返回:1
  错误则返回:0
==============================================================*/
 bit ISCheckSUM()
{
  uchar crc;
  crc=0x01+~(ComBuf[0]+ComBuf[1]+ComBuf[2]+ComBuf[3]+ComBuf[4]);
  if(ComBuf[5]==crc)
    return 1;
  else
  {
    ComBuf[1]=crc;//如果错误,则返回计算后得到的CHECKSUM校验码
    ComBuf[2]=ComBuf[5];//返回原来上位机发送来的CHECKSUM校验码
    return 0;
  }
}

/*-----------------------------------
 *                                   *
 *    等待接收上位机发来的指令       *
 *                                   *
-------------------------------------*/
void WaitComm()
{
    uchar n=0;
 RI=0;
 while (1)
    {
   while(!RI);//等接收数据
  //-----------------
      ComBuf[n]=SBUF;
      RI=0;
  //      SBUF=ComBuf[n]; 
  if (ComBuf[n]==0x7e) break;//接收到结束符则退出
  if (n>=MAXCMD_LENGTH)
        n=0;//接收10个字节,如果还没有接收到0x7e结束符,就重新记录
  else
     n++;
 }
}


/*-------------------------------
 *                               *
 *    发送combuf数据至上位机     *
 *                               *
 --------------------------------*/
void SendByteArray()
{
 unsigned i;
 SetCheckSUM();//加入ComBuf[5]的checkSUM校验码
 ComBuf[4]=P0;//取读本模块地址
 ComBuf[6]=0x7e;//结束符
 for(i=0;i<=MAXCMD_LENGTH-1;i++)
  {
   SendByte(ComBuf[i]);
  }
}

/*-------------------------------
 *                               *
 *        送端口状态至上位机     *
 *                               *
 --------------------------------*/
void GetP0()
{
  switch(ComBuf[2])
  {
   case 0x00: ComBuf[3]=P0_0; break;
   case 0x01: ComBuf[3]=P0_1; break;
   case 0x02: ComBuf[3]=P0_2; break;
   case 0x03: ComBuf[3]=P0_3; break;
   case 0x04: ComBuf[3]=P0_4; break;
   case 0x05: ComBuf[3]=P0_5; break;
   case 0x06: ComBuf[3]=P0_6; break;
   case 0x07: ComBuf[3]=P0_7; break;
   default:
    ComBuf[3]=P0;//为8时...则以上传整个port状态
  } 
}
//--------------------
void GetP1()
{
  switch(ComBuf[2])
  {
   case 0x00: ComBuf[3]=P1_0; break;
   case 0x01: ComBuf[3]=P1_1; break;
   case 0x02: ComBuf[3]=P1_2; break;
   case 0x03: ComBuf[3]=P1_3; break;
   case 0x04: ComBuf[3]=P1_4; break;
   case 0x05: ComBuf[3]=P1_5; break;
   case 0x06: ComBuf[3]=P1_6; break;
   case 0x07: ComBuf[3]=P1_7; break;
   default:
    ComBuf[3]=P1;//为8时...则以上传整个port状态
  } 
}
//---------------
void GetP2()
{
  switch(ComBuf[2])
  {
   case 0x00: ComBuf[3]=P2_0; break;
   case 0x01: ComBuf[3]=P2_1; break;
   case 0x02: ComBuf[3]=P2_2; break;
   case 0x03: ComBuf[3]=P2_3; break;
   case 0x04: ComBuf[3]=P2_4; break;
   case 0x05: ComBuf[3]=P2_5; break;
   case 0x06: ComBuf[3]=P2_6; break;
   case 0x07: ComBuf[3]=P2_7; break;
   default:
    ComBuf[3]=P2;//为8时...则以上传整个port状态
  } 
}
//--------------
void GetP3()
{
  switch(ComBuf[2])
  {
   case 0x00: ComBuf[3]=P3_0; break;
   case 0x01: ComBuf[3]=P3_1; break;
   case 0x02: ComBuf[3]=P3_2; break;
   case 0x03: ComBuf[3]=P3_3; break;
   case 0x04: ComBuf[3]=P3_4; break;
   case 0x05: ComBuf[3]=P3_5; break;
   case 0x06: ComBuf[3]=P3_6; break;
   case 0x07: ComBuf[3]=P3_7; break;
   default:
    ComBuf[3]=P3;//为8时...则以上传整个port状态
  } 
}
//-------发送AT89S5x的指定端口状态到上位机-----
void SendPortData()
{
    switch (ComBuf[1])/*Port号*/
    {
     case 0x00: GetP0(); break;
     case 0x01: GetP1(); break;
     case 0x02: GetP2(); break;
     case 0x03: GetP3(); break;           
    }

  /*--------------------*/
SendByteArray();//发送数据
}

 


/*-------------------------------
 *                               *
 *  各个端口的状态设定       *
 *                               *
 --------------------------------*/
void SetP0()
{
   switch(ComBuf[2])
    {
    case 0x00: P0_0=ComBuf[3]; break;
 case 0x01: P0_1=ComBuf[3]; break;
 case 0x02: P0_2=ComBuf[3]; break;
   case 0x03: P0_3=ComBuf[3]; break;
    case 0x04: P0_4=ComBuf[3]; break;
    case 0x05: P0_5=ComBuf[3]; break;
    case 0x06: P0_6=ComBuf[3]; break;
    case 0x07: P0_7=ComBuf[3]; break;
    default:
    P0=ComBuf[3];//为8时...则设置整个port状态
   }
}
//=================================
void SetP1()
{
   switch(ComBuf[2])
    {
    case 0x00:  P1_0=ComBuf[3]; break;
 case 0x01:  P1_1=ComBuf[3]; break;
 case 0x02: P1_2=ComBuf[3]; break;
   case 0x03: P1_3=ComBuf[3]; break;
    case 0x04: P1_4=ComBuf[3]; break;
    case 0x05: P1_5=ComBuf[3]; break;
    case 0x06: P1_6=ComBuf[3]; break;
    case 0x07: P1_7=ComBuf[3]; break;
    default:
    P1=ComBuf[3];//为8时...则设置整个port状态
   }
}
//=================================
void SetP2()
{
   switch(ComBuf[2])
    {
    case 0x00: P2_0=ComBuf[3]; break;
 case 0x01: P2_1=ComBuf[3]; break;
 case 0x02: P2_2=ComBuf[3]; break;
   case 0x03: P2_3=ComBuf[3]; break;
    case 0x04: P2_4=ComBuf[3]; break;
    case 0x05: P2_5=ComBuf[3]; break;
    case 0x06: P2_6=ComBuf[3]; break;
    case 0x07: P2_7=ComBuf[3]; break;
    default:
    P2=ComBuf[3];//为8时...则设置整个port状态
   }
}
//=================================
void SetP3()
{
   switch(ComBuf[2])
    {
    case 0x00: P3_0=ComBuf[3]; break;
 case 0x01: P3_1=ComBuf[3]; break;
 case 0x02: P3_2=ComBuf[3]; break;
   case 0x03: P3_3=ComBuf[3]; break;
    case 0x04: P3_4=ComBuf[3]; break;
    case 0x05: P3_5=ComBuf[3]; break;
    case 0x06: P3_6=ComBuf[3]; break;
    case 0x07: P3_7=ComBuf[3]; break;
    default:
    P3=ComBuf[3];//为8时...则设置整个port状态
   }
}

/*=================================
       WritePortData()

按上位机传来的格式进行端口的设置
=================================*/
void WritePortData()
{
 switch (ComBuf[1])/*Port号*/
    {
     case 0x00: SetP0(); break;
     case 0x01: SetP1(); break;
     case 0x02: SetP2(); break;
     case 0x03: SetP3(); break;           
    }
}

/*----------------------------------
 *           SetEA()                *
 *                                  *
 *    中断允许设定,(EA寄存器)       *
 *  ComBuf[1]==>0x00为EA设定        *
 *              0x01为读取EA值      *
------------------------------------*/
void SetEA()
{
 if (ComBuf[1]==0x00)
   EA=ComBuf[3];
 else
 {
   ComBuf[3]=EA;
   SendByteArray();//发送数据
 }
}


/*---------------------------------------------------------------
 *                                                             *
 *         float型转为2位char型,并发送至串行                   *
 *          void Convert_AD_VOL_ValueToChar()                  *    
 *                                                             *
---------------------------------------------------------------*/
void Convert_AD_VOL_ValueToChar(uint vol)
{
  float temp_float_vol;
  unsigned  int temp;
  uchar AD_Hight,AD_Low;

  temp_float_vol=vol*0.0048*AD_VOL_PER;
  temp=temp_float_vol*100;
  AD_Hight=temp /100;//取个位数
  AD_Low=temp-AD_Hight*100;//取2位小数
  ComBuf[2]=AD_Hight;
  ComBuf[3]=AD_Low;
  SendByteArray();//发送数据
}

/*--------------------------------
 *                                *
 *       预先采集一次AD数据       *
 *                                *
 *--------------------------------*/
void Befor_Once_AD()
{
  uchar i;

   ADCLK=ADOUT=0;
   //----------
   ADCS=0; //开启控制电路,使能DATA OUT和I/O CLOCK
  for(i=1;i<=10;i++)
  {
   ADCLK=1;
   ADCLK=0;
  }
  ADCS=1;
  delay(25);//两次转换间隔大于21us
}

/*---------------------------------------------------------------     
 *          GetAD()     TLC1549数据采集                          *
 *  sbit ADCLK=P2^0;                                             *
 *  sbit ADOUT=P2^1;                                             * 
 *  sbit ADCS=P2^2;                                              *  
-----------------------------------------------------------------*/
void GetAD()
{
 uchar i=1,w,PickCount;
 uint vol;

 Befor_Once_AD();//预先采集一次AD数据

//---------------

 if (ComBuf[1]==0)ComBuf[1]=0x01;
 PickCount=ComBuf[1];
 for(w=1;w<=PickCount;w++)
 {
   ADCLK=ADOUT=0;
   vol=0;
   ADCS=0; //开启控制电路,使能DATA OUT和I/O CLOCK
  for(i=1;i<=10;i++)
  {
  //给一个脉冲
    ADCLK=1;
    vol<<=1;
    if(ADOUT)vol|=0x01;
    ADCLK=0;
  }
  ADCS=1;
  delay(21);//两次转换间隔大于21us
  //---------------
  ComBuf[1]=w;//发送第几次采集的序号
  Convert_AD_VOL_ValueToChar(vol);//对float转为2位char型,并发送至串行口
  P2=0xff;//p2口置初始状态
 }
}

 

/*---------------------------------------------------------------
 *                                                               *
 *                     TLC1549数据软件滤波采集                   *
 *                                                               *
-----------------------------------------------------------------*/
void GetAD_With_VOL_Filter()
{
 uchar i,w,j,k,PickCount,AD_Hight=0,AD_Low=0;
 uint Vol=0,VolArray[10],temp;
 float SumVol=0;
 Befor_Once_AD();//预先采集一次AD数据
//---------------
//---------------
 PickCount=11;
 for(w=0;w<=PickCount;w++)
 {
   ADCLK=ADOUT=0;
   Vol=0;
   ADCS=0; //开启控制电路,使能DATA OUT和I/O CLOCK
  for(i=1;i<=10;i++)
  {
  //给一个脉冲
    ADCLK=1;
    Vol<<=1;
    if(ADOUT)Vol|=0x01;
    ADCLK=0;
  }
  ADCS=1;
  delay(21);//两次转换间隔大于21us
  VolArray[w]=Vol;//保存采集来的数据
 //---------------
  P2=0xff;//p2口置初始状态
 }
//-------按从小到大排序--------
//选择排序法..
 for(i=0;i<=PickCount-1;i++)
 {
   k=i;
   for(j=PickCount+1;j<i;j++)
   {
     if(VolArray[j]>VolArray[k])k=j;
     if(k!=i)
     {
       temp=VolArray[k];
       VolArray[k]=VolArray[i];
       VolArray[i]=temp;
     }   
   }
 }
//----------累加计算平静均值------------
//乎略最小和最大值
  for(i=1;i<=PickCount-1;i++)
  {
    SumVol=SumVol+VolArray[i];//累加结果
  }
  SumVol=SumVol/(PickCount-1)*0.0048;//电压值=平均值*介数
 /*------------------------------
  0时为正常采集,1为CD4051循环采集
  因为CD4051通道存在电压消耗,
  所以和正常的直接采集的校准值不一样
 -------------------------------*/
     /*电压校准比*/
if(CD4051_Vol_Conver_Flag)
  SumVol*=AD_Loop_PickVol_PER;//采用CD4051时的电压校准值
else
  SumVol*=AD_VOL_PER;//直接输入时的电压校准值

//----------------
  temp=SumVol*100;//保留2位小位
  AD_Hight=temp /100;//取个位数
  AD_Low=temp-AD_Hight*100;//取2位小数
//ComBuf[1]=w;//发送第几次采集的序号
  ComBuf[2]=AD_Hight;
  ComBuf[3]=AD_Low;
  SendByteArray();//发送数据
}

 

/*-------------------------------------------------------------------------*
 *                                                                        *
 *               CD4051_PickVol...8路选通TLC1549采集                       *   
 *                                                                         *
 *-------------------------------------------------------------------------*/
void CD4051_PickVol()
{
  CD4051_Vol_Conver_Flag=1;
  P1=CD4051_NUM[ComBuf[1]];//CD4051通道选通
 // delay(2300);//通道切换时间间隔,避免电路的残余电
  GetAD_With_VOL_Filter();
  CD4051_Vol_Conver_Flag=0;
}

/*-------------------------------------------------------------------------*
 *                                                                        *
 *               CD4051_LoopPickVol()...8路巡检TLC1549采集                 *   
 *                                                                         *
 *-------------------------------------------------------------------------*/
void CD4051_LoopPickVol()
{
  uchar i=0,w;
  w=ComBuf[1]-1;//通导号等于。。。通道数-1
  for(;i<=w;i++)
  {
    ComBuf[1]=i;//通道号
    CD4051_PickVol();
  }
 P1=0xff;//关闭通道
}


/*-------------------------------------------------------------------------*
 *                                                                        *
 *                   电容放电计数测试                                      *
 *                     TestCapCount()                                      *   
 *                                                                         *
 *-------------------------------------------------------------------------*/
void TestCapCount()
{

  uint Vol,TempVol=0xff,Count=0,temp1,temp2;
 uchar i,CAPDELAYTIME;
 float TEST_CAP_OUT_VALUE=0.05;
  P1=CD4051_NUM[1];//CD4051通道选通,1号通道
  TEST_CAP_VOL_CRLT=0;//打开电源
 if (ComBuf[1]==0x00)//为0x00时为电容测量方式,0x01为电压测量方式
 {
  for(i=0;i<=ComBuf[2];i++)delay(60000);//等待电容充电

   TEST_CAP_VOL_CRLT=1;//断开电源
   TEST_CAP_OUT_VALUE=0.01;//当为电容测量时。。下限电压
 } 
  CAPDELAYTIME=ComBuf[3];//延时常量
//--------------
  P1_1=0;//打开LED状态指示
 while(TempVol*0.0048*AD_VOL_PER>=TEST_CAP_OUT_VALUE)//当放电到0V时退出
 {
    ADCLK=ADOUT=0;
    Vol=0;
    ADCS=0; //开启控制电路,使能DATA OUT和I/O CLOCK
    for(i=1;i<=10;i++)
    {
    //给一个脉冲
      ADCLK=1;
      Vol<<=1;
      if(ADOUT)Vol|=0x01;
      ADCLK=0;
    }
    ADCS=1;
    delay(21);//两次转换间隔大于21us
   //---------------
    P2=0xff;//p2口置初始状态
    Count++;//计数
    ComBuf[0]=0x05;//利用软件滤波的处理过程显示
    if(Count>2)TempVol=Vol;//第一次的取值有可能是1,,去掉不要

    Convert_AD_VOL_ValueToChar(Vol);//转换并发送本次数据
    Pluckdelay(CAPDELAYTIME);//采集间隔时间,为ComBuf[4]*1000的时间常数
  }
//从高到低取
 P1=0xff;//初始P1口

 ComBuf[0]=0x0b;
 temp1=Count/1000;//取前1-2位
 ComBuf[1]=temp1;
 temp2=Count/10-temp1*100;//得到3-4位
 ComBuf[2]=temp2;
 ComBuf[3]=Count-(temp1*1000+temp2*10);
 SendByteArray();//发送数据
}
//--------------------------------------------------------------------------//

//写一个字节到AT24C04EEPROM
void WriteAT24C04()          
{
  uchar address,RomData;
  address=ComBuf[1];
  RomData=ComBuf[2];
  WriteByte_24c04(RomData,address);
}

//读取AT24C04EEPROM一个字节
void ReadAT24C04()
{
  ComBuf[2]=ReadByte_24c04(ComBuf[1]);
  SendByteArray();//发送数据
}

//=================================
//         看门狗设置
//=================================
//void watchdog()
//{
//WDTRST=0x1E;
//WDTRST=0xE1;//喂狗指令
//}


void SetLedData()
{
  uchar ShowData,ShowBit;
  Timer_Pro_Flag=0;//0为显示处理,1为时序采集处理
  ShowBit=ComBuf[1];
  ShowData=LED_NUM[ShowBit];//选择位
  ShowData|=ComBuf[2];//显示内容
  LED_BIT[ShowBit]=0x00;
  LED_BIT[ShowBit]=ShowData;
  TH0=(65536-4000)>>8;
  TL0=(65536-4000)&0xff;
  TR0=ComBuf[3];
  if(ComBuf[3]) P0=0x00;//关闭显示
}

/*=========================================
          PluckPulse----时序采集
===========================================*/
void PluckPulse()
{
  Timer_Pro_Flag=1;//0为显示处理,1为时序采集处理
  OLD_TH0=ComBuf[2];
  OLD_TL0=ComBuf[3];
  TH0=OLD_TH0;
  TL0=OLD_TL0;
  TR0=ComBuf[1];//关闭或启动计时器
}
//------------
/*=========================================
          PWM----时序采集
===========================================*/
void PWM()
{
  Timer_Pro_Flag=2;//0为显示处理,1为时序采集处理
  OLD_TH0=ComBuf[2];
  OLD_TL0=ComBuf[3];
  TH0=OLD_TH0;
  TL0=OLD_TL0;
  TR0=ComBuf[1];//关闭或启动计时器
}

//------------
void timer0(void) interrupt 1 using 1
{
//-------------------
 switch(Timer_Pro_Flag)
 {
 case 0:
        //LED显示处理
        TH0=(0xffff-4000)>>8;
        TL0=(0xffff-4000)&0xff;
 
        if (LedCount>4) LedCount=0;
        P0=0x00;
        P0=LED_BIT[LedCount++];
        break;
 case 1:
        // 时序采集
        TH0=OLD_TH0;
        TL0=OLD_TL0;
        SendByte(IrDA_in_Pin);//发送P1^0引脚状态
        break;
 case 2://模拟PWM输出
       if(!PWMFlag)
       {
         TH0=OLD_TH0;
         TL0=OLD_TL0;
         TR0=1;
         PWMFlag=1;
         PWM_Pin=0;
       }
       else
       {
         PWM_Pin=1;
         TR0=0;
         TH0=OLD_TH0;
         TL0=OLD_TL0;
         TR0=1;
         PWMFlag=0;
       }     
       break;
 }
}

 


/*===================================================================

                          主程序开始处
===================================================================*/
void main()
{
//晶振:11.0592,波特率:19200
 TMOD=0x21;
 TL1=0xfd;
 TH1=0xfd;
 SCON=0xd8;
 PCON=0x80;//高位为0时不倍频:9600pbf,1时倍频:19200bpf
 TR1=1;

//------------------
 // TMOD=0x01;//工作在定时器方式1,16位计数器
  TH0=(65536-4000)/256;
  TL0=(65536-4000)%256;
  ET0=1;
  EA=1;//中断允许
 //-------------

 while(1)
 {
  WaitComm();//等待接收数据
  //校对checksum校验码是否正确,如正确则进行相关的操作
  if(ISCheckSUM())
  {
    switch (ComBuf[0])
   {
     case 0x01:WritePortData(); break;       //响应上位机发送的写操作      
     case 0x02:SendPortData(); break;        //响应上位机发送的读操作     
     case 0x03:SetEA();break;                //中断允许设定              
     case 0x04:GetAD();break;                //TLC1549数据采集            
     case 0x05:GetAD_With_VOL_Filter();break;//采软件滤软件的TLC1549数据采集
     case 0x06:CD4051_PickVol();break;       //CD4051--8选1TLC1549采集
     case 0x07:CD4051_LoopPickVol();break;   //8路巡检TLC1549采集
     case 0x08:ReadAT24C04();break;          //读取AT24C04EEPROM一个字节
     case 0x09:WriteAT24C04();break;         //写一个字节到AT24C04EEPROM
     case 0x0a:SetLedData();break;           //设定显示的数据
     case 0x0b:TestCapCount();break;         //电容放电时间计数测试
     case 0x0c:PluckPulse();break;           //时序采集
     case 0x0d:PWM();break;                  //控制P2_7模拟输出PWM
    }
  }
  else//如检验错误则返回上位机错误信息
  {
    ComBuf[0]=0xFF;
    SendByteArray();//返回错误信息
  }
 }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lijinjie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值