- 打卡等级:初来乍到
- 打卡总天数:1
- 最近打卡:2025-03-17 16:39:04
中级会员
- 积分
- 253
|
/********************************************************************
实现功能:应用程序
使用芯片:STC15W408AS
晶振:11.0592MHZ
波特率:9600
编译环境:Keil 4
【声明】此程序仅用于学习与参考!
*********************************************************************/
/********************************************************************
宏定义
*********************************************************************/
#include<STC15W408AS.h> //库文件
#include<intrins.h>
#define uchar unsigned char//宏定义无符号字符型
#define uint unsigned int //宏定义无符号整型
#define ulong unsigned long //宏定义无符号整型
#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;
uint AD_H=0,AD_L=0,AD_Dat=0;
/********************************************************************
初始定义
*********************************************************************/
//code uchar seg7code[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //显示段码 数码管字跟
code uchar seg7code[10]={0x7E,0x0C,0xB6,0x9E,0xCC,0xDA,0xFA,0x0E,0xFE,0xDE}; //显示段码 数码管字跟
/********************************************************************
I/O定义
*********************************************************************/
bit z=0,ba=0,zs=0,kz=0;
uchar y=0,smg2=0;
uchar s1=0,s2=0,s3=0,qian=0,bai=0,shi=0,ge=0,js=0;
uchar s11=0,s22=0,s33=0;
ulong dat=0,dat1=0,dat2=0,dat3=0,dat4=0,dat5=0;
sbit aj1=P5^4;
sbit aj2=P5^5;
sbit out=P1^7;
sbit L1=P1^4;//数码管位控制
sbit L2=P1^3;//数码管位控制
sbit L3=P1^2;//数码管位控制
sbit dp=P1^0;//小数点
sbit CS=P1^5;//测试脚
bit pdbz=0;
uchar jsz=0; //AD计数值
bit bz1=0; //按键标志
bit bz2=0; //按键标志
bit smbz=0;//扫描标志
uint date;//设置报警阀值
bit write=0;//EEPROM存储标志位
xdata uint receBuf[50]; //接收缓冲区
uchar r=0;//读取AD计数
bit flag_zx=0;
ulong sum=0;//AD值总和
uchar i=0;
bit qlbz=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 = 0x40; //设置P1.7口AD转换,必须加
P1M0=0X40;
P1M1=0X40; //设置P1.7口为开漏模式,使用AD功能
ADC_RES = 0; //AD数据寄存器清空
ADC_CONTR = ADC_POWER | ADC_SPEEDLL;//打开AD电源,转换周期210
_nop_(); //延时一个机器周期
_nop_();
_nop_(); //延时一个机器周期
}
void delay(uchar z)
{
uchar i,j;
for(i=0;i<z;i++)
{
for(j=130;j>0;j--);
}
}
/********************************************************************
AD转换控制程序
*********************************************************************/
uint 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转换
AD_H = ADC_RES; // 修改的 注:把高8位AD值付给AD_H
AD_H <<= 2; // 修改的 注:高八位左移2位
AD_L = ADC_RESL & 0x03; // 修改的 注:取低两位
AD_Dat = AD_H | AD_L; // 修改的 注:把高八位和低两位合并在一起
return AD_Dat; //返回数据
}
/*******************************************************************
* 按键函数
********************************************************************/
void key()
{
if((aj1==0)&&(bz1==0)){delay(10);if((aj1==0)&&(bz1==0)) //位选
{
smbz=0;bz1=1;z=1;y++;if(y==5){z=0;y=0;date=s3*100+s2*10+s1;write=1;}smg2=y;if(y==4){smbz=1;}}}
if((aj1==1)&&(bz1==1)){delay(10);if((aj1==1)&&(bz1==1)){bz1=0;}}
if((aj2==0)&&(bz2==0)) //段选
{
delay(10);if((aj2==0)&&(bz2==0))
{
if(y==1){smg2=1;s1++;if(s1>9){s1=0;}}
if(y==2){smg2=2;s2++;if(s2>9){s2=0;}}
if(y==3){smg2=3;s3++;if(s3>9){s3=0;}}
bz2=1;
}
}
if((aj2==1)&&(bz2==1)){delay(10);if((aj2==1)&&(bz2==1)){bz2=0;}} }
/*******************************************************************
* 定时器配置
********************************************************************/
void ConfigTimer0(){
TMOD=0x01;//将定时器0,1都设置为模式1
TH0=0XFC;//1ms
TL0=0X66;
TR0=1;//开启定时器0
ET0=1;//开定时器0的中断
EA=1;//开总中断
}
/*******************************************************************
* 显示 1
********************************************************************/
void led(uint date)
{
bai=date%1000/100;
shi=date%100/10;
ge=date%10;
}
/*******************************************************************
* 显示2
********************************************************************/
//void dispay(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++;
switch(smg2){ //数码管扫描
/**************数码管-开始*****************/
case 1: P3=seg7code[ge]; L3=1;L2=1;L1=0;dp=0;break;//从P2进P0出
case 2: P3=seg7code[shi];L3=1;L2=0;L1=1;dp=0;break;
case 3: P3=seg7code[bai];L3=0;L2=1;L1=1;dp=0;break;
/**************数码管-结束*****************/
default: smg2=0; L3=1;L2=1;L1=1; break;
}
}
else{
if(smbz==1){smg2++;}else {smg2=y;}
switch(smg2){ //数码管扫描
/**************数码管-开始*****************/
case 1: P3=seg7code[s1];L3=1;L2=1;L1=0;dp=0;break;//从P2进P0出
case 2: P3=seg7code[s2];L3=1;L2=0;L1=1;dp=0;break;
case 3: P3=seg7code[s3];L3=0;L2=1;L1=1;dp=0;break;
/**************数码管-结束*****************/
default: smg2=0; L3=1;L2=1;L1=1; break;
}
}
}
/********************************************************************
主函数
*********************************************************************/
void main()
{
ConfigTimer0(); //定时器初始化
InitADC(); //AD初始化
P3M0 = 0xff; //设置强推挽和开漏模式
P3M1 = 0x00;
P1M0 = 0x40; //小数点使用
P1M1 = 0x40;
if(s1>9){s1=0;}
if(s2>9){s1=0;}
if(s3>9){s1=0;}
if(Byte_Read(0X0001)==0xff){s1=0;s2=0;s3=0;}//首次读取,如果读到0xFF说明没有存过数据,直接付给00值
else
{
s1=Byte_Read(0X0001);
s2=Byte_Read(0X0002);
s3=Byte_Read(0X0003);
}
date=s3*100+s2*10+s1;
while(1)
{
jsz++;
if(jsz>=20){ dat=ADCRead(6);jsz=0; }
/////****************去掉两个最大值和两个最小值求平均值*********************************/
////receBuf[r++]=dat1; //把接受的数据存储到BUT数组中
////
////if(r>=7)
////{
////r=0;
////flag_zx=1;
////}
////if(flag_zx==1)
////{
////flag_zx=0;
////for(i=0; i<7-1; i++)
////{
////每一轮比较前n-1-i个,即已排序好的最后i个不用比较
////for( j=0; j<7-1-i; j++)
////{
////if(receBuf[j] > receBuf[j+1])
////{
////temp = receBuf[j];
////receBuf[j] = receBuf[j+1];
////receBuf[j+1]=temp;
////}
////}
//
///****************取100个数值求平均数*********************************/
receBuf[r++]=dat; //把接受的数据存储到BUT数组中
if(r>=100)
{
r=0;
sum=0;
flag_zx=1;
}
if(flag_zx==1)
{
flag_zx=0;
for(i=0; i<100; i++)
{
sum=sum+receBuf;
}
dat2=sum/100;
}
key();
dat4=dat2;
if(CS==0){dat3=0;qlbz=1;dat5=dat4;}
if(dat4>dat5){qlbz=0;}
if(qlbz==1){led(dat3); }
if((y==0)&&(z==0)&&(qlbz==0))
{
if((dat2>=(dat3+32))||(dat2<(dat3+29)))
{
dat3=dat2-30;led(dat3);
}
} //zs标志位控制小数点
if(write==1)
{
Sector_Erase(0);
Byte_Program(0x0001,s1); //写入扇区
Byte_Program(0x0002,(s2)); //写入扇区
Byte_Program(0x0003,(s3)); //写入扇区
write=0;
}
}
}
//// if((dat2>s)&&(pdbz==0)){out=0;dat4=dat2*0.98;pdbz=1;}
//// if((dat2<s)&&(pdbz==1)){out=1;pdbz=0;}
//// if(dat4<s){out=1;}
// KeyRead(); //按键扫描
//读一字节,调用前需打开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;
}
/*********************************************************************************************/
|
|