题目要求
程序代码
主函数
#include "stc15f2k60s2.h"
#include "key.h"
#include "hardware.h"
#include "iic.h"
#include "delay.h"
typedef unsigned char uchar;
typedef unsigned int uint;
bit Read_adc_flag;
bit led1_count_flag;
uchar test_flag;
uchar led_value=0xff;
uchar key_val; //按键值
uint AD_val; //电压值
int VP=300; //电压参数
uchar count_val=0; //计数值
uchar error_count; //错误计数
uchar Display_mode; //界面选择
uchar code SMG_duan[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
uchar SMG_wei[]={ 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar Display1[8]; //界面1
uchar Display2[8]; //界面2
uchar Display3[8]; //界面3
void key_process(); //按键功能函数
void Timer0Init(void); //1毫秒@12.000MHz
void Display1_pro(); //界面1处理函数
void Display2_pro(); //界面2处理函数
void Display3_pro(); //界面3处理函数
void judge();
void main()
{
uchar j;
All_init();
Timer0Init();
test_flag=Read_eeprom(0x09); //读取指定地址的值
if(test_flag==8) //可取任意值,确保第一次上电,VP=3V
VP=Read_eeprom(0x00)*10;
else
{
VP=300;
Write_eeprom(0x09,8);
delayms(10);
}
while(1)
{
key_process();
Display1_pro();
Display2_pro();
Display3_pro();
judge();
Ledlight(led_value);
switch(j) //保证每次只加1
{
case 0:
if(AD_val>VP)
{
j++;
}
break;
case 1:
if(AD_val<VP)
{
j=0;
count_val++;
}
break;
}
}
}
void judge()
{
uchar flag1,flag2,flag3;
if(AD_val<VP)
led1_count_flag=1;
else
led1_count_flag=0;
if(count_val%2!=0) //判断奇偶
led_value&=0xfd;
else
led_value|=0x02;
if(Display_mode!=1) //无效按键
{
if((key_val==16)||(key_val==17))
error_count++;
}
else
{
if((key_val==16)||(key_val==17))
error_count=0;
}
if(Display_mode!=2)
{
if(key_val==13)
error_count++;
}
else
{
if(key_val==13)
error_count=0;
}
if((key_val==4)||(key_val==5)||(key_val==6)||(key_val==7))
flag1=1;
if((key_val==8)||(key_val==9)||(key_val==10)||(key_val==11))
flag2=1;
if((key_val==14)||(key_val==15)||(key_val==18)||(key_val==19))
flag3=1;
if((flag1==1)||(flag2==1)||(flag3==1))
{
flag1=0; flag2=0; flag3=0;
error_count++;
}
if(error_count>=3)
{
led_value&=0xfb;
}
else
led_value|=0x04;
}
#define fun(x) (int)(5*x/255.0*100+0.5) //数字电压x转换为模拟电压的公式
void Display1_pro() //界面1
{
uint temp;
if(Read_adc_flag) //100ms读一次数据
{
temp=Read_pcf8591(0x03);
Read_adc_flag=0;
AD_val=fun(temp);
}
Display1[0]=0x3e;
Display1[1]=0x00;
Display1[2]=0x00;
Display1[3]=0x00;
Display1[4]=0x00;
Display1[5]=SMG_duan[AD_val/100]|0x80;
Display1[6]=SMG_duan[AD_val/10%10];
Display1[7]=SMG_duan[AD_val%10];
}
void Display2_pro() //界面2
{
Display2[0]=0x73;
Display2[1]=0x00;
Display2[2]=0x00;
Display2[3]=0x00;
Display2[4]=0x00;
Display2[5]=SMG_duan[VP/100]|0x80;
Display2[6]=SMG_duan[VP/10%10];
Display2[7]=SMG_duan[VP%10];
}
void Display3_pro() //界面3
{
Display3[0]=0x37;
Display3[1]=0x00;
Display3[2]=0x00;
Display3[3]=0x00;
Display3[4]=0x00;
Display3[5]=0x00;
Display3[6]=SMG_duan[count_val/10];
Display3[7]=SMG_duan[count_val%10];
}
void key_process()
{
uchar temp;
key_val=Key_init();
switch(key_val)
{
case 12: //界面切换
error_count=0;
Display_mode++;
if(Display_mode==3)
Display_mode=0;
break;
case 13: //清零
if(Display_mode==2)
count_val=0;
break;
case 16: //"加"
if(Display_mode==1)
{
VP+=50;
if(VP>500)
VP=0;
temp=VP/10;
Write_eeprom(0x00,temp);
delayms(10);
}
break;
case 17: //"减"
if(Display_mode==1)
{
VP-=50;
if(VP<0)
VP=500;
temp=VP/10;
Write_eeprom(0x00,temp);
delayms(10);
}
break;
}
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
}
void timer0() interrupt 1
{
static smg_count;
uchar adc_count;
uint led1_count;
uchar i;
adc_count++;
smg_count++;
if(led1_count_flag)
{
led1_count++;
if(led1_count>5000)
{
led_value&=0xfe;
}
}
else
{
led_value|=0x01;
led1_count=0;
}
if(smg_count==2)
{
smg_count=0;
P2=P2&0x1f|0xc0; P0=SMG_wei[i];
P2=P2&0x1f;
if(Display_mode==0)
{
P2=P2&0x1f|0xe0; P0=~Display1[i];
P2=P2&0x1f;
}
if(Display_mode==1)
{
P2=P2&0x1f|0xe0; P0=~Display2[i];
P2=P2&0x1f;
}
if(Display_mode==2)
{
P2=P2&0x1f|0xe0; P0=~Display3[i];
P2=P2&0x1f;
}
i++;
if(i==8)
i=0;
}
if(adc_count==100)
{
adc_count=0;
Read_adc_flag=1;
}
}
按键部分
#include "key.h"
unsigned char Key_init()
{
static unsigned char key_state=0;
unsigned char key1,key2;
unsigned char key_press;
unsigned char key_val;
P30=0; P31=0; P32=0; P33=0; P34=1; P35=1; P42=1; P44=1;
if(P34==0) key1=0xe0;
if(P35==0) key1=0xd0;
if(P42==0) key1=0xb0;
if(P44==0) key1=0x70;
if((P34==1)&&(P35==1)&&(P42==1)&&(P44==1))
key1=0xf0;
P30=1; P31=1; P32=1; P33=1; P34=0; P35=0; P42=0; P44=0;
if(P30==0) key2=0x0e;
if(P31==0) key2=0x0d;
if(P32==0) key2=0x0b;
if(P33==0) key2=0x07;
if((P30==1)&&(P31==1)&&(P32==1)&&(P33==1))
key2=0x0f;
key_press = key1|key2;
switch(key_state)
{
case 0:
if(key_press!=0xff)
key_state = 1;
break;
case 1:
if(key_press!=0xff)
{
if(key_press==0x7e) key_val=7;
if(key_press==0x7d) key_val=6;
if(key_press==0x7b) key_val=5;
if(key_press==0x77) key_val=4;
if(key_press==0xbe) key_val=11;
if(key_press==0xbd) key_val=10;
if(key_press==0xbb) key_val=9;
if(key_press==0xb7) key_val=8;
if(key_press==0xde) key_val=15;
if(key_press==0xdd) key_val=14;
if(key_press==0xdb) key_val=13;
if(key_press==0xd7) key_val=12;
if(key_press==0xee) key_val=19;
if(key_press==0xed) key_val=18;
if(key_press==0xeb) key_val=17;
if(key_press==0xe7) key_val=16;
key_state = 2;
}
else
key_state = 0;
break;
case 2:
if(key_press==0xff)
key_state = 0;
break;
}
return key_val;
}
led模块
#include "hardware.h"
void All_init()
{
P2=(P2&0x1f)|0x80; //关闭led
P0=0xff;
P2=P2&0x1f;
P2=(P2&0x1f)|0xA0; //关闭蜂鸣器、继电器
P0=0x00;
P2=P2&0x1f;
}
void Ledlight(unsigned char led_val)
{
P0=0xff;
P2=(P2&0x1f)|0x80;
P0=led_val;
P2=P2&0x1f;
}
iic模块
#include "iic.h"
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
//应答位控制
void IIC_Ack(unsigned char ackbit) //当ackbit为1时,表示单片机对从设备发送来数据的应答
//当ackbit为0时,表示主机接收了最后一个字节,因此不再应答,结束通信
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA) //在SCL为高电平期间,因为接收设备未将SDA拉低,所以默认未接收到应答,结束IIC通信
{
SCL = 0;
IIC_Stop();
return 0;
}
else //接收到应答,返回1,继续下一个数据字节的传输
{
SCL = 0;
return 1;
}
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
void Write_eeprom(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char Read_eeprom(unsigned char addr)
{
unsigned char temp;
ET0=0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
ET0=1;
return temp;
}
unsigned char Read_pcf8591(unsigned char addr)
{
unsigned char temp;
ET0=0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
ET0=1;
return temp;
}
(iic.h文件中定义的somenop为5个_nop_(),编程时应改为25个)
延时模块
#include "delay.h"
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void delayms(unsigned char ms)
{
unsigned char i;
for(i=0;i<ms;i++)
Delay1ms();
}
以上就是代码全部内容,欢迎交流~