main.c
#include "STC15F2K60S2.h"
#include "iic.h"
#define u8 unsigned char
#define u16 unsigned int
u8 code smg_du[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x3E,0x73,0x37}; //0-9
u8 code smg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
void vEEPROM_init();
void re_EEPROM();
#define KEY P3
#define NO_KEY 0xff //无按键按下
#define KEY_STATE0 0 //判断按键按下
#define KEY_STATE1 1 //确认按键按下
#define KEY_STATE2 2 //释放按键
unsigned char Key_Scan()
{
static unsigned char key_state=KEY_STATE0; //定义为静态变量,用于保存每次按键的状态
u8 key_value=0,key_temp; //key_val:返回的键值;key_temp:读取的IO状态
u8 key1,key2;
P30=0;P31=0;P32=0;P33=0;P34=1;P35=1;P42=1;P44=1;
if(P44==0) key1=0x70;
if(P42==0) key1=0xb0;
if(P35==0) key1=0xd0;
if(P34==0) key1=0xe0;
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_temp=key1|key2;
switch(key_state)
{
case KEY_STATE0: //判断按键按下
if(key_temp!=NO_KEY)
{
key_state=KEY_STATE1; //有键按下,就转到状态1
}
break;
case KEY_STATE1: //经过10ms,再次确认按键按下,用于消抖
if(key_temp==NO_KEY)
{
key_state=KEY_STATE0; //如果是抖动,则回到状态0
}
else //如果不是抖动,则返回对应的键值
{
switch(key_temp)
{
case 0x77: key_value=4;break;
case 0x7b: key_value=5;break;
case 0x7d: key_value=6;break;
case 0x7e: key_value=7;break;
case 0xb7: key_value=8;break;
case 0xbb: key_value=9;break;
case 0xbd: key_value=10;break;
case 0xbe: key_value=11;break;
case 0xd7: key_value=12;break;
case 0xdb: key_value=13;break;
case 0xdd: key_value=14;break;
case 0xde: key_value=15;break;
case 0xe7: key_value=16;break;
case 0xeb: key_value=17;break;
case 0xed: key_value=18;break;
case 0xee: key_value=19;break;
}
key_state=KEY_STATE2;
}
break;
case KEY_STATE2: //经过10ms,判断是否释放按键
if(key_temp==NO_KEY)
{
key_state=KEY_STATE0;
}
break;
}
return key_value;
}
void Timer_Init(void) //1ms定时器,用STC-ISP生成
{
AUXR |= 0x80; //1T的定时器
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //开启定时器0中断
EA=1; //开启总中断
}
void Io_init()
{
P2=0x80;P0=0xff;P2=0x00;
P2=0xa0;P0=0x00;P2=0x00;
}
bit key_flag; //按键标志位
u8 S12_num=0;
u8 V_data[8];
u8 P_data[8];
u8 N_data[8];
u8 adc_3;
u16 adc_v;
u16 adc_vnow;
u16 adc_data=0;
u8 N_num=0;
u8 S_null=0;
void main(void)
{
u8 key_val=NO_KEY;
Io_init(); //关闭蜂鸣器和继电器
vEEPROM_init();
V_data[0]=smg_du[10];
V_data[1]=0x00;
V_data[2]=0x00;
V_data[3]=0x00;
V_data[4]=0x00;
P_data[0]=smg_du[11];
P_data[1]=0x00;
P_data[2]=0x00;
P_data[3]=0x00;
P_data[4]=0x00;
N_data[0]=smg_du[12];
N_data[1]=0x00;
N_data[2]=0x00;
N_data[3]=0x00;
N_data[4]=0x00;
N_data[5]=0x00;
Timer_Init(); //1ms定时器
while(1)
{ if(S12_num==0)
{
V_data[5]=smg_du[adc_vnow/100]|0x80;
V_data[6]=smg_du[adc_vnow/10%10];
V_data[7]=smg_du[adc_vnow%10];
}
if(S12_num==1)
{
P_data[5]=smg_du[adc_data/100]|0x80;
P_data[6]=smg_du[adc_data/10%10];
P_data[7]=smg_du[adc_data%10];
}
if(S12_num==2)
{
N_data[6]=smg_du[N_num/10];
N_data[7]=smg_du[N_num%10];
}
if(key_flag) //10ms的轮询
{
key_flag=0;
key_val=Key_Scan();
switch(key_val)
{
case 4: break;
case 5: break;
case 6: break;
case 7: break;
case 8: break;
case 9: break;
case 10: break;
case 11: break;
case 12: S12_num++;
re_EEPROM();
if(S12_num==3) S12_num=0; break;
case 13: if(S12_num==2)
{
N_num=0;
S_null=0;
}
else{
S_null++;
}
break;
case 14: S_null++; break;
case 15: S_null++;break;
case 16:
if(S12_num==1)
{
adc_data+=50;
S_null=0;
if(adc_data>500)
{
adc_data=0;
}
}
else
{
S_null++;
}break;
case 17: if(S12_num==1)
{ S_null=0;
if(adc_data==0)
{
adc_data=550;}
adc_data=adc_data-50;
}
else{S_null++;}break;
case 18: break;
case 19: break;
}
}
}
}
void vEEPROM_init()
{
adc_data=read_24c02(0x00)*10;
if((adc_data>500)||(adc_data%50!=0))
adc_data=300;
}
u8 ledCtrl=0xff;
u16 led_count=0;
void Led_process()
{
if(adc_vnow=5000)
{
led_count=0;
P0=ledCtrl&~0x01; P2=0x80;P2=0x00;
}
}
else
{led_count=0;
P0=ledCtrl|0x01; P2=0x80;P2=0x00;
}
if(N_num%2==1)
{
P0=ledCtrl&~0x02; P2=0x80;P2=0x00;
}
else
{
P0=ledCtrl|0x02; P2=0x80;P2=0x00;
}
if(S_null>=3)
{
P0=ledCtrl&~0x04; P2=0x80;P2=0x00;
}
else
{
P0=ledCtrl|0x04; P2=0x80;P2=0x00;
}
}
void re_EEPROM()
{
if(S12_num==2)
{
write_24c02(0x00,adc_data/10);
}
}
void timer0() interrupt 1 //定时器0的中断编号是1
{
static int key_count=0,smg_count=0,i=0,U_count=0;
key_count++;
smg_count++;
U_count++;
Led_process();
if(U_count==10)
{
U_count=0;
read_adc(0x03);
adc_3=read_adc(0x03);
adc_v=adc_vnow;
adc_vnow=adc_3*100/51;
if((adc_v>adc_data)&&(adc_data>adc_vnow)&&(adc_v>adc_vnow))
{
N_num++;
}
}
if(key_count==10) //10ms轮询
{
key_count=0;
key_flag=1;
}
if(smg_count==3) //3ms轮询
{
smg_count=0;
P2=0xc0;P0=0;P2=0; //数码管消影
if(S12_num==0)
{
P2=0xe0;P0=~V_data[i];P2=0;
}
if(S12_num==1)
{
P2=0xe0;P0=~P_data[i];P2=0;
}
if(S12_num==2)
{
P2=0xe0;P0=~N_data[i];P2=0;
}
P2=0xc0;P0=smg_wei[i];P2=0; //数码管位选赋值
i++;
if(i==8) i=0;
}
}
iic.c
#include "reg52.h"
#include "iic.h"
#include "intrins.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
uchar read_24c02(uchar add)
{
uchar temp;
EA=0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
EA=1;
return temp;
}
void write_24c02(uchar add,uchar date)
{
EA=0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(date);
IIC_WaitAck();
IIC_Stop();
EA=1;
}
uchar read_adc(uchar add)
{
uchar temp;
EA=0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
EA=1;
return temp;
}
void write_adc(uchar add)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
}
总结主要一个 是 学习如何 判断 计数 触发条件编程
if(U_count==10) //10毫秒 刷新 电压值
{
U_count=0;
read_adc(0x03);
adc_3=read_adc(0x03);
adc_v=adc_vnow; // 获取前一次 电压值
adc_vnow=adc_3*100/51; // 此时的电压值
if((adc_v>adc_data)&&(adc_data>adc_vnow)&&(adc_v>adc_vnow)) // 初始值大于参数值,参数值大于现在值,现在值小于初始值 则符合条件加一
{
N_num++;
}
}
数值跃迁问题
主要是 从EEPROM 中读取值的时候 判断是否读取错误
void vEEPROM_init()
{
adc_data=read_24c02(0x00)*10;
if((adc_data>500)||(adc_data%50!=0)) // 电压值不可能超过 5v 这里电压值是扩大100倍 方便数码管显示 2. 读取的电压值 也不可能 是 23 34 之类的 按键加减都是 50 所以 不被50 整除也是数值错误 给与一个 初始值3 v
adc_data=300;
}



