- 打卡等级:初来乍到
- 打卡总天数:1
- 最近打卡:2025-03-17 16:39:04
中级会员
- 积分
- 253
|
功能说明:输入一个模拟量0-10V的电压 ,通过按键设置报警阈值,
数码管显示实时电压,当输入电压大于设定电压时,继电器吸合,
小于设定值时,继电器断开
【声明】此程序仅用于学习与参考!
*********************************************************************/
/********************************************************************
宏定义
*********************************************************************/
#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;
}
/*********************************************************************************************/
|
|