找回密码
 立即注册
查看: 880|回复: 0

基于STC15W408AS单片机10位AD采集0~10V电压数码管显示报警电路及程序分享

[复制链接]

该用户从未签到

42

主题

7

回帖

246

积分

中级会员

积分
246
发表于 2023-6-28 00:41:26 | 显示全部楼层 |阅读模式

功能说明:输入一个模拟量0-10V的电压 ,通过按键设置报警阈值,
数码管显示实时电压,当输入电压大于设定电压时,继电器吸合,
小于设定值时,继电器断开

GYJ-0298 淘宝描述_01.jpg

GYJ-0298 淘宝描述_02.jpg

GYJ-0298 淘宝描述_04.jpg

GYJ-0298 淘宝描述_05.jpg

GYJ-0298 淘宝描述_07.jpg

GYJ-0298 淘宝描述_08.jpg

GYJ-0298 淘宝描述_13.jpg


【声明】此程序仅用于学习与参考!     


*********************************************************************/
/********************************************************************
                            宏定义
*********************************************************************/
#include<STC15W408AS.h>                 //库文件
#include<intrins.h>
#define uchar unsigned char//宏定义无符号字符型
#define uint unsigned int  //宏定义无符号整型
#define ADC_POWER   0x80            //ADC 电源控制位
#define ADC_FLAG    0x10            //ADC 转换结束标志位
#define ADC_START   0x08            //ADC 开始转换控制位
#define ADC_SPEEDLL 0x00            //210 个时钟周期转换一次
#define ADC_SPEEDL  0x20            //420 个时钟周期转换一次
#define ADC_SPEEDH  0x40            //630 个时钟周期转换一次
#define ADC_SPEEDHH 0x60            //840 个时钟周期转换一次

