前言:
师承小蜜蜂。头文件使用reg52.h。
赛题:
个人参考程序:(未使用模块化,程序有点乱)
main.c
#include <REGX52.H>
#include "DS1302.h"
#include "intrins.h"
#include "iic.h"
sfr P4=0xc0;
sbit TX=P1^0;
sbit RX=P1^1;
sbit L1=P4^4;
sbit L2=P4^2;
sbit L3=P3^5;
sbit L4=P3^4;
void HC573(unsigned char channel,unsigned char value);
void Delay(int x);
void Nixie(unsigned char column,unsigned char value);
void System_init();
unsigned char code Read_Ds1302[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};//时钟
unsigned char code Write_Ds1302_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char code Array[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
0xbf,0x7f};
unsigned char code Array_pot[10]={0x40,0x79,0X24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned char Time[]={0x55,0x59,0x23,0x00,0x00,0x00,0x00};//设置时间
unsigned char Key_Flag=1;//10ms循环扫描按键
unsigned char Mode_S4=0;//s4按键
unsigned char Mode_S5=0;//s5按键
unsigned int Distance;//超声波数据
unsigned char Mode_chao=0;//数据测量模式
unsigned char Mode_stroate=0;//数据记录页面模式
unsigned char Time_collect=2;//采集时间参数
unsigned char Distance_collect=20;//采集距离参数
//参数需要退出页面后生效,故设置中间变量代替
unsigned char Time_collect1=2;
unsigned char Distance_collect1=20;
unsigned char Flag_chao=0;//超声波采集标志位(定时模式)
unsigned char Rb2_Data=0;//光敏电阻读取
unsigned char Flag_chao1=0;//超声波采集标志位(触发模式)
unsigned char chao_Max=0;//最大值
unsigned char chao_Min=200;//最小值
unsigned int chao_ave=0;//平均值
unsigned char Array_chao[50];//存放数据数组
unsigned int cnt=0;//记录次数
unsigned char Flag_alarm=0;//报警标志位
unsigned char cnt_alarm=0;//警报次数
unsigned char LED_Stat=0xff;//灯光
unsigned char LED=0xff;
//光敏电阻读取
void Read_RB2()
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x41);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
Rb2_Data=I2CReceiveByte();
I2CSendAck(1);
I2CStop();
}
//设置DAC
void Set_DAC()
{
unsigned char tem;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x41);
I2CWaitAck();
if(cnt!=0)
{
if(Array_chao[cnt-1]<10)
{
I2CSendByte(51);
}
else if(Array_chao[cnt-1]>80)
{
I2CSendByte(255);
}
else
{
tem=(3*Array_chao[cnt-1])+15;
I2CSendByte(tem);
}
}
I2CSendAck(1);
I2CStop();
}
//定时器初始化
void Time_init()
{
TMOD=0x01;
TH0=(65535-10000+1)/256;
TL0=(65535-10000+1)%256;
ET0=1;
TR0=1;
TF0=0;
EA=1;
}
//按键
unsigned char Key_Scan()
{
unsigned char Ket_Value;
unsigned int Key_temp;
L1=0;L2=1;L3=1;L4=1;P3|=0x0F;
Key_temp=P3&0x0f;
L1=1;L2=0;L3=1;L4=1;P3|=0x0F;
Key_temp=(Key_temp<<4)|(P3&0x0f);
L1=1;L2=1;L3=0;L4=1;P3|=0x0F;
Key_temp=(Key_temp<<4)|(P3&0x0f);
L1=1;L2=1;L3=1;L4=0;P3|=0x0F;
Key_temp=(Key_temp<<4)|(P3&0x0f);
switch(~Key_temp)
{
case 0x8000:Ket_Value=4;break;
case 0x4000:Ket_Value=5;break;
case 0x2000:Ket_Value=6;break;
case 0x1000:Ket_Value=7;break;
case 0x0800:Ket_Value=8;break;
case 0x0400:Ket_Value=9;break;
case 0x0200:Ket_Value=10;break;
case 0x0100:Ket_Value=11;break;
case 0x0080:Ket_Value=12;break;
case 0x0040:Ket_Value=13;break;
case 0x0020:Ket_Value=14;break;
case 0x0010:Ket_Value=15;break;
case 0x0008:Ket_Value=16;break;
case 0x0004:Ket_Value=17;break;
case 0x0002:Ket_Value=18;break;
case 0x0001:Ket_Value=19;break;
default :Ket_Value=0;
}
return Ket_Value;
}
//时钟初始化
void Ds1302_init()
{
unsigned char i;
Write_Ds1302_Byte(0x8e,0x00);
for(i=0;i<7;i++)
{
Write_Ds1302_Byte(Write_Ds1302_address[i],Time[i]);
}
Write_Ds1302_Byte(0x8e,0x80);
}
//超声波测距
void Delay12us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 28;
while (--i);
}
void Send_Wave()
{
unsigned char i;
for(i=0;i<8;i++)
{
TX=1;
Delay12us();
TX=0;
Delay12us();
}
}
void Time_Chao()
{
unsigned int temp;
TMOD&=0x01;
TH1=0x00;
TL1=0x00;
Send_Wave();
TR1=1;
while((RX==1)&&(TF1==0));
TR1=0;
if(TF1==0)
{
temp=TH1;
temp=(temp<<8)|TL1;
Distance=((temp/10)*17)/100+3;
}
else
{
TF1=0;
}
TH1=0x00;
TL1=0x00;
Flag_chao=0;
Flag_chao1=0;//清除标志位,确保每次只测量一次
}
//读取时钟
void Read_time()
{
unsigned char i;
for(i=0;i<7;i++)
{
Time[i]=Read_Ds1302_Byte(Read_Ds1302[i]);
}
}
void Key_Read()
{
unsigned char Key_Temp,Key_Up;
static unsigned char Key_Old=0;
if(Key_Flag)return;
Key_Flag=1;
Key_Temp=Key_Scan();
Key_Up=~Key_Temp&(Key_Temp^Key_Old);
Key_Old=Key_Temp;
if(Key_Up==4)
{
if(Mode_S4==0){Mode_S4=1;Mode_S5=0;}//S4切换时,都回到模式的第一个页面
else if(Mode_S4==1)
{
Mode_S4=0;Mode_S5=0;
Time_collect=Time_collect1;//退出页面,参数生效
Distance_collect=Distance_collect1;
}
}
else if(Key_Up==5)
{
if(Mode_S4==0)
{
if(Mode_S5==0){Mode_S5=1;}
else if(Mode_S5==1)
{
Mode_S5=2;
Mode_stroate=0;//每次进入数据记录页面,都是最大值页面
}
else if(Mode_S5==2)Mode_S5=0;
}
else if(Mode_S4==1)//参数设置页面切换
{
if(Mode_S5==0)Mode_S5=1;
else if(Mode_S5==1)Mode_S5=0;
}
}
else if(Key_Up==8)
{
if(Mode_S4==0)
{
if(Mode_S5==1)//超声波模式切换
{
if(Mode_chao==0)Mode_chao=1;
else if(Mode_chao==1)Mode_chao=0;
}
else if(Mode_S5==2)//数据记录页面切换
{
if(Mode_stroate==0)Mode_stroate=1;
else if(Mode_stroate==1)Mode_stroate=2;
else if(Mode_stroate==2)Mode_stroate=0;
}
}
}
else if(Key_Up==9)
{
if(Mode_S4==1)
{
if(Mode_S5==0)//参数设置
{
if(Time_collect1==2)Time_collect1=3;
else if(Time_collect1==3)Time_collect1=5;
else if(Time_collect1==5)Time_collect1=9;
else if(Time_collect1==9)Time_collect1=2;
}
else if(Mode_S5==1)
{
Distance_collect1+=10;
if(Distance_collect1>80)Distance_collect1=10;
}
}
}
}
//显示时间页面
void Display_time()
{
Nixie(1,Array[Time[2]/16]);
Nixie(2,Array[Time[2]%16]);
Nixie(3,Array[16]);
Nixie(4,Array[Time[1]/16]);
Nixie(5,Array[Time[1]%16]);
Nixie(6,Array[16]);
Nixie(7,Array[Time[0]/16]);
Nixie(8,Array[Time[0]%16]);
}
//距离数据页面
void Display_Distance()
{
Nixie(1,0xc7);
if(Mode_chao==0)Nixie(2,Array[12]);
else if(Mode_chao==1)Nixie(2,Array[15]);
Nixie(3,0xff);
Nixie(4,0xff);
Nixie(5,0xff);
if(Distance>99)Nixie(6,Array[Distance/100%10]);else Nixie(6,0xff);
if(Distance>9)Nixie(7,Array[Distance/10%10]);else Nixie(7,0xff);
Nixie(8,Array[Distance%10]);
}
//数据记录页面
void Display_DataStorate()
{
Nixie(1,0x89);
if(Mode_stroate==1)
{
Nixie(2,Array[16]);
if(chao_ave>1000)Nixie(5,Array[chao_ave/1000%10]);
if(chao_ave>100)Nixie(6,Array[chao_ave/100%10]);
Nixie(7,Array_pot[chao_ave/10%10]);
Nixie(8,Array[chao_ave%10]);
}
else if(Mode_stroate==0)
{
Nixie(2,0xfe);
Nixie(5,0xff);
if(chao_Max>99)Nixie(6,Array[chao_Max/100%10]);
if(chao_Max>9)Nixie(7,Array[chao_Max/10%10]);
Nixie(8,Array[chao_Max%10]);
}
else if(Mode_stroate==2)
{
Nixie(2,0xf7);
Nixie(5,0xff);
if(chao_Min>99)Nixie(6,Array[chao_Min/100%10]);
if(chao_Min>9)Nixie(7,Array[chao_Min/10%10]);
Nixie(8,Array[chao_Min%10]);
}
Nixie(3,0xff);
Nixie(4,0xff);
}
//参数设置页面
void Display_Para()
{
Nixie(1,0x8c);
Nixie(3,0xff);
Nixie(4,0xff);
Nixie(5,0xff);
Nixie(6,0xff);
if(Mode_S5==0)
{
Nixie(2,Array[1]);
Nixie(7,Array[Time_collect1/10%10]);
Nixie(8,Array[Time_collect1%10]);
}
else if(Mode_S5==1)
{
Nixie(2,Array[2]);
Nixie(7,Array[Distance_collect1/10%10]);
Nixie(8,Array[Distance_collect1%10]);
}
}
//页面显示选择函数
void Display_All()
{
if(Mode_S4==0)
{
if(Mode_S5==0)
{
Display_time();
}
else if(Mode_S5==1)
{
Display_Distance();
}
else if(Mode_S5==2)
{
Display_DataStorate();
}
}
else if(Mode_S4==1)
{
Display_Para();
}
}
//最大值,最小值,平均值计算
void calculate_data()
{
unsigned char i;
unsigned int sum=0;
Array_chao[cnt]=Distance;
if(Mode_chao==1)//如果是触发模式
{
if(((Array_chao[cnt]-Distance_collect)<=5)||((Distance_collect-Array_chao[cnt])<=5))
{//当前测量数据在参数±5cm范围内
cnt_alarm++;//警报次数+1
}
else
{
cnt_alarm=0;//否则警报次数清零
}
if(cnt_alarm>=3)//如果警报次数大于3
{
Flag_alarm=1;//警报标志位
}
else
{
Flag_alarm=0;
}
}
cnt++;
for(i=0;i<cnt;i++)
{
sum+=Array_chao[i];
}
chao_ave=sum*10/cnt;//平均值,扩大10倍算小数
if(Distance>chao_Max)//最大值
{
chao_Max=Distance;
}
if(Distance<chao_Min)//最小值
{
chao_Min=Distance;
}
}
//超声波模式选择
void Mode_Choose()
{
if(Mode_S5==1)
{
if(Mode_chao==0)//触发模式
{
Read_RB2();//读光敏电阻
if(Rb2_Data>100)//亮
{
Flag_chao1=1;//置标志位
}
else if((Flag_chao1==1)&&(Rb2_Data<100))//如果标志位为1且变为暗模式
{//执行一次超声波测量,和数据计算
Time_Chao();
calculate_data();
}
}
else if(Mode_chao==1)//定时模式
{
if(((Time[0]%Time_collect)==0)&&(Flag_chao==1))//当标识位为1且满足条件
{//执行一次超声波测量
Time_Chao();
calculate_data();
}
else if((Time[0]%Time_collect)!=0)
{//当过了能被时间参数整除的那一秒,再重新置标志位
Flag_chao=1;
}
}
}
}
//灯光使用
void LED_Run()
{
if(Mode_S4==0)
{
if(Mode_S5==0)//LED1
{
LED_Stat=LED&0xfe;
HC573(4,LED_Stat);
}
else if(Mode_S5==1)//LED2
{
LED_Stat=LED&0xfd;
HC573(4,LED_Stat);
}
else if(Mode_S5==2)//LED3
{
LED_Stat=LED&0xfb;
HC573(4,LED_Stat);
}
if(Mode_chao==0)//LED4
{
LED_Stat=LED_Stat&0xf7;
HC573(4,LED_Stat);
}
if((Mode_chao==1)&&(Mode_S5==1))
{
if(Flag_alarm==1)//警报灯
{
LED_Stat=LED_Stat&0xef;
HC573(4,LED_Stat);
}
else
{
LED_Stat=LED_Stat|0x10;
HC573(4,LED_Stat);
}
}
else
{
LED_Stat=LED_Stat|0x10;
HC573(4,LED_Stat);
}
}
else if(Mode_S4==1)//参数设置页面关闭LED1,2,3
{
LED_Stat=LED_Stat|0x07;
HC573(4,LED_Stat);
}
if(Rb2_Data>100)//亮状态L6
{
LED_Stat=LED_Stat&0xdf;
HC573(4,LED_Stat);
}
else
{
LED_Stat=LED_Stat|0x20;
HC573(4,LED_Stat);
}
}
void main()
{
System_init();
while(1)
{
Mode_Choose();
Read_time();
Key_Read();
Display_All();
LED_Run();
Set_DAC();
}
}
void Time0() interrupt 1
{
TH0=(65535-10000+1)/256;
TL0=(65535-10000+1)%256;
Key_Flag=0;//10ms刷新一次按键
}
void System_init()
{
HC573(4,0xff);
HC573(5,0x00);
Time_init();
Ds1302_init();
}
void HC573(unsigned char channel,unsigned char value)
{
P2=(0x1f&P2)|0x00;
P0=value;
switch(channel)
{
case 4:P2=(0x1f&P2)|0x80;break;
case 5:P2=(0x1f&P2)|0xa0;break;
case 6:P2=(0x1f&P2)|0xc0;break;
case 7:P2=(0x1f&P2)|0xe0;break;
case 0:P2=(0x1f&P2)|0x00;break;
}
P2=(0x1f&P2)|0x00;
}
void Delay(int x) //@12.000MHz
{
unsigned char i, j;
while(x--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
void Nixie(unsigned char column,unsigned char value)
{
HC573(6,0x01<<(column-1));
HC573(7,value);
Delay(1);
HC573(6,0x01<<(column-1));
HC573(7,0xff);
}
ds1302.c:
#include <REGX52.H>
#include "intrins.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;
//
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
ds1302.h
#ifndef __DS1302_H_
#define __DS1302_H_
void Write_Ds1302(unsigned char temp) ;
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte ( unsigned char address );
#endif
iic.c
#include <REGX52.H>
#include "intrins.h"
sbit scl=P2^0;
sbit sda=P2^1;
#define DELAY_TIME 5
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
iic.h
#ifndef __IIC_H_
#define __IIC_H_
void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);
#endif