main.c
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "stdio.h"
#include "MCU_init.h"
#include "iic.h"
#include "key4.h"
#define SET_VALUE(X,Y) {P0=X;P2=(P2&=0X1F)|(Y<<5);P2&=0X1F;} //宏定义
#define uint unsigned int
#define uchar unsigned char
extern unsigned char shift_state; //外部变量
extern unsigned char mode;
int num[4]={15,0,30,26}; //定义显示初值
uint count=0; //计时器计时
uchar value[9]={0},tran[8]={0},wei=0;
uchar light=0,temperature=0;
uchar position=0;
bit adc_flag=0; //adc开始标志位
bit light_flag=0,temperature_flag=0; //LED亮灯标志位
bit blight_flag=0; //数码管闪烁标志位
bit relay_flag=0; //继电器亮标志位
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void Delay500ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 23;
j = 205;
k = 120;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/******蜂鸣器函数******/
void bell_2times()
{
SET_VALUE(0x40,5);
Delay500ms();
SET_VALUE(0x00,5);
Delay500ms();
SET_VALUE(0x40,5);
Delay500ms();
SET_VALUE(0x00,5);
Delay500ms();
}
/******翻译函数******/
void translate(uchar *value,uchar *tran)
{
uchar i,j,temp; //temp用于保存中间量
for(i=0,j=0;i<8;i++,j++)
{
switch(value[j]) //翻译value里的字符值
{
case '0':temp=0xc0;break;
case '1':temp=0xf9;break;
case '2':temp=0xa4;break;
case '3':temp=0xb0;break;
case '4':temp=0x99;break;
case '5':temp=0x92;break;
case '6':temp=0x82;break;
case '7':temp=0xf8;break;
case '8':temp=0x80;break;
case '9':temp=0x90;break;
case 'A':temp=0x88;break;
case 'B':temp=0x83;break;
case 'C':temp=0xc6;break;
case 'D':temp=0xa1;break;
case 'E':temp=0x86;break;
case 'F':temp=0x8e;break;
case 'H':temp=0x89;break;
case 'L':temp=0xc7;break;
case 'N':temp=0xc8;break;
case 'P':temp=0x8c;break;
case 'U':temp=0xc1;break;
case '-':temp=0xbf;break;
case ' ':temp=0xff;break;
default:temp=0xff;break;
}
if(value[j+1]=='.') //小数点显示
{
temp &= 0x7f;
j++;
}
tran[i]=temp; //将value保存字符串翻译后赋给tran数组保存
}
}
/******显示函数******/
void display(uchar *tran,uchar wei)
{
P0 = 0xff; //将数码管段码清零
P2 = P2 & 0x1f | 0xe0; //选通Y7,赋予段码清零信号,消影
P2 = P2 & 0X1f; //关闭锁存器
P0 = 0x01 << wei; //位选左移1位
P2 = P2 & 0x1f | 0xc0; //选通Y6,赋予位选信号
P2 = P2 & 0X1f; //关闭锁存器
P0 = tran[wei]; //
P2 = P2 & 0x1f | 0xe0; //打开Y7,赋予段码信号
P2 = P2 & 0x1f; //关闭锁存器
}
/******定时器1初始化******/
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
/******定时器1中断服务函数******/
void Timer1() interrupt 3
{
count++;
display(tran,wei);
if(++wei==8)
wei=0;
if(relay_flag==1) //继电器开启
P0=0x10;P2=P2&0x1f|0xa0;P2=P2&0x1f;
if(relay_flag==0) //继电器断开
P0=0x00;P2=P2&0x1f|0xa0;P2=P2&0x1f;
if(light_flag) //LED点亮
{
light_flag=0;
switch((uint)(light/28.0))
{
case 0:{P0=0x00;P2=P2&0x1f|0x80;P2 = P2&0x1f;}break;
case 1:{P0=0x80;P2=P2&0x1f|0x80;P2 = P2&0x1f;}break;
case 2:{P0=0xc0;P2=P2&0x1f|0x80;P2 = P2&0x1f;}break;
case 3:{P0=0xe0;P2=P2&0x1f|0x80;P2 = P2&0x1f;}break;
case 4:{P0=0xf0;P2=P2&0x1f|0x80;P2 = P2&0x1f;}break;
case 5:{P0=0xf8;P2=P2&0x1f|0x80;P2 = P2&0x1f;}break;
case 6:{P0=0xfc;P2=P2&0x1f|0x80;P2 = P2&0x1f;}break;
case 7:{P0=0xfe;P2=P2&0x1f|0x80;P2 = P2&0x1f;}break;
case 8:{P0=0xff;P2=P2&0x1f|0x80;P2 = P2&0x1f;}break;
}
}
if(count%20==0) //独立按键扫描
key4();
if(count%200==0) //adc读取
{
adc_flag=1;
}
if(count%300==0) //数码管闪烁
blight_flag=~blight_flag;
}
/******设置函数******/
void set()
{
position=0; //每次进入设置状态,位置从0开始
while(!mode) //当设置模式时
{
switch(shift_state) //确定按键键值
{
case 2:{position++;if(position==4)position=0;shift_state=-1;}break; //S6按下,向右移一位
case 3:{num[position]++;shift_state=-1;}break; //调参位加1
case 4:{num[position]--;shift_state=-1;}break; //调参位减1
default:break;
}
switch(position) //确认位置
{
case 0:{if(num[0]>25)num[0]=25;if(num[0]<15)num[0]=15;}break; //第一页最高值在15-25之间
case 1:{if(num[1]>10)num[1]=10;if(num[1]<0)num[1]=0;}break; //第一页最低值在0-10之间
case 2:{if(num[2]>50)num[2]=50;if(num[2]<30)num[2]=30;if(num[2]<num[3])num[2]=num[3];}break; //第二页最高值在30-50之间且不能低于最低值
case 3:{if(num[3]>32)num[3]=32;if(num[3]<26)num[3]=26;if(num[2]<num[3])num[3]=num[2];}break; //第二页最低值在26-32之间且不能高于最高值
}
if(position/2==0) //第一页
{
if(position%2==1) //最低值闪烁
{
if(blight_flag==1)
{
sprintf(value,"1-H%2dL ",num[0]);
translate(value,tran);
}
if(blight_flag==0)
{
sprintf(value,"1-H%2dL%2d",num[0],num[1]);
translate(value,tran);
}
}
if(position%2==0) //最高值闪烁
{
if(blight_flag==1)
{
sprintf(value,"1-H L%2d",num[1]);
translate(value,tran);
}
if(blight_flag==0)
{
sprintf(value,"1-H%2dL%2d",num[0],num[1]);
translate(value,tran);
}
}
}
if(position/2==1) //第二页
{
if(position%2==1) //最低值闪烁
{
if(blight_flag==1)
{
sprintf(value,"2-H%2dL ",num[2]);
translate(value,tran);
}
if(blight_flag==0)
{
sprintf(value,"2-H%2dL%2d",num[2],num[3]);
translate(value,tran);
}
}
if(position%2==0) //最高值闪烁
{
if(blight_flag==1)
{
sprintf(value,"2-H L%2d",num[3]);
translate(value,tran);
}
if(blight_flag==0)
{
sprintf(value,"2-H%2dL%2d",num[2],num[3]);
translate(value,tran);
}
}
}
}
AT24c02_W(0,num[0]); //AT24C02保存
Delay5ms();
AT24c02_W(1,num[1]);
Delay5ms();
AT24c02_W(2,num[2]);
Delay5ms();
AT24c02_W(3,num[3]);
Delay5ms();
}
void work() //工作模式
{
if(adc_flag)
{
light=ADC(0x03); //读取光敏值
light_flag=1;
temperature=ADC(0x01); //读取温度
if(temperature==255)
temperature-=1;
adc_flag=0;
}
sprintf(value,"C-%2dL-%02d",(uint)(temperature/5.0),(uint)(light/28.0));
translate(value,tran);
if(temperature>=num[1]*5&&temperature<=num[0]*5) //温度在最大值和最小值之间,模拟电压
DAC((unsigned char)(255/(num[0]-num[1])*(num[0]-temperature/5)));
else if(temperature>num[0]*5) //温度超过最大值输出5V
DAC(0);
else if(temperature<num[1]*5) //温度低于最小值输出0V
DAC(255);
if((temperature/5)>num[2]) //温度大于第二页最高值继电器打开
relay_flag=1;
else //低于时继电器断开
relay_flag=0;
}
void main()
{
MCU_init(); //单片机初始化函数
bell_2times(); //蜂鸣器响2次
Timer1Init(); //定时器1初始化
num[0]=AT24c02_R(0); //AT24C02上电读取
Delay5ms();
num[1]=AT24c02_R(1);
Delay5ms();
num[2]=AT24c02_R(2);
Delay5ms();
num[3]=AT24c02_R(3);
Delay5ms();
while(1)
{
switch(mode) //扫描模式
{
case 0:set();break; //设置参数模式
case 1:work();break; //工作模式
default:break;
}
}
}
MCU_init.c
#include <STC15F2K60S2.H>
void MCU_init()
{
P2 = P2 & 0x1f | 0x80;P0 = 0xff; //打开锁存器Y4,关闭LED灯
P2 = P2 & 0x1f;
P2 = P2 & 0x1f | 0xa0;P0 = 0x00; //打开锁存器Y5,关闭继电器和蜂鸣器
P2 = P2 & 0x1f;
P2 = P2 & 0x1f | 0xc0;P0 = 0x00; //打开锁存器Y6,清楚锁存器中数码管位选信号
P2 = P2 & 0x1f;
P2 = P2 & 0x1f | 0xe0;P0 = 0xff; //打开锁存器Y7,清楚锁存器中数码管段码信号
P2 = P2 & 0x1f;
}
key4.c
#include <STC15F2K60S2.H>
#include "key4.h"
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
unsigned char shift_state=0;
unsigned char key4_scan=0;
unsigned char shift_times=0;
unsigned char mode=1;
void key4()
{
if(key4_scan==0) //第一次扫描
{
if((P3&0x0f) != 0x0f)
{
key4_scan=1;
}
}
else if(key4_scan==1) //第二次扫描
{
if((P3&0x0f) != 0x0f)
{
if(S7==0)
{
shift_times++;
switch(shift_times%2)
{
case 0:{mode=1;};break;
case 1:{mode=0;};break;
}
if(shift_times>=100)
shift_times=0;
key4_scan=2;
}
else if(S6==0)
{
shift_state=2;
key4_scan=2;
}
else if(S5==0)
{
shift_state=3;
key4_scan=2;
}
else if(S4==0)
{
shift_state=4;
key4_scan=2;
}
else
{
shift_state=4;
key4_scan=0;
}
}
}
else if(key4_scan==2) //第三次扫描
{
if((P3&0x0f)==0x0f)
{
key4_scan=0;
}
}
}
iic.c
#include <STC15F2K60S2.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;
}
unsigned char ADC(unsigned char Ain)
{
unsigned char dat;
IIC_Start();
IIC_SendByte(0x90); //写
IIC_WaitAck();
IIC_SendByte(Ain|0x40);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91); //读
IIC_WaitAck();
// IIC_RecByte();
// IIC_SendAck(0);
dat=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return dat;
}
void DAC(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90); //写
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
void AT24c02_W(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 int AT24c02_R(unsigned char addr)
{
unsigned int dat;
IIC_Start();
IIC_SendByte(0xa0); //写
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1); //读
IIC_WaitAck();
dat=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return dat;
}