藍橋杯第3屆省賽(單片機)_溫度監控器
題目



這是2011年藍橋杯單片機組的省賽題,我感覺整體的難度不大,可能有點挑戰性的就是EEPROM儲存了,本次題型主要考查了數碼管,獨立按鍵,IIC-(EEPROM儲存),繼電器和電機拖動了,考察的都是那幾種固定的模塊,
題目分析
1 數碼管顯示單元
首先在數碼管那一面上,DS1部分顯示上限溫度與下限溫度,而在DS2部分我們要關閉前兩位數碼管而在最后兩位顯示自測溫度,這題主要考的是數碼管顯示,對于DS1部分,我們只需寫變數來控制溫度上下限的高低,而自測溫度那一部分,我們可以通過ds18b20部分將所得溫度表達出來,最后再將溫度通過乘除部分來通過數碼管顯示,
2 溫度測量單元
這題比較簡單,只需要改寫底層驅動代碼(onewhile)就可以測量了,
3 按鍵控制單元
這里主要考察的是獨立按鍵,獨立按鍵比較簡單,只需要寫好相應的按鍵代碼格式就行,然后通過不同按鍵來控制不同的變數來控制溫度值的變數,
(這里的按鍵代碼格式我會在下面的代碼顯示部分表達出來)
4 EEPROM的記錄
這里也是一樣,只需要改寫底層驅動代碼(iic)就可以測量了.不過溫度要保留在0X01,0X00部分,
5 電機拖動,6溫控單元
由于我沒有電機拖動,我在這里就用led1來代替了,其實主要的程式都一樣,等我到時候有電機時我再來改動吧!再電機拖動哪里我主要是用了定時器,繼電器也是一樣,把定時器函式寫在定時器函式里面,這里我先不多說,等到代碼部分我在詳見,
代碼部分
time.c
# include "time.h"
void Timer0Init(void) //100微秒@12.000MHz
{
AUXR &= 0x7F; //定時器時鐘12T模式
TMOD &= 0xF0; //設定定時器模式
TL0 = 0x9C; //設定定時初值
TH0 = 0xFF; //設定定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
EA=ET0=1;
}
time.h
# ifndef _TIME_H
# define _TIME_H
# include <STC15F2K60S2.H>
void Timer0Init(void);
# endif
smg.c
# include "smg.h"
unsigned char code tab[11]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XFF};
unsigned char dspbuf[8]={10,10,10,10,10,10,10,10};
void smg_display(void)
{
static unsigned char i;
P0=0XFF;
P2&=0X1F;
P2|=0XE0;//Y7C
P2&=0X1F;
P0=(1<<i);
P2&=0X1F;
P2|=0XC0;//Y6C
P2&=0X1F;
P0=tab[dspbuf[i]];
P2&=0X1F;
P2|=0XE0;//Y7C
P2&=0X1F;
if(++i==8)
i=0;
}
smg.h
# ifndef _SMG_H
# define _SMG_H
# include <STC15F2K60S2.H>
void smg_display(void);
extern unsigned char dspbuf[8];
# endif
key.c
(這里的是矩陣按鍵的基本模型,通過按鍵控制變數最后控制數碼管)
# include "key.h"
unsigned char key_value;
void key_read(void)
{
static unsigned char i; //靜態變數
if(P30!=1||P31!=1||P32!=1||P33!=1)
{
i++;
if(i==1)
{
if(P30!=1) key_value=1;
else if(P31!=1) key_value=2;
else if(P32!=1) key_value=3;
else if(P33!=1) key_value=4;
}
else if(i>=30) //長按變短按
{
i=1;
key_value=0;
}
}
else //沒有按鍵按下則為零
i=0;
}
key.h
# ifndef _KEY_H
# define _KEY_H
# include <STC15F2K60S2.H>
void key_read(void);
extern unsigned char key_value;
# endif
other.c
# include "other.h"
void relay_on(void)
{
P2=(P2&0X1F)|0XA0;
P0|=0X10;
P2&=0X1F;
P04=1; //在這里我認為這部分代碼比上述代碼好,出現的bug少
P2&=0X1F;
P2|=0XA0;
P2&=0X1F;
}
void relay_off(void)
{
P04=0;
P2&=0X1F;
P2|=0XA0;
P2&=0X1F;
// P2=(P2&0X1F)|0XA0;
// P0&=0xEF;
// P2&=0X1F;
}
void bee_off(void)
{
P06=0;
P2&=0X1F;
P2|=0XA0;
P2&=0X1F;
// P2=(P2&=0X1F)|0XA0;
// P0&=0X00;
// P2&=0X1F;
}
other.h
# ifndef _OTHER_H
# define _OTHER_H
# include <STC15F2K60S2.H>
void relay_on(void);
void relay_off(void);
void bee_off(void);
# endif
main.c
# include <STC15F2K60S2.H>
# include "time.h"
# include "smg.h"
# include "key.h"
# include "ds18b20.h"
# include "iic.h"
# include "other.h"
unsigned char tempature_max;
unsigned char tempature_min;
unsigned char key_allow;
unsigned int temp;
unsigned char flag_key;
unsigned char flag_relay;
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void allinit(void)
{
P0=0X00;
P2&=0X1F;
P2|=0XA0; //Y5C
P2&=0X1F;
//燈全滅
P0=0XFF;
P2&=0X1F;
P2|=0X80;//Y4C
P2&=0X1F;
}
void eeprom_init(void)
{
if(eeprom_read(0X99)==0X99)//這里可以隨便定,只要不是資料庫里的變數就行
{//這里主要是把板里的資料清除掉
tempature_max=30;
tempature_min=23;
tempature_max=eeprom_read(0X00);
tempature_min=eeprom_read(0X01);
}
else
{
eeprom_write(0X99,0X99);
}
}
void main(void)
{
allinit();
eeprom_init();
Timer0Init();
bee_off();
relay_off();
while(1)
{
/******************key******************/
if(key_allow==1)
{
key_allow=0;
key_read();
}
switch(key_value)
{
case 1:
key_value=0;
flag_key=1;
break;
case 2:
key_value=0;
flag_key=2;
break;
case 3:
key_value=0;
flag_key=3;
break;
case 4:
key_value=0;
flag_key=4;
break;
}
/****************ds18b20*******************/
temp=temp_read();
if(temp<tempature_min)
{
flag_relay=1;
}
if(temp>tempature_min)
{
flag_relay=2;
}
if(temp>tempature_max)
{
flag_relay=3;
}
if(temp<tempature_max)
{
flag_relay=4;
}
/****************temp_change*****************/
if(tempature_min>tempature_max||tempature_max==99||tempature_min==99)
{
tempature_min--;
}
switch(flag_key)
{
case 4:
flag_key=0;
if(tempature_max!=99)
{
tempature_max++;
eeprom_write(0x00,tempature_max);
Delay5ms();//延遲5毫秒來儲存資料
}
break;
case 3:
flag_key=0;
if(tempature_min!=99)
{
tempature_min++;
eeprom_write(0x01,tempature_min);
Delay5ms();
}
break;
case 2:
flag_key=0;
if(tempature_max!=99)
{
tempature_max--;
eeprom_write(0x00,tempature_max);
Delay5ms();
}
break;
case 1:
flag_key=0;
if(tempature_min!=99)
{
tempature_min--;
eeprom_write(0x01,tempature_min);
Delay5ms();
}
break;
}
/**************smg***************/
dspbuf[0]=tempature_max/10;
dspbuf[1]=tempature_max%10;
dspbuf[2]=tempature_min/10;
dspbuf[3]=tempature_min%10;
dspbuf[4]=10;
dspbuf[5]=10;
dspbuf[6]=temp/10;
dspbuf[7]=temp%10;
}
}
void time0(void) interrupt 1
{
static unsigned char key_30_times;
if(++key_30_times==30)
{
key_30_times=0;
key_allow=1;
}
/***************溫控單元***************/
if(flag_relay==1)
{
relay_on();
flag_relay=0;
bee_off();
}
if(flag_relay==2)
{
flag_relay=0;
relay_off();
bee_off();
}
if(flag_relay==3)
{
P0=0xFE;
P2&=0X1F;
P2=0X80;
P2&=0X1F;
}
if(flag_relay==4)
{
P0=0xFF;
P2&=0X1F;
P2=0X80;
P2&=0X1F;
}
smg_display();
}
//(這里的溫控單元要在這里因為因為就是你那個如果放在中斷的話,你可能在呼叫那個繼電器打開函式的時候,剛執行到p14等于1他那個中斷時間到了,
//它就進入到那個數碼段,顯示那里要批零就等于0xff,然后繼續往下執行,P0就會被重繪掉,)
//然后等你處理完數碼管之后,出來再繼續進行那個繼電器那個,打開那個函式,然后這時候p04應該不是1了,或者是其他的數,如果把溫控單元這一部分放在主函式部分那繼電器會不靈敏,會跳來跳去,顯示bug,
結語
在這里我還是要感謝一下我都朱師兄,感謝他幫我找到了bug(就是溫控單元那部分),不然我現在可能還卡在這道題吧!,我也看了一些大佬的文章,感覺自己的代碼還是有許多問題,比如代碼過長,不簡便,所以,我認為我自己還是要好好學習,也感謝大家的觀看,如果你認為可以的話可以收藏一下哦(⊙o⊙)!實在不行也給個贊( ̄▽ ̄)"吧!謝謝大家,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/255963.html
標籤:其他
上一篇:初探C51單片機LED
下一篇:STM32——兩個模塊代碼的合并