typedef unsigned char  INT8U;
typedef unsigned int   INT16U;
#define ENABLE_ISP 0x82 //系统工作时钟<20MHz 时,对IAP_CONTR 寄存器设置此值
#define WD1        0x5a        //使用STC11xx系列单片机时,先写入0x5a,然写入0xa5
#define WD2        0xa5
char IAPAddr=0;
/********************************************************************
                            初始定义
*********************************************************************/
code uchar seg7code[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //显示段码 数码管字跟
/********************************************************************
                            I/O定义
*********************************************************************/
bit z=0,ba=0,k=0,zs=0;
uchar y=0,smg2=0,s1=0,s2=0;
uint s=0,bai=0,shi=0,ge=0,js=0,dat=0,dat1=0;
sbit aj1=P5^4;
sbit aj2=P5^5;
sbit out=P3^4;
sbit L1=P3^5;//数码管位控制
sbit L2=P3^6;//数码管位控制
sbit L3=P3^7;//数码管位控制
sbit dp=P3^3;//小数点
bit kt=0,kt_1=0;
uchar trg=0,trg_1=0,cont=0,cont_1=0;
uchar ReadData=0,ReadData_1=0;
/********************************************************************
                            E2P函数
*********************************************************************/
union union_temp16
{
    INT16U un_temp16;
    INT8U  un_temp8[2];
}my_unTemp16;

INT8U Byte_Read(INT16U add);              //读一字节,调用前需打开IAP 功能
void Byte_Program(INT16U add, INT8U ch);  //字节编程,调用前需打开IAP 功能
void Sector_Erase(INT16U add);            //擦除扇区
void IAP_Disable();                       //关闭IAP 功能
/********************************************************************
                         AD转换初始化程序
*********************************************************************/
void InitADC()
{
   P1ASF = 0x80;          //设置P1.7口AD转换,必须加
   P1M0=0X80;
   P1M1=0X80;        //设置P1.7口为开漏模式,使用AD功能
    ADC_RES = 0;                   //AD数据寄存器清空
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;//打开AD电源,转换周期210
    _nop_();                        //延时一个机器周期
    _nop_();
        _nop_();                        //延时一个机器周期
}
/********************************************************************
                         AD转换控制程序
*********************************************************************/
uchar ADCRead(uchar px)          //转换输出的数据 (PX为通道口)
{
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL |px| ADC_START;//开始转换
    _nop_();                        //延时一个机器周期
    _nop_();                                                //延时一个机器周期
    _nop_();                                                //延时一个机器周期
    _nop_();                                                //延时一个机器周期
    while (!(ADC_CONTR & ADC_FLAG));//等待转换结束
    ADC_CONTR &= ~ADC_FLAG;         //关闭AD转换
    return ADC_RES;                //返回数据
}
/*******************************************************************
*                        读取按键状态
********************************************************************/
void KeyRead()//读取按键IO口函数
{
     ReadData = aj1^0xff;  // 读取按键状态取反后赋值给ReadData
     trg = ReadData & (ReadData ^ cont);  //trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
     cont = ReadData;   //cont长按,长按cont=1,抬手后cont=0

         ReadData_1 = aj2^0xff;  // 读取按键状态取反后赋值给ReadData
     trg_1 = ReadData_1 & (ReadData_1 ^ cont_1);  //trg短按,每按下按键trg=1;抬手后为trg=0,长按为trg=0
    cont_1 = ReadData_1;   //cont长按,长按cont=1,抬手后cont=0
}
/*******************************************************************
*                        按键
********************************************************************/
void key_1()
{          
  if(trg & 0x01) //短按
  {       
     kt_1=0;
         kt=1; //这是短按标志位,kt=1说明短按了
  }
  if((aj1!=0)&&(kt==1))//判断
        {
         z=1; // 选位标志位
         y++; //选位
         out=1;
         if(y==4)
          {
           z=0;
           k=1;
           y=0;
//           s=s1+s2+s3;
          }
         kt=0;
    }           // 短按

}

void key_2()
{          
  if(trg_1 & 0x01) //短按
  {       
     kt=0;
         kt_1=1; //这是短按标志位,kt=1说明短按了
  }
  if((aj2!=0)&&(kt_1==1))//判断
        {
         if(y==1)
          {
           s1++;
           if(s1>9)
            {
                 s1=0;
                }
          }
         if(y==2)
          {
           s2+=10;
           if(s2>90)
            {
                 s2=0;
                }
          }
         s=s1+s2;
         kt_1=0;
    }           // 短按
}

/*******************************************************************
*                        定时器配置
********************************************************************/
void ConfigTimer0(){
        TMOD=0x01;//将定时器0,1都设置为模式1
    TH0=0XFC;//1ms
    TL0=0X66;
        TR0=1;//开启定时器0
        ET0=1;//开定时器0的中断
        EA=1;//开总中断
}

/*******************************************************************
*                         显示
********************************************************************/
void led(uint date)
{
bai=date/100;
shi=date%100/10;
ge=date%10;
}
/*******************************************************************
*                         t0定时器
********************************************************************/
void timer0() interrupt 1
{
    TH0=0XFC;//1ms
    TL0=0X66;
        js++;
        if(js==200){ba=1;js=0;}
         
           if(z==0){
          smg2++;
          }
           else{
             smg2=y;//让逐个显示位
           }

             switch(smg2){                 //数码管扫描
        /**************数码管-开始*****************/
          case 1:  P1=seg7code[ge];L3=1;L2=1;L1=0;dp=0;break;//从P2进P0出
          case 2:  P1=seg7code[shi];L3=1;L2=0;L1=1;if(zs==0){dp=0;}else{dp=1;}break;
          case 3:  P1=seg7code[bai]; L3=0;L2=1;L1=1;dp=0;break;       
        /**************数码管-结束*****************/       
          default: smg2=0; L3=1;L2=1;L1=1; break;
         }
}
/********************************************************************
                            主函数
*********************************************************************/
void main()
{
  ConfigTimer0();        //定时器初始化
    InitADC();           //AD初始化
    P1M0 = 0xff;   //设置强推挽和开漏模式
    P1M1 = 0x80;
        P3M0 = 0x08;   //小数点使用
        P3M1 = 0x00;
        if(Byte_Read(0X0001)==0xff){s1=0;s2=0;}//首次读取,如果读到0xFF说明没有存过数据,直接付给00值
        else
        {
         s1=Byte_Read(0X0001);
         s2=Byte_Read(0X0002);
        }
        s2=s2*10;
        s=s2+s1;
   while(1)
    {
//          if(ba==1){dat=((ADCRead(7)*1000)/249);ba=0;}
          if(ba==1){dat=((ADCRead(7)*51)/255);dat1=dat*2;ba=0;} //51是单片机的工作电压,单片机的工作电压是多少这个就是多少
//          if(ba==1){dat=ADCRead(7);dat1=dat*100/249;ba=0;}
          if((y==0)&&(z==0)){zs=1;led(dat1);} //zs标志位控制小数点
          if(y==1){zs=0;led(s1);}
          if(y==2){zs=0;led(s2);}
          if(y==3){zs=1;z=0;led(s);}
          if(dat1>s){out=0;}else{out=1;}
          KeyRead(); //按键扫描
          key_1();
          key_2();
          if(k==1)
          {
             Sector_Erase(0);
                 Byte_Program(0x0001,s1);  //写入扇区
                 Byte_Program(0x0002,(s2/10));  //写入扇区
                 k=0;
          }
        }
  
}
//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
INT8U Byte_Read(INT16U add)
{
    IAP_DATA = 0x00;
    IAP_CONTR = ENABLE_ISP;         //打开IAP 功能, 设置Flash 操作等待时间
    IAP_CMD = 0x01;                 //IAP/ISP/EEPROM 字节读命令

    my_unTemp16.un_temp16 = add;
    IAP_ADDRH = my_unTemp16.un_temp8[0];    //设置目标单元地址的高8 位地址
    IAP_ADDRL = my_unTemp16.un_temp8[1];    //设置目标单元地址的低8 位地址

    //EA = 0;
    IAP_TRIG = WD1;   //先送 WD1,再送WD2 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG = WD2;   //送完WD2 后,ISP/IAP 命令立即被触发起动
    _nop_();
    //EA = 1;
    IAP_Disable();  //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
                    //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
    return (IAP_DATA);
}
/*********************************************************************************************/
//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据
void Byte_Program(INT16U add, INT8U ch)
{
    IAP_CONTR = ENABLE_ISP;         //打开 IAP 功能, 设置Flash 操作等待时间
    IAP_CMD = 0x02;                 //IAP/ISP/EEPROM 字节编程命令

    my_unTemp16.un_temp16 = add;
    IAP_ADDRH = my_unTemp16.un_temp8[0];    //设置目标单元地址的高8 位地址
    IAP_ADDRL = my_unTemp16.un_temp8[1];    //设置目标单元地址的低8 位地址

    IAP_DATA = ch;                  //要编程的数据先送进IAP_DATA 寄存器
    //EA = 0;
    IAP_TRIG = WD1;   //先送 WD1,再送WD2 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG = WD2;   //送完WD2 后,ISP/IAP 命令立即被触发起动
    _nop_();
    //EA = 1;
    IAP_Disable();  //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
                    //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}
/*********************************************************************************************
//擦除扇区, 入口:DPTR = 扇区地址 */
void Sector_Erase(INT16U add)
{
    IAP_CONTR = ENABLE_ISP;         //打开IAP 功能, 设置Flash 操作等待时间
    IAP_CMD = 0x03;                 //IAP/ISP/EEPROM 扇区擦除命令

    my_unTemp16.un_temp16 = add;
    IAP_ADDRH = my_unTemp16.un_temp8[0];    //设置目标单元地址的高8 位地址
    IAP_ADDRL = my_unTemp16.un_temp8[1];    //设置目标单元地址的低8 位地址

    //EA = 0;
    IAP_TRIG = WD1;   //先送 WD1,再送WD2 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG = WD2;   //送完WD2 后,ISP/IAP 命令立即被触发起动
    _nop_();
    //EA = 1;
    IAP_Disable();  //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
                    //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}
/*********************************************************************************************/
void IAP_Disable()
{
    //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
    //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
    IAP_CONTR = 0;      //关闭IAP 功能
    IAP_CMD   = 0;      //清命令寄存器,使命令寄存器无命令,此句可不用
    IAP_TRIG  = 0;      //清命令触发寄存器,使命令触发寄存器无触发,此句可不用
    IAP_ADDRH = 0;
    IAP_ADDRL = 0;
}
/*********************************************************************************************/



GYJ-0298_0~10V电压报警模块开关量干节点输出资料.rar

1.63 MB, 下载次数: 36

回复 送花

使用道具 举报

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2024-5-21 05:32 , Processed in 0.055952 second(s), 31 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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