自学内容网 自学内容网

LQB新-2023省赛参考代码

#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;
u8cfshi=0;//触发小时
u8cffen=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秒

}

}


原文地址:https://blog.csdn.net/lmf666/article/details/136386612

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!