第四届蓝桥杯比赛题目——风扇控制系统

/*
  程序说明: 第七届省赛风扇控制系统
  软件环境: Keil uVision 4.10
  硬件环境: CT107单片机综合实训平台(内部晶振11.0592MHZ) STC15F2K60S2单片机
  日    期: 2018-5-22
  备注:不用示波器,直接用led1反应PWN波形,我习惯于一个定时器工作,如觉得有干扰可用第二个
*/
#include <stc15f2k60s2.h>
#include <onewire.h>

typedef unsigned char u8;
typedef unsigned int u16;
/*************  宏定义    **************/
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2

/*************  本地常量声明    **************/
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};      //位码
bit key_flag;
u8 key_scan();
u8 mode=1;
u8 set_time=0;
u8 real_time=50;
u8 smg_on[8],smg_temp[8];
u8 temperature=0;
u8 s7_count =0;

/*************  定时器初始化程序    **************/
void Timer0Init(void)        //0.1毫秒@11.0592MHz
{
    AUXR |= 0x80;        //定时器时钟1T模式
    TMOD &= 0xF0;        //设置定时器模式
    TL0 = 0xAE;        //设置定时初值
    TH0 = 0xFB;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0 = 1;
    EA = 1;
}
/*************  中断服务程序    **************/
void timer0() interrupt 1 using 1
{
    static char smg_count=0,key_count =0,i=0,pwn_count=0;//中断溢出计数
    static int time_count=0;
    smg_count++;key_count++;time_count++;pwn_count++;//每进一次中断加一,也就是计时数0.1毫秒自增1
//调用显示模块    
    if(smg_count==30) //产生3毫秒定时
    {
        smg_count =0;
        if(s7_count==1)
        {P2=0XE0;P0=~smg_temp[i];P2=0X00;}
        else
        {P2=0XE0;P0=~smg_on[i];P2=0X00;}
        P2=0XC0;P0=T_COM[i];P2=0X00;
        i++;
        if(i==8)i=0;
    }
//
//调用按键模块
    if(key_count==100)
    {
        key_count = 0;
        key_flag = 1;
    }
//倒计时发生数    
    if(time_count==10000)
    {
        time_count=0;
        if(real_time>0)real_time--;
    }
//pwn(脉宽调制信号)设置模块
    if(real_time!=0)
    {
        if(mode==1)
        {
            if(pwn_count==8)
            {
                P2=0X80;P0=~0x01;P2=0X00;
            }
            if(pwn_count==10)
            {
                P2=0X80;P0=0xff;P2=0X00;
            }
        }
    
        if(mode==2)
        {
            if(pwn_count==7)
            {
                P2=0X80;P0=~0x01;P2=0X00;
            }
            if(pwn_count==10)
            {
                P2=0X80;P0=0xff;P2=0X00;
            }
        }
    
        if(mode==3)
        {
            if(pwn_count==3)
            {
                P2=0X80;P0=~0x01;P2=0X00;
            }
            if(pwn_count==10)
            {
                P2=0X80;P0=0xff;P2=0X00;
            }
        }
    }
}

