#include "stc15.h"
#include <intrins.h>
#include <stdio.h>
//-----------------------------------------------
#define FOSC 12000000L
//#define T1MS (65536-FOSC/1000) //1T模式
#define T1MS (65536-FOSC/12/1000) //12T模式
//全局变量
unsigned int cnt1ms=0;
//RTC变量************
u8 shi=11;
u8 fen=43;
u8 miao=54;
void ReadRTC(void);
void InitRTC();
//报警
u8 led4flag=0;
u8 led5flag=0;
u8 led6flag=0;
//*****************温度
float wendumax=0.0f;//温度最大值
float wenducs=30.0f;//温度参数
float wendunow=0.0f;//温度当前值
float wenduave=0.0f;//温度平均值
float readwendu();
float wendusum=0;
float shidusum=0;
//PCF8591数据
u8 in1dat=0;
u8 readIN1(void);
//湿度计算,NE555
unsigned int freqnum=0;
unsigned int pulnum=0;
float shidunow=0.0f;
float shidumax=0.0f;
float shiduave=0.0f;
u8 shiduerr=0;
u8 flag555=0;
float shiducal(unsigned int x);
//界面
u8 pagex=1;//1 20 21 22 3 4
u8 pageM=0;
u8 page1cnt=0;
u8 page2cnt=0;
void PageProc();
unsigned int cfcnt=0;
u8 cfshi=0;//触发小时
u8 cffen=0;//触发分
u8 cfflag=0;//触发标记
void cfread();//触发判断
int cftime=0;
//延时函数
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
void delayms(int nms)
{
int i;
for(i=0;i<nms;i++)
{
Delay1ms();
}
}
//****************************************************************************
//位操作函数,置1清0取反位读
u8 bitSet(u8 x,u8 pos)
{
u8 res;
res=x|(1<<pos);
return res;
}
u8 bitReset(u8 x,u8 pos)
{
u8 res;
res=x&(~(1<<pos));
return res;
}
u8 bitRead(u8 x,u8 pos)
{
u8 res;
res=(x>>pos)&0x01;
return res;
}
u8 bitTog(u8 x,u8 pos)
{
u8 res;
res=x^(1<<pos);
return res;
}
//***************
#define LEDY 0 //定义主时钟
#define SMGABCY 1 //定义主时钟
#define SMGCOMY 2 //定义主时钟
#define ULNY 3 //定义主时钟
#define NONE 4 //定义主时钟
//选择573
void s573(u8 x)
{
switch(x)
{
case LEDY:P2=(P2&0x1F)|0x80;break;//y4 100 0 0000
case SMGABCY:P2=(P2&0x1F)|0xe0;break;//7 1110 0000
case SMGCOMY:P2=(P2&0x1F)|0xc0;break;//6 1100 0000
case ULNY:P2=(P2&0x1F)|0xa0;break;//5
case NONE:P2=P2&0x1F;break;
}
}
//****************************************************************************
//LED函数
u8 u8LED=0xff;//熄灭初始
#define L1 0
#define L2 1
#define L3 2
#define L4 3
#define L5 4
#define L6 5
#define L7 6
#define L8 7
void LEDonx(u8 i) //0点亮
{
u8LED=bitReset(u8LED,i);
}
void LEDoffx(u8 i) //1mie
{
u8LED=bitSet(u8LED,i);
}
void LEDshow(u8 x) //1mie
{
u8LED=x;
s573(NONE);
P0=u8LED;
s573(LEDY);
s573(NONE);
}
//ULN2003函数,本次比赛没用到
u8 u8ULN=0x00;//熄灭初始
//void LEDonx(u8 i) //0点亮
//{
// u8LED=bitReset(u8LED,i);
//}
//void LEDoffx(u8 i) //1mie
//{
// u8LED=bitSet(u8LED,i);
//}
void ULNshow(u8 x) //1mie
{
u8ULN=x;
s573(NONE);
P0=u8ULN;
s573(ULNY);
s573(NONE);
}
//****************************************************************************
//数码管函数
//位码,段码,转换函数,显示函数,stc-isp
/************* 本地常量声明 **************/
u8 code t_display[]={ //标准字库,共阴极,要取反
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
/************* 本地变量声明 **************/
u8 smgbuf[20];
u8 LED8[20]; //显示缓冲,改为20,实际显示需要前面8个
u8 display_index; //显示位索引
bit B_1ms; //1ms标志
/********************** 显示扫描函数 ************************/
void DisplayScan(void)
{
//消隐
s573(NONE);
P0=0x00;
s573(SMGCOMY);
s573(NONE);
s573(NONE);
P0=0xff;
s573(SMGABCY);
//显示,位选,段码
s573(NONE);
P0=T_COM[display_index];//我们不用取反,
s573(SMGCOMY);
s573(NONE);
P0=LED8[display_index];
s573(SMGABCY);
s573(NONE);
//锁存输出数据
if(++display_index >= 8) display_index = 0; //8位结束回0
}
//数码管转换函数
void smgconv(void)
{
u8 i=0,j=0,temp=0;
while(smgbuf[i]!=0)
{
switch(smgbuf[i])
{
case '0':temp=~t_display[0];break;//记得取反
case '1':temp=~t_display[1];break;//记得取反
case '2':temp=~t_display[2];break;//记得取反
case '3':temp=~t_display[3];break;//记得取反
case '4':temp=~t_display[4];break;//记得取反
case '5':temp=~t_display[5];break;//记得取反
case '6':temp=~t_display[6];break;//记得取反
case '7':temp=~t_display[7];break;//记得取反
case '8':temp=~t_display[8];break;//记得取反
case '9':temp=~t_display[9];break;//记得取反 CHPEF-
case 'C':temp=~0x39;break;//记得取反 CHPEF-
case 'H':temp=~0x76;break;//记得取反 CHPEF-
case 'P':temp=~0x73;break;//记得取反 CHPEF-
case 'E':temp=~0x79;break;//记得取反 CHPEF-
case '-':temp=~0x40;break;//记得取反 CHPEF-
case 'F':temp=~0x71;break;//记得取反 CHPEF-
default :temp=0xFF;break;
}
if(smgbuf[i+1]=='.')
{
temp &=0x7f;
i++;
}
i++;
LED8[j]=temp;
j++;
}
}
//****************************************************************************
//按键函数,S4 5 8 9
//长按,短按
int longtime=0;
int longtimeflag=0;
u8 key10ms=0;
u8 key10msflag=0;
u8 readkey(void)
{
//列扫描
u8 keyx=0;
P44=0;P42=1;
if(P32==0)keyx=5;
else if(P33==0)keyx=4;
P44=1;P42=0;
if(P32==0)keyx=9;
else if(P33==0)keyx=8;
return keyx;
}
//按键判断,重要步骤
void KeyProc()
{
//按键当前值,按键下降,按键上升沿,上一次按键值
static u8 keyold=0;
u8 keynow=0;
u8 keydown=0;
u8 keyup=0;
//去抖动,10ms进来一次
if(key10msflag==1)
{
key10msflag=0;
}
else return;
//读取按键
keynow=readkey();
keydown=keynow &(keyold^keynow);
keyup=~keynow &(keyold^keynow);
keyold=keynow;
if(keydown)
{
longtime=0;
//sprintf(smgbuf,"CCCCCCCC");//8个字符长度,占据完数码管
// smgconv();
}
//**********************************按键松开
if(keyup)
{
if(longtimeflag==0)
{
//只有4个按键,因此不用switch了
if(keyup==4)
{
// sprintf(smgbuf,"CHCHH%3d",(unsigned int)keyup);//8个字符长度,占据完数码管
// smgconv();
flag555=1;
freqnum=0;
pulnum=0;
TR0=1;//开始计算频率
//1 2 3 4
// if(pagex==0)pagex=1;
if(pagex==1)
{
pagex=2;
page2cnt=0;//每次切入界面2,都是温度回显
}
else if(pagex==2)pagex=3;
else if(pagex==3)pagex=1;
}
else if(keyup==5)
{
if(pagex==2)
{
if(page2cnt==0)page2cnt=1;
else if(page2cnt==1)page2cnt=2;
else if(page2cnt==2)page2cnt=0;
}
}
//***************************按键8
else if(keyup==8)
{
if(pagex==3)
{
if(wenducs>90)wenducs=0;
else wenducs++;
}
}
//*********************按键9
else if(keyup==9)
{
if(pagex==3)
{
if(wenducs<0)wenducs=90;
else wenducs--;
}
}
}
else if(longtimeflag==1)longtimeflag=0;
}
//***********长按,只有判断长按9
if(keyold &&(longtime>2000))
{
longtime=0;
longtimeflag=1;
if(keyold==9)
{
if(pagex==2 &&page2cnt==2)//回显界面,时间回显之
{
cfcnt=0;//触发次数=0
wendumax=0;
shidumax=0;
wenduave=0;
shiduave=0;
cfshi=0;
cffen=0;
}
}
}
}
void LedProc();
//定时器0计数脉冲NE555,定时器1滴答定时器
void main()
{
//测试一下上面的函数,一个个模块来。
float wendu=12.52;
int shidumax=123;
LEDshow(0xFF);//开机关闭LED灯;
ULNshow(0x00);//开机关闭LED灯;
sprintf(smgbuf," ");//清屏
smgconv();
readwendu();
readwendu();
delayms(800);//消除一开始的85
InitRTC();//初始化时间
TMOD |= 0x04; //设置定时器0为16位自动重装载外部记数模式
TH0 = TL0 = 0xff; //设置定时器0初始值
TR0 = 1; //定时器0开始工作,一开始不工作
ET0 = 1; //开定时器0中断
TMOD |= 0x00; //设置定时器为模式0(16位自动重装载)
TL1 = T1MS; //初始化计时值
TH1 = T1MS >> 8;
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器0中断
EA=1;
while(1)
{
if(cnt1ms%100==0)
{
ReadRTC();
LedProc();
LEDshow(u8LED);
if(pageM==0)KeyProc();//温湿度器件才有效
}
if(cnt1ms%250==0)//250ms采样一次频率数据
{
TR0=0;
freqnum=pulnum*4;
pulnum=0;
TR0=1;
}
if(cnt1ms%300==0)
{
PageProc();
}
if(cnt1ms%500==0)
{
if(cfflag==0) cfread();//触发判断
else if(cfflag==1 && cftime>3000)
{
cfflag=0;
cftime=0;
pageM=0;
}
}
}
}
//-----------------------------------------------
//中断服务程序.NE555
void t0int() interrupt 1 //中断入口
{
pulnum++;
}
/* Timer1 interrupt routine */
void tm1_isr() interrupt 3
{
cnt1ms++;
if(cnt1ms==60000)cnt1ms=0;//边界处理
cftime++;
key10ms++;
longtime++;
if(key10ms==10)
{
key10msflag=1;
key10ms=0;
}
DisplayScan(); //1ms扫描显示一位
}
//****************led_Proc
void LedProc()
{
if(led4flag==1)
{
u8LED=bitTog(u8LED,L4);//u8LED^(1<<L4);
}
else LEDoffx(L4);
if(pagex==1&&pageM==0)
{
LEDonx(L1); LEDoffx(L2);LEDoffx(L3);//L1=0,L2=1,L3=1;
}
else if(pagex==2&&pageM==0)
{
LEDoffx(L1);LEDonx(L2);LEDoffx(L3);
}
else if(pagex==3&&pageM==0)
{
LEDoffx(L1);LEDoffx(L2);LEDoffx(L3);
}
if(pageM==1)
{
LEDoffx(L1);LEDoffx(L2);LEDonx(L3);
}
}
//************************************界面
void PageProc()
{
//&******************时间见面
if(pagex==1&&pageM==0)
{
sprintf(smgbuf,"%02u-%02u-%02u",(unsigned int)shi,(unsigned int)fen,(unsigned int)miao);
smgconv();
}
//***********************************************
else if(pagex==2&&pageM==0)
{
if(page2cnt==0) //温度回显
{
if(cfcnt==0)
{
sprintf(smgbuf,"Cxxxxxxx");
// smgconv();
}
else
{
sprintf(smgbuf,"C %02u-%2.1f",(unsigned int)wendumax,wenduave);
// smgconv();
}
}
//*************湿度回显
else if(page2cnt==1) //湿度回显
{
if(cfcnt==0)
{
sprintf(smgbuf,"Hxxxxxxx");
// smgconv();
}
else
{
sprintf(smgbuf,"H %02u-%2.1f",(unsigned int)shidumax,shiduave);
// smgconv();
}
}
//*************
else if(page2cnt==2) //时间回显
{
if(cfcnt==0)
{
sprintf(smgbuf,"F%02uXXXXX",(unsigned int)cfcnt);
// smgconv();
}
else
{
sprintf(smgbuf,"F%02u%02u-%02u",(unsigned int)cfcnt,(unsigned int)cfshi,(unsigned int)cffen);
//smgconv();
}
}
}
//**********参数界面
else if(pagex==3&&pageM==0)
{
sprintf(smgbuf,"Pxxxxx%02u",(unsigned int)wenducs);
// smgconv();
}
//*********************温湿度界面
if(pageM==1)
{
if(shiduerr==1)
{
sprintf(smgbuf,"Exx%02u-AA",(unsigned int)wendunow);
// smgconv();
}
else if(shiduerr==0)
{
sprintf(smgbuf,"Exx%02u-%02u",(unsigned int)wendunow,(unsigned int)shidunow);
// smgconv();
}
}
smgconv();
}
//***********************************************************************ds1302
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
//
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);
}
//**********初始化时间,设置时间,读取时间
void InitRTC()
{
//写保护关闭,往时分秒写数据,打开写保护
Write_Ds1302_Byte(0x8E,0x00);
Write_Ds1302_Byte(0x84,0x11);//时
Write_Ds1302_Byte(0x82,0x46);
Write_Ds1302_Byte(0x80,0x55);
Write_Ds1302_Byte(0x8E,0x80);
}
//不要求设置时间题目,只要读取时分秒
/********************** 读RTC函数 ************************/
void ReadRTC(void)
{
u8 tmp[3];
tmp[0] =Read_Ds1302_Byte(0x81);
tmp[1] =Read_Ds1302_Byte(0x83);
tmp[2] =Read_Ds1302_Byte(0x85);
miao = ((tmp[0] >> 4) & 0x07) * 10 + (tmp[0] & 0x0f);
fen = ((tmp[1] >> 4) & 0x07) * 10 + (tmp[1] & 0x0f);
shi = ((tmp[2] >> 4) & 0x03) * 10 + (tmp[2] & 0x0f);
}
//****************温度显示
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
//
sbit DQ=P1^4;//引脚
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//读取温度
float readwendu()
{
u8 LSB=0;
u8 MSB=0;
float x0,x1;
float wendux;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);//改为44,转换温度
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);//改为44,转换温度
LSB=Read_DS18B20();
MSB=Read_DS18B20();
//高位
x0=bitRead(MSB,2)*64+bitRead(MSB,1)*32+bitRead(MSB,0)*16;
x1=bitRead(LSB,7)*8+bitRead(LSB,6)*4+bitRead(LSB,5)*2+bitRead(LSB,4)*1+bitRead(LSB,3)*0.5+bitRead(LSB,2)*0.25;
wendux=x0+x1;
return wendux;
}
//PCF8591*****************************
#define SLAW 0x90
#define SLAR 0x91
sbit SDA0 = P2^1; //定义SDA PIN5
sbit SCL0 = P2^0; //定义SCL PIN6
/****************************/
void I2C_Delay(void) //for normal MCS51, delay (2 * dly + 4) T, for STC12Cxxxx delay (4 * dly + 10) T
{
u8 dly=5;
dly = 12000000 / 2000000UL; //按2us计算
while(--dly) ;
}
/****************************/
void I2C_Start(void) //start the I2C, SDA High-to-low when SCL is high
{
SDA0 = 1;
I2C_Delay();
SCL0 = 1;
I2C_Delay();
SDA0 = 0;
I2C_Delay();
SCL0 = 0;
I2C_Delay();
}
void I2C_Stop(void) //STOP the I2C, SDA Low-to-high when SCL is high
{
SDA0 = 0;
I2C_Delay();
SCL0 = 1;
I2C_Delay();
SDA0 = 1;
I2C_Delay();
}
//void S_ACK(void) //Send ACK (LOW)
//{
// SDA0 = 0;
// I2C_Delay();
// SCL0 = 1;
// I2C_Delay();
// SCL0 = 0;
// I2C_Delay();
//}
void S_NoACK(void) //Send No ACK (High)
{
SDA0 = 1;
I2C_Delay();
SCL0 = 1;
I2C_Delay();
SCL0 = 0;
I2C_Delay();
}
void I2C_Check_ACK(void) //Check ACK, If F0=0, then right, if F0=1, then error
{
SDA0 = 1;
I2C_Delay();
SCL0 = 1;
I2C_Delay();
F0 = SDA0;
SCL0 = 0;
I2C_Delay();
}
/****************************/
void I2C_WriteAbyte(u8 dat) //write a byte to I2C
{
u8 i;
i = 8;
do
{
if(dat & 0x80) SDA0 = 1;
else SDA0 = 0;
dat <<= 1;
I2C_Delay();
SCL0 = 1;
I2C_Delay();
SCL0 = 0;
I2C_Delay();
}
while(--i);
}
/****************************/
u8 I2C_ReadAbyte(void) //read A byte from I2C
{
u8 i,dat;
i = 8;
SDA0 = 1;
do
{
SCL0 = 1;
I2C_Delay();
dat <<= 1;
if(SDA0) dat++;
SCL0 = 0;
I2C_Delay();
}
while(--i);
return(dat);
}
/****************************/
//题目只要求光敏电阻,AIN1,读IIC器件的数据,可以看
u8 readIN1(void)
{
u8 res=0;
I2C_Start();
I2C_WriteAbyte(0x90);
I2C_Check_ACK();
I2C_WriteAbyte(0x01);//01
I2C_Check_ACK();
I2C_Start();
I2C_WriteAbyte(0x91);
I2C_Check_ACK();
res= I2C_ReadAbyte();
S_NoACK(); //send no ACK
I2C_Stop();
return res;
}
//湿度变化
float shiducal(unsigned int x)
{
float y;
if(x<200||x>2000)y=999.0f;
else
{
y=0.044f*x+1.12f;
}
return y;
}
void cfread()//触发判断
{
static u8 inold=0;
u8 innow=0,indown=0,inup=0;
static float wenduold=0.0f,shiduold=0.0f;
innow=readIN1();
if(innow<100)innow=1;//档光的情况下
else innow=0;//亮光的情况下0-255是大于90的
indown=innow &(inold ^innow);
inold=innow;
if(indown)
{
wendunow= readwendu();
if(wendunow>wenducs)
{
led4flag=1;
}
else
led4flag=0;
shidunow=shiducal(freqnum);
if(shidunow>95)
{
shiduerr=1;
LEDonx(L5);
}
else
{
shiduerr=0;
LEDoffx(L5);
}
if(shiduerr==0)
{
cfcnt++;
ReadRTC();
cfshi=shi;
cffen=fen;
//计算最大温度和最大湿度,平均温度,平均湿度。
if(wendunow>wenduold)wendumax=wendunow;
else wendumax=wenduold;
if(shidunow>shiduold)shidumax=shidunow;
else shidumax=shiduold;
if(cfcnt>=2)
{
if(wendunow>wenduold &&shidunow>shiduold)
LEDonx(L6);
else
LEDoffx(L6);
}
wenduold=wendunow;
shiduold=shidunow;
wendusum+=wendunow;
shidusum+=shidunow;
shiduave=shidusum/cfcnt;
wenduave=wendusum/cfcnt;
}
pageM=1;//调到温湿度界面页面
cfflag=1;//触发标记等于1
cftime=0;//温湿度界面时间请0,在定时器1中计算时间3秒
}
}
LQB新-2023省赛参考代码
最新推荐文章于 2024-11-05 17:16:24 发布