|
【声明】此程序仅用于学习与参考!
*********************************************************************/
#include <STC12C5A60S2.H>
#define uchar unsigned char//宏定义无符号字符型
#define uint unsigned int //宏定义无符号整型
uchar Byte_Read(uint add); //读一字节,调用前需打开IAP 功能
void Byte_Program(uint add, uint ch); //字节编程,调用前需打开IAP 功能
void Sector_Erase(uint add); //擦除扇区
void IAP_Disable(); //关闭IAP 功能
#define ENABLE_ISP 0x81 //系统工作时钟<20MHz 时,对IAP_CONTR 寄存器设置此值
void eerpominputmain();//掉电存储主函数
void readeerpom();
void timer0_1init();
sbit ins1=P3^2;
sbit ins2=P3^3;
sbit key3=P2^7;
sbit key2=P2^6;
sbit key1=P2^5;
sbit rt1=P2^0;
sbit rt2=P2^1;
sbit rt3=P2^2;
sbit rt4=P2^3;
xdata uchar keynewval[]={1,1,1,1,1,1,1,1,1};//获取每个按键最新的状态
xdata uchar keyoldval[]={1,1,1,1,1,1,1,1,1};//保存每个按键老的状态
uchar keypatrol(uchar keys);//按键巡查
uint keytime;
void keytimevoid();//写在定时器中,用于注册按键
void keymainvoid();//写在main函数中,用于按键实际操作
void insmainvoid();//触发端
void rtsmainvoid();//用于遥控实际操作
sbit out2=P3^7;
sbit out1=P2^4;
sbit pa = P1^0;//数码管段
sbit pb = P1^1;
sbit pc = P1^2;
sbit pd = P1^3;
sbit pe = P1^4;
sbit pf = P1^5;
sbit pg = P1^6;
sbit pp = P1^7;
sbit displayplace1=P0^1;//数码管位
sbit displayplace2=P0^2;
sbit displayplace3=P0^3;
uint displaynum=0;
code uchar displaysectionarray[13]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0x8c,0xff};//数码管0到9 - p 不显示
code uchar displaysectionarrayp[13]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x3f,0x0c,0x7f};//数码管0到9
uchar displaysection;//数码管获取显示字样,以及传给io进行显示
uchar undreds,decade,unit;//百 十 个
void display();//数码管处理
bit undredsp=0,decadep=0,unitp=0,valuationp=0;
char automationf=0,modef =0;//自动 手动
void automationvoid();//自动
void modevoid();//手动
uchar keypage=0,place=0;
uchar num1,num2,num3;
uint automationgoupnum,automationstopnum,automationdeclinenum,modegoupnum,modeclinenum;//自动上升,自动停止,自动下降,手动上升,手动下降
uchar automationgoupnum1,automationgoupnum2,automationstopnum1,automationstopnum2,automationdeclinenum1,automationdeclinenum2;
uchar modegoupnum1,modegoupnum2,modeclinenum1,modeclinenum2;
void displayvoid();//显示函数
void automationtime();
bit atimef=0,atimefs=0,atimefgoup=0,atimefstop=0,atimefdecline=0;
uint timess,timegoup,timestop,timedecline;
void modetime();
bit mtimefg=0,mtimec=0,mtimef=0;
uint mtimes1;
void modetime(){
if(mtimef){
timess++;
if(timess==500){
timess=0;
if(mtimefg){
timegoup--;
if(timegoup==0){
timegoup=modegoupnum;
out1=1;
out2=1;
mtimefg=0;
mtimef=0;
}
}else if(mtimec){
timedecline--;
if(timedecline==0){
timedecline=modeclinenum;
out1=1;
out2=1;
mtimec=0;
mtimef=0;
}
}
}
}
}
void insmainvoid(){//用于触发端操作
if(keynewval[0]!=keyoldval[0]){//输入端1操作
if(keynewval[0]){keyoldval[0] = 1;//松开 -----
modef=0;undredsp=0;decadep=0;unitp=0;
}else{keyoldval[0] = 0; //按下 -----手动
modef=1;
keypage=0;
undredsp=1;decadep=1;unitp=1;
}}//输入端1操作完成
if(keynewval[1]!=keyoldval[1]){//输入端2操作
if(keynewval[1]){keyoldval[1] = 1;//松开 -----
automationf=0;undredsp=0;decadep=0;unitp=0;
}else{keyoldval[1] = 0;//按下 -----自动
automationf=1;
atimef=1;
out1=0;
atimefgoup=1;
atimefstop=0;
atimefdecline=0;
timedecline=automationdeclinenum;
timestop=automationstopnum;
timegoup=automationgoupnum;
keypage=0;undredsp=0;decadep=0;unitp=0;
}}//输入端2操作完成
}
void rtsmainvoid(){//写在main函数中,用于遥控实际操作
if(keynewval[8]!=keyoldval[8]){//遥控A操作 --------------上升
if(keynewval[8]){keyoldval[8] = 1;//松开 -----
if(mtimefg==0){
out1=0;
out2=1;
mtimef=1;
mtimefg=1;
mtimec=0;
timegoup=modegoupnum;
}
}else{keyoldval[8] = 0;//按下 -----
//out2=1;
}}//遥控A操作完成
if(keynewval[7]!=keyoldval[7]){//遥控B操作 --------------下降
if(keynewval[7]){keyoldval[7] = 1;//松开 -----
if(mtimec==0){
out1=1;
out2=0;
mtimef=1;
mtimefg=0;
mtimec=1;
timedecline=modeclinenum;
}
}else{keyoldval[7] = 0;//按下 -----
//out1=1;
}}//遥控B操作完成
if(keynewval[6]!=keyoldval[6]){//遥控C操作 --------------停止
if(keynewval[6]){keyoldval[6] = 1;//松开 -----
out1=1;
out2=1;
mtimef=0;
mtimefg=0;
mtimec=0;
}else{keyoldval[6] = 0;//按下 -----
//out2=1;
}}//遥控C操作完成
// if(keynewval[5]!=keyoldval[5]){//遥控D操作
// if(keynewval[5]){keyoldval[5] = 1;//松开 -----
// out2=1;
// }else{keyoldval[5] = 0;//按下 -----
// out2=0;
// }}//遥控D操作完成
}
void modevoid(){//手动模式
if(mtimefg){
undreds=timegoup%1000/100;
decade=timegoup%100/10;
unit=timegoup%10;
}else if(mtimec){
undreds=timedecline%1000/100;
decade=timedecline%100/10;
unit=timedecline%10;
}else if(mtimef==0){
unit=10;
decade=10;
undreds=10;
}
}
void main(){
P1M1=0x00;
P1M0=0xff;
timer0_1init();
readeerpom();
while(1){
insmainvoid();//触发端
if(automationf){
automationvoid();//自动模式
}else if(modef){
rtsmainvoid();//用于遥控实际操作
modevoid();//手动模式
}else{
keymainvoid();//用于按键实际操作
displayvoid();
out1=1;
out2=1;
timedecline=0;
timestop=0;
timegoup=0;
mtimef=0;
mtimefg=0;
mtimec=0;
atimef=0;
atimefgoup=0;
atimefstop=0;
atimefdecline=0;
}
}
}
void automationvoid(){//自动模式
if(atimefgoup){
undreds=timegoup%1000/100;
decade=timegoup%100/10;
unit=timegoup%10;
}else if(atimefstop){
undreds=timestop%1000/100;
decade=timestop%100/10;
unit=timestop%10;
}else if(atimefdecline){
undreds=timedecline%1000/100;
decade=timedecline%100/10;
unit=timedecline%10;
}else if(atimef==0){
unit=10;
decade=10;
undreds=10;
}
}
void automationtime(){
if(atimef){
timess++;
if(timess==500){
timess=0;
if(atimefgoup){
timegoup--;
if(timegoup==0){
timegoup=automationgoupnum;
out1=1;
atimefgoup=0;
atimefstop=1;
}
}else if(atimefstop){
timestop--;
if(timestop==0){
timestop=automationstopnum;
out2=0;
atimefstop=0;
atimefdecline=1;
}
}else if(atimefdecline){
timedecline--;
if(timedecline==0){
timedecline=automationdeclinenum;
out2=1;
atimefdecline=0;
atimef=0;
}
}
}
}
}
void timer0(void)interrupt 1 {
TL0 = 0x18; //设置定时初值 2ms
TH0 = 0xFC; //设置定时初值
keytime++;
if(keytime>100){
keytimevoid();//用于注册按键
keytime=0;
}
displaynum++;//数码管计数
display();//数码管处理
modetime();
automationtime();
}
uchar keypatrol(uchar keys){//按键巡查
static unsigned char keypatrolval= 1;//按键巡查的值
keypatrolval = (keypatrolval<<1) | keys;//获取按键
if(keypatrolval==0X00)keys=0;
if(keypatrolval==0XFF)keys=1;
return keys;
}
void keytimevoid(){//写在定时器中,用于注册按键
keynewval[0]=keypatrol(ins1);//注册按键1,将按键1的值传入到按键数组中
keynewval[1]=keypatrol(ins2);
keynewval[2]=keypatrol(key1);
keynewval[3]=keypatrol(key2);//注册触发端
keynewval[4]=keypatrol(key3);
keynewval[5]=keypatrol(rt1);
keynewval[6]=keypatrol(rt2);
keynewval[7]=keypatrol(rt3);
keynewval[8]=keypatrol(rt4);
}
void display(){//数码管处理
if(displaynum==1){if(undredsp){displaysection=displaysectionarrayp[undreds];}else{displaysection=displaysectionarray[undreds];}displayplace1=0;displayplace3=1;}//千
if(displaynum==2){if(decadep){displaysection=displaysectionarrayp[decade];}else{displaysection=displaysectionarray[decade];} displayplace2=0;displayplace1=1;}//百
if(displaynum==3){if(unitp){displaysection=displaysectionarrayp[unit];}else{displaysection=displaysectionarray[unit];} displayplace3=0;displayplace2=1;displaynum=0;}//个
if(displaysection&0x01)pa=0; else pa=1;//段处理,分配到不同的io上
if(displaysection&0x02)pb=0; else pb=1;
if(displaysection&0x04)pc=0; else pc=1;
if(displaysection&0x08)pd=0; else pd=1;
if(displaysection&0x10)pe=0; else pe=1;
if(displaysection&0x20)pf=0; else pf=1;
if(displaysection&0x40)pg=0; else pg=1;
if(displaysection&0x80)pp=0;else pp=1;
}
void timer0_1init(void){//定时配置
TMOD=0x11;//将定时器0,1都设置为模式1
TL0 = 0x18; //设置定时初值 2ms
TH0 = 0xFC; //设置定时初值
TR0=1;//开启定时器0
TR1=1;//开启定时器1
EA=1;//开总中断
ET0=1;//开定时器0的中断
}
void delay1(unsigned int t){//延时
while(t>0){
t--;
}
}
void keymainvoid(){//写在main函数中,用于按键实际操作
if(keynewval[2]!=keyoldval[2]){//按键1操作
if(keynewval[2]){keyoldval[2] = 1;//松开 -----
}else{keyoldval[2] = 0;//按下 -----
keypage++;
place=0;
valuationp=1;
if(keypage>5){keypage=0;}
}}//按键1操作完成
if(keynewval[3]!=keyoldval[3]){//按键2操作
if(keynewval[3]){keyoldval[3] = 1;//松开 -----
}else{keyoldval[3] = 0;//按下 -----
place++;
if(place>3){place=0;}
}}//按键2操作完成
if(keynewval[4]!=keyoldval[4]){//按键3操作
if(keynewval[4]){keyoldval[4] = 1;//松开 -----
if(keypage>0)eerpominputmain();
}else{keyoldval[4] = 0;//按下 -----
if(place==1){num1++;if(num1>9){num1=0;}}
else if(place==2){num2++;if(num2>9){num2=0;}}
else if(place==3){num3++;if(num3>9){num3=0;}}
}}//按键3操作完成
}
void displayvoid(){
if(keypage==1){
undredsp=1;decadep=0;unitp=0;
if(valuationp){valuationp=0;
num1=automationgoupnum%1000/100;num2=automationgoupnum%100/10;num3=automationgoupnum%10;
}else{
automationgoupnum=num1*100+num2*10+num3;
}
}else if(keypage==2){
undredsp=0;decadep=1;unitp=0;
if(valuationp){valuationp=0;
num1=automationstopnum%1000/100;num2=automationstopnum%100/10;num3=automationstopnum%10;
}else{
automationstopnum=num1*100+num2*10+num3;
}
}else if(keypage==3){
undredsp=0;decadep=0;unitp=1;
if(valuationp){valuationp=0;
num1=automationdeclinenum%1000/100;num2=automationdeclinenum%100/10;num3=automationdeclinenum%10;
}else{
automationdeclinenum=num1*100+num2*10+num3;
}
}else if(keypage==4){
undredsp=1;decadep=1;unitp=0;
if(valuationp){valuationp=0;
num1=modegoupnum%1000/100;num2=modegoupnum%100/10;num3=modegoupnum%10;
}else{
modegoupnum=num1*100+num2*10+num3;
}
}else if(keypage==5){
undredsp=0;decadep=1;unitp=1;
if(valuationp){valuationp=0;
num1=modeclinenum%1000/100;num2=modeclinenum%100/10;num3=modeclinenum%10;
}else{
modeclinenum=num1*100+num2*10+num3;
}
}else{
undredsp=0;decadep=0;unitp=0;valuationp=0;
unit=decade=undreds=10;
}
if(keypage>0){
if(place==1){
unit=12;
decade=12;
undreds=num1;
}else if(place==2){
unit=12;
decade=num2;
undreds=12;
}else if(place==3){
unit=num3;
decade=12;
undreds=12;
}else{
unit=num3;
decade=num2;
undreds=num1;
}
}
}
void readeerpom(){
automationgoupnum1=Byte_Read(0x01);
automationgoupnum2=Byte_Read(0x02);
automationgoupnum=automationgoupnum1*100+automationgoupnum2;
automationstopnum1=Byte_Read(0x03);
automationstopnum2=Byte_Read(0x04);
automationstopnum=automationstopnum1*100+automationstopnum2;
automationdeclinenum1=Byte_Read(0x05);
automationdeclinenum2=Byte_Read(0x06);
automationdeclinenum=automationdeclinenum1*100+automationdeclinenum2;
modegoupnum1=Byte_Read(0x07);
modegoupnum2=Byte_Read(0x08);
modegoupnum=modegoupnum1*100+modegoupnum2;
modeclinenum1=Byte_Read(0x09);
modeclinenum2=Byte_Read(0x0A);
modeclinenum=modeclinenum1*100+modeclinenum2;
}
void eerpominputmain(){
automationgoupnum1=automationgoupnum/100;
automationgoupnum2=automationgoupnum%100;
automationstopnum1=automationstopnum/100;
automationstopnum2=automationstopnum%100;
automationdeclinenum1=automationdeclinenum/100;
automationdeclinenum2=automationdeclinenum%100;
modegoupnum1=modegoupnum/100;
modegoupnum2=modegoupnum%100;
modeclinenum1=modeclinenum/100;
modeclinenum2=modeclinenum%100;
Sector_Erase(0);
Byte_Program(0x01,automationgoupnum1);
Byte_Program(0x02,automationgoupnum2);
Byte_Program(0x03,automationstopnum1);
Byte_Program(0x04,automationstopnum2);
Byte_Program(0x05,automationdeclinenum1);
Byte_Program(0x06,automationdeclinenum2);
Byte_Program(0x07,modegoupnum1);
Byte_Program(0x08,modegoupnum2);
Byte_Program(0x09,modeclinenum1);
Byte_Program(0x0A,modeclinenum2);
}
union union_temp16{
uint un_temp16;
uchar un_temp8[2];
}my_unTemp16;
//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
uchar Byte_Read(uint 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 = 0x5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
delay1(1);
//EA = 1;
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
return (IAP_DATA);
}
//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据
void Byte_Program(uint add, uint 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 = 0x5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
delay1(1);
//EA = 1;
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}
//擦除扇区, 入口:DPTR = 扇区地址
void Sector_Erase(uint 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 位地址
IAP_TRIG = 0x5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
delay1(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;
}
|
|