/*************  主函数体    **************/
void main(void)
{
    u8 key_val;
    P2=0XA0;P0=0X00;P2=0X00;//关定时器
    Timer0Init();//调用定时器初始化

    while(1)
    {
        if(real_time==0){P2=0X80;P0=0Xff;P2=0X00;}//检测是否还在定时周期中

        temperature=(unsigned char)rd_temprature_f();//调用单总线

        //工作计时显示模块
        smg_on[0]=t_display[17];smg_on[1]=t_display[mode];smg_on[2]=t_display[17];smg_on[3]=t_display[16];
        smg_on[4]=t_display[real_time/1000];smg_on[5]=t_display[real_time/100%10];
        smg_on[6]=t_display[real_time/10%10];smg_on[7]=t_display[real_time%10];
        //温度显示模块
        smg_temp[0]=t_display[17];smg_temp[1]=t_display[4];smg_temp[2]=t_display[17];
        smg_temp[3]=t_display[16];smg_temp[4]=t_display[17];
        smg_temp[5]=t_display[temperature/10];smg_temp[6]=t_display[temperature%10];smg_temp[7]=t_display[12];
        //按键检测
        if(key_flag)
        {
            key_flag =0;
            key_val=key_scan();
            switch(key_val)
            {
                case 4:
                    mode++;//按下一次模式自增一次
                    if(mode==4)mode =1;
                break;
                case 5:
                    real_time = set_time; //把设定的时间赋给操作时间
                    set_time+=60;
                    if(set_time==240)set_time=0;
                break;
                case 6:
                    real_time = 0;//关闭计时
                break;
                case 7:
                    s7_count++;    //记录s7按下次数
                    if(s7_count==3)s7_count=1;

                break;
            }
        }    
    }

}
/*************  按键及状态机消抖    **************/
u8 key_scan()
{
    static char key_state = key_state_0;
    u8 key1,key2,key_temp,key_value=0;

    P30=0;P31=0;P32=0;P33=0;P34=1;P35=1;P42=1;P44=1;
    if(P44==0)key1=0x70;
    if(P42==0)key1=0xb0;
    if(P35==0)key1=0xd0;
    if(P34==0)key1=0xe0;
    if((P44==1)&&(P42==1)&&(P35==1)&&(P34==1))key1=0xf0;

    P30=1;P31=1;P32=1;P33=1;P34=0;P35=0;P42=0;P44=0;
    if(P33==0)key2=0x07;
    if(P32==0)key2=0x0b;                   
    if(P31==0)key2=0x0d;
    if(P30==0)key2=0x0e;
    if((P33==1)&&(P32==1)&&(P31==1)&&(P30==1))key2=0x0f;
    key_temp = key1|key2;

    switch(key_state)
    {
        case key_state_0:
            if(key_temp!=0xff)key_state = key_state_1;
        break;
        case key_state_1:
            if(key_temp==0xff)key_state = key_state_0;
            else
            {
                switch(key_temp)
                {
                    case 0x77:key_value=4;break;
                    case 0x7b:key_value=5;break;
                    case 0x7d:key_value=6;break;
                    case 0x7e:key_value=7;break;

                    case 0xb7:key_value=8;break;
                    case 0xbb:key_value=9;break;
                    case 0xbd:key_value=10;break;
                    case 0xbe:key_value=11;break;

                    case 0xd7:key_value=12;break;
                    case 0xdb:key_value=13;break;
                    case 0xdd:key_value=14;break;
                    case 0xde:key_value=15;break;

                    case 0xe7:key_value=16;break;
                    case 0xeb:key_value=17;break;
                    case 0xed:key_value=18;break;
                    case 0xee:key_value=19;break;

                }
                key_state = key_state_2;
            }
        break;
        case key_state_2:
            if(key_temp==0xff)key_state = key_state_0;
        break;
    }
    return key_value;
}

附件(单总线协议程序)

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2018-5-22
*/
#include "reg52.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
    unsigned char i;
    while(t--)
    for(i=0;i<12;i++);
}

//通过单总线向DS18B20写一个字节
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);
}

//从DS18B20读取一个字节
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;
}

//DS18B20设备初始化
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 rd_temprature_f(void)
{
    unsigned int temp;
    float temperature;
    unsigned char low,high;

    init_ds18b20();
    Write_DS18B20(0xcc);
    Write_DS18B20(0x44);
    Delay_OneWire(200);

    init_ds18b20();
    Write_DS18B20(0xcc);
    Write_DS18B20(0xbe);

    low = Read_DS18B20();
    high = Read_DS18B20();

    temp = high;
    temp <<=8;
    temp|=low;
    temperature = temp*0.0625;
    return temperature;

}

猜你喜欢

转载自www.cnblogs.com/scr971023/p/9071515.html