other.h
#ifndef __OTHER_H_
#define __OTHER_H_
#include <stc15f2k60s2.h>
#include "intrins.h"
sbit TX = P1^0;
sbit RX = P1^1;
void close_perl(void);
unsigned char seg_tran(int num);
void seg_disp(int adr,int num);
void seg_disp_f(int adr,int num);
int key_scan(void);
void Delay2ms(void);
void Delay12us(void);
void output_b(void);
void Timer0Init(void);
unsigned char distance_get(void);
#endif
other.c
#include <other.h>
void close_perl(void)//关闭外设
{
P0 = 0xff;
P2 = P2&0x1f|0x80;
P2 = P2&0x1f;
P0 = 0x00;
P2 = P2&0x1f|0xa0;
P2 = P2&0x1f;
}
unsigned char seg_tran(int num)//数码管转置
{
unsigned char date;
switch(num)
{
case 0: date = 0xC0;break;
case 1: date = 0xF9;break;
case 2: date = 0xA4;break;
case 3: date = 0xB0;break;
case 4: date = 0x99;break;
case 5: date = 0x92;break;
case 6: date = 0x82;break;
case 7: date = 0xF8;break;
case 8: date = 0x80;break;
case 9: date = 0x90;break;
case 10: date = 0xbf;break;//-
case 11: date = 0xc7;break;//L
case 12: date = 0x8e;break;//f
case 13: date = 0xc6;break;//c
case 14: date = 0x89;break;//H
case 15: date = 0xfe;break;//上
case 16: date = 0xf7;break;//下
case 17 : date = 0x8c ; break;//p
}
return date;
}
void seg_disp(int adr,int num)//数码管显示
{
unsigned char seg_adr[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
P2 = P2&0x1f|0xe0;
P2 = P2&0x1f;
P0 = seg_adr[adr];
P2 = P2&0x1f|0xc0;
P2 = P2&0x1f;
P0 = seg_tran(num);
P2 = P2&0x1f|0xe0;
P2 = P2&0x1f;
}
void seg_disp_f(int adr,int num)//数码管显示(含小数点)
{
unsigned char seg_adr[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
P2 = P2&0x1f|0xe0;
P2 = P2&0x1f;
P0 = seg_adr[adr];
P2 = P2&0x1f|0xc0;
P2 = P2&0x1f;
P0 = seg_tran(num)&0x7f;
P2 = P2&0x1f|0xe0;
P2 = P2&0x1f;
}
int key_scan(void)//矩阵按键扫描
{
int key_mark,key;
P3 = 0x0f;
P44 = 0;P42 = 1;P35 = 1;P34 = 1;
key = P3;
P44 = 1;P42 = 0; key = (key<<4)|(P3&0x0f);
P42 = 1;P35 = 0; key = (key<<4)|(P3&0x0f);
P35 = 1;P34 = 0; key = (key<<4)|(P3&0x0f);
switch(~key)
{
case 0x8000: key_mark = 4;break;
case 0x4000: key_mark = 5;break;
case 0x0800: key_mark = 8;break;
case 0x0400: key_mark = 9;break;
default: key_mark = 0;break;
}
return key_mark;
}
void Delay2ms() //@12.000MHz
{
unsigned char i, j;
i = 24;
j = 85;
do
{
while (--j);
} while (--i);
}
void Timer0Init(void) //12微秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xF4; //设置定时初值
TH0 = 0xFF; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 0; //定时器0开始计时
}
unsigned char distance_get(void)
{
unsigned char distance, num = 10;
TX = 0;
TL0 = 0xF4;
TH0 = 0xFF;
TR0 = 1;
while(num --)
{
while(!TF0);
TX ^= 1;
TF0 = 0;
}
TR0 = 0;
TL0 = 0;
TH0 = 0;
TR0 = 1;
while(RX && !TF0);
TR0 = 0;
if(TF0)
{
TF0 = 0;
distance = 255;
}
else
distance = ((TH0 << 8) + TL0) * 0.017;
return distance;
}
iic.c
void dac_pcf(unsigned char dac)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_SendByte(dac);
IIC_WaitAck();
IIC_Stop();
}
unsigned char adc_pcf(void)
{
unsigned char adc;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x41);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
adc = IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return adc;
}
mian.c
#include <other.h>
#include <iic.h>
#include <ds1302.h>
#define led1 0x01
#define led2 0x02
#define led3 0x04
#define led4 0x08
#define led5 0x10
#define led6 0x20
unsigned char key_old;
unsigned char dac;
unsigned char adc;
unsigned int distance;
unsigned int distance_ever;
bit disp_mode;//界面切换
char perl_mode;//外设切换
bit chuma_mode;//触发模式
char jilu_mode;//数据记录模式
char c_mode;//参数模式
bit light_mode; //光照强度,0为暗,1为常光
bit light_mode_old;//旧光照强度
bit light_mode_new;//新光照强度
char time_c_mode;//时间参数模式
char time_c_sz[5] = {2,3,5,7,9};//时间参数
char time_c;
unsigned char distance_c = 10;//距离参数
unsigned char ds1302_write[3] = {0x80,0x82,0x84};
unsigned char ds1302_read[3] = {0x81,0x83,0x85};
unsigned char ds1302_first[3] = {0x00,0x20,0x20};
unsigned char dis_max = 0;
unsigned char dis_min = 0;
unsigned int dis_all_10;//所有距离之和*10
unsigned int dis_arr_10;//所有距离之和平均值*10
unsigned int dis_number = 0;//采集次数
unsigned int over_times = 0;//超出范围次数
bit led5_ok = 0;
void ds1302_init(void)
{
int t;
Write_Ds1302_Byte(0x8e,0);//关闭写保护
for(t = 0; t < 3; t++)
{
Write_Ds1302_Byte(ds1302_write[t],ds1302_first[t]);//写入时间
}
Write_Ds1302_Byte(0x8e,1);//开启写保护
}
void key_pro(void)
{
unsigned char key_vol,key_down;
key_vol = key_scan();
key_down = key_vol&(key_vol^key_old);
key_old = key_vol;
switch(key_down)
{
case 4://界面切换按键
disp_mode = ~disp_mode;
// 0为数据显示
// 1为参数设置
break;
case 5:
if(disp_mode == 1)//参数设置界面选择
{
perl_mode = 0;
c_mode ++;
if(c_mode == 2) c_mode = 0;//采集时间 距离参数
}
else if(disp_mode == 0)//数据显示界面选择
{
c_mode = 0;
perl_mode ++;
if(perl_mode == 3) perl_mode = 0;//时间 距离 数据记录
}
break;
case 8:
if((disp_mode == 0)&&(perl_mode == 1)) chuma_mode = ~chuma_mode;//其他触发 定时
else if((disp_mode == 0)&&(perl_mode == 2))
{
jilu_mode ++;
if(jilu_mode == 3) jilu_mode = 0;//大 均 小
}
break;
case 9:
if((disp_mode == 1)&&(c_mode == 0))
{
time_c_mode ++;
if(time_c_mode == 5) time_c_mode = 0;
time_c = time_c_sz[time_c_mode];
}
else if((disp_mode == 1)&&(c_mode == 1))
{
distance_c = distance_c + 10;
if(distance_c == 90) distance_c = 10;
}
break;
}
}
void other_pro(void)
{
adc = adc_pcf();//电压读出
dac_pcf(dac);//电压写入
distance_ever = distance_get();//一直测
//判断光照强度
if(adc > 40) light_mode = 1;
else light_mode = 0;
light_mode_new = light_mode;
//dac输出函数
if(distance <= 10) dac = 51;
else if((distance > 10)&&(distance <= 80)) dac = 3*distance+23;
else dac = 255;
//距离采集
if(chuma_mode == 0)//触发采集
{
if((light_mode_new == 0)&&(light_mode_old == 1))//由亮变暗
{
distance = distance_ever;//距离采集一次
dis_number = dis_number+1;//采集次数加一次
if(distance > dis_max) dis_max = distance;//大于最大值,则替换
if(distance < dis_min) dis_min = distance;//小于最小值,则替换
dis_all_10 = dis_all_10 + distance*10;
dis_arr_10 = dis_all_10/dis_number;
if((distance < distance_c+5)&&(distance > distance_c-5)) over_times ++;//参数约定范围
else over_times = 0;
}
}
else if(chuma_mode == 1)//定时采集
{
if( ((Read_Ds1302_Byte(ds1302_read[0])/16*10 + Read_Ds1302_Byte(ds1302_read[0])%16) % time_c) == 0 )
{
distance = distance_ever;//距离采集一次
dis_number = dis_number+1;//采集次数加一次
if(distance > dis_max) dis_max = distance;//大于最大值,则替换
if(distance < dis_min) dis_min = distance;//小于最小值,则替换
dis_all_10 = dis_all_10 + distance*10;
dis_arr_10 = dis_all_10/dis_number;
if((distance < distance_c+5)&&(distance > distance_c-5)) over_times ++;//参数约定范围
else over_times = 0;
}
}
if(over_times >= 3) led5_ok = 1;//允许led5亮
else led5_ok = 0;
light_mode_old = light_mode;
}
void seg_pro(void)
{
//时间数据显示界面
if(disp_mode == 0)//数据界面
{
if(perl_mode == 0)//时间参数
{
seg_disp(0,Read_Ds1302_Byte(ds1302_read[2])/16);Delay2ms();
seg_disp(1,Read_Ds1302_Byte(ds1302_read[2])%16);Delay2ms();
seg_disp(2,10);Delay2ms();
seg_disp(3,Read_Ds1302_Byte(ds1302_read[1])/16);Delay2ms();
seg_disp(4,Read_Ds1302_Byte(ds1302_read[1])%16);Delay2ms();
seg_disp(5,10);Delay2ms();
seg_disp(6,Read_Ds1302_Byte(ds1302_read[0])/16);Delay2ms();
seg_disp(7,Read_Ds1302_Byte(ds1302_read[0])%16);Delay2ms();
}
else if(perl_mode == 1)//距离参数
{
seg_disp(0,11);Delay2ms();
if(chuma_mode == 0) {seg_disp(1,13);Delay2ms();}
else if(chuma_mode == 1) {seg_disp(1,12);Delay2ms();}
if(distance > 100) seg_disp(5,distance/100);Delay2ms();
if(distance > 10) seg_disp(6,distance%100/10);Delay2ms();
seg_disp(7,distance%10);Delay2ms();
}
else if(perl_mode == 2)//距离记录
{
seg_disp(0,14);Delay2ms();//H
switch(jilu_mode)
{
case 0:
seg_disp(1,15);Delay2ms();
if(dis_max > 100) seg_disp(5,dis_max/100);Delay2ms();
if(dis_max > 10) seg_disp(6,dis_max%100/10);Delay2ms();
seg_disp(7,dis_max%10);Delay2ms();
break;
case 1:
seg_disp(1,10);Delay2ms();
if(dis_arr_10 > 1000) seg_disp(4,dis_arr_10/1000);Delay2ms();
if(dis_arr_10 > 100) seg_disp(5,dis_arr_10%1000/100);Delay2ms();
seg_disp_f(6,dis_arr_10%100/10);Delay2ms();
seg_disp(7,dis_arr_10%10);Delay2ms();
break;
case 2:
seg_disp(1,16);Delay2ms();
if(dis_min > 100) seg_disp(5,dis_min/100);Delay2ms();
if(dis_min > 10) seg_disp(6,dis_min%100/10);Delay2ms();
seg_disp(7,dis_min%10);Delay2ms();
break;
}
}
}
else if(disp_mode == 1)//参数
{
if(c_mode == 0)
{
seg_disp(0,17);Delay2ms();
seg_disp(1,1);Delay2ms();
seg_disp(6,time_c_sz[time_c_mode]/10);Delay2ms();
seg_disp(7,time_c_sz[time_c_mode]%10);Delay2ms();
}
else if(c_mode == 1)
{
seg_disp(0,17);Delay2ms();
seg_disp(1,2);Delay2ms();
seg_disp(6,distance_c/10);Delay2ms();
seg_disp(7,distance_c%10);Delay2ms();
}
}
}
void led_pro(void)
{
P0 = 0xff;
//Led1
if((disp_mode == 0)&&(perl_mode == 0)) P0 = P0&(~led1);
else P0 = P0|(led1);
//led2
if((disp_mode == 0)&&(perl_mode == 1)) P0 = P0&(~led2);
else P0 = P0|(led2);
//led3
if((disp_mode == 0)&&(perl_mode == 2)) P0 = P0&(~led3);
else P0 = P0|(led3);
//led4
if(chuma_mode == 0) P0 = P0&(~led4);
else P0 = P0|(led4);
//led5
if(led5_ok == 1) P0 = P0&(~led5);
else P0 = P0|(led5);
//Led6
if(light_mode == 1) P0 = P0&(~led6);
else P0 = P0|(led6);
P2 = P2&0x1f|0x80;
P2 = P2&0x1f;
}
void main(void)
{
close_perl();
Timer0Init();
ds1302_init();
dis_min = distance_get();//最小值先取一个值
while(1)
{
key_pro();
other_pro();
seg_pro();
led_pro();
}
}