第三屆藍橋杯單片機類溫度監控器
題目要求

要實作溫度監控可以將功能模塊化,


前期準備
頭檔案、管腳定義、全域變數定義、函式宣告
#include<STC15F2K60S2.H>
#include"Delay.h"
#include"SelectHC573.h"
#include"Disp_SMG.h"
#include"onewire.h"
#include "iic.h"
sbit S7=P3^0;//按鍵
sbit S6=P3^1;
sbit S5=P3^2;
sbit S4=P3^3;
sbit L1=P0^0;//LED
sbit L2=P0^2;
sbit J=P0^4;//繼電器
unsigned char SMG_DM[18]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90,0x88,0x80,
0xc6,0xc0,0x86,0x8e,0xbf,0x7f
};
unsigned int temp=0;//溫度
unsigned char max=30;//上限
unsigned char min=20;//下限
char a=1;//存盤資料控制位
void Dsip();
void All_Init();
鎖存器選擇函式
//=================================
//函 數 名:鎖存器選擇函式
//功 能:將選擇的鎖存器打開
//輸入引數:所選擇的鎖存器
//輸出引數:無
void SelectHC573(unsigned char n)
{
switch(n)
{
case 0:P2=P2&0x1f;break; //將打開的鎖存器關閉
case 4:P2=P2&0x1f|0x80;break; //打開LED相關的鎖存器
case 5:P2=P2&0x1f|0xa0;break; //蜂鳴器、繼電器相關的鎖存器
case 6:P2=P2&0x1f|0xc0;break; //數碼管位選
case 7:P2=P2&0x1f|0xe0;break; //數碼管段選
}
}
外設關閉函式
//========================
//函式名:外設初始化函式
//功能:關閉外設
//輸入引數:無
//輸出引數:無
//========================
void All_Init()
{
SelectHC573(4);
P0=0xff;//熄滅LED資料
SelectHC573(0);
SelectHC573(5);
P0=0x00;//熄滅蜂鳴器、繼電器資料
SelectHC573(0);
}
延時函式
//======================
//函式名:延時函式
//功能:延時
//輸入引數:延時大小
//輸出引數:無
void Delay(unsigned char t)
{
while(t--);
}
功能實作
功能一數碼管顯示

//======================
//函式名:數碼管顯示函式
//功能:傳入引數,讓數碼管顯示
//輸入引數:要顯示的資料,和要顯示的位置
//輸出引數:無
//========================
void Disp_SMG(unsigned char dat,unsigned char pos)
{
SelectHC573(6);
P0=0x01<<pos;//要顯示的位置
SelectHC573(7);
P0=dat;//要顯示的資料
}
下面這段代碼實作了題目中的要求
//========================
//函式名:顯示
//功能:將要顯示的資料放在一個函式中
//輸入引數:無
//輸出引數:無
//========================
void Dsip()
{
Disp_SMG(SMG_DM[max/10],0);
Delay(100);
Disp_SMG(SMG_DM[max%10],1);
Delay(100);
Disp_SMG(SMG_DM[min/10],2);
Delay(100);
Disp_SMG(SMG_DM[min%10],3);
Delay(100);
Disp_SMG(0xff,4);
Delay(100);
Disp_SMG(0xff,5);
Delay(100);
Disp_SMG(SMG_DM[temp/10],6);
Delay(100);
Disp_SMG(SMG_DM[temp%10],7);
Delay(100);
}
效果是這樣的
功能二溫度獲取

要實作此功能需要ds18b20數字芯片獲取,
#include "onewire.h"
//單總線延時函式
void Delay_OneWire(unsigned int t)
{
while(t--);
}
//DS18B20初始化
bit Init_DS18B20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(144);
DQ = 0;
Delay_OneWire(960);
DQ = 1;
Delay_OneWire(120);
initflag = DQ;
Delay_OneWire(60);
return initflag;
}
//通過單總線寫一個位元組
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(60);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(60);
}
//讀一個位元組
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(60);
}
return dat;
}
上述代碼考試當天會提供,我們只需要自己進行修改即可,(上面的代碼是修改過的)比賽所提供的檔案中onewire.h中沒有宣告函式,需要自己進行宣告
比賽當天提供的代碼是1Hz的,將onewire.c中所有延時函式擴大12倍即可成為12Hz的
溫度獲取
/*
//溫度獲取中的延時函式,
//作用是防止數碼管所顯示的溫度一位特別亮,一位特暗
*/
void Delay_wd(unsigned int t)
{
while(t--)
{
Dsip();
}
}
//========================
//函式名:溫度獲取函式
//功能:獲取溫度給全域變數temp
//輸入引數:無
//輸出引數:無
//========================
void Ds18B20_temp()
{
unsigned int LSB,MSB;//溫度資料
Init_DS18B20();//初始化
Write_DS18B20(0xcc);//跳過ROM指令
Write_DS18B20(0x44);//開始溫度轉換
Delay_wd(1000);//稍微延時一下
Init_DS18B20();//初始化
Write_DS18B20(0xcc);//跳過ROM指令
Write_DS18B20(0xbe);//讀取高速快取
LSB=Read_DS18B20();//讀取低8位
MSB=Read_DS18B20();//讀取高8位
Init_DS18B20();//初始化
temp=MSB;
temp=(temp<<8)|LSB;//高8位左移,低四位賦給temp
temp>>=4;//去掉小數位
}
注意:不要將高位和低位弄反了,不然讀出來的資料是錯誤的
功能三按鍵實作

這個功能很好實作,定義兩個全域變數max\min為上下限溫度,當按鍵按下時數值改變,并且將數值保存在AT24C02中,
void Key()
{
if(S7==0)
{
Delay(10);
if(S7==0)
{
min--;
a=0;//全域變數,為實作功能四而設定
}
}
if(S6==0)
{
Delay(10);
if(S6==0)
{
max--;
a=0;
}
}
if(S5==0)
{
Delay(10);
if(S5==0)
{
min++;
a=0;
}
}
if(S4==0)
{
Delay(10);
if(S4==0)
{
max++;
a=0;
}
}
if(a==0)//功能四的部分實作
{
Write_24c02(0x00,max);//向e2prom寫入溫度上限
Delay(2000);
Write_24c02(0x01,min);//寫入溫度下限
a=2;
}
}
功能四將資料保存在AT24C02中
#include "iic.h"
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
void IIC_Ack(unsigned char ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
return 1;
}
}
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
這些代碼比賽當天都會提供,需要自己看手冊來實作功能就行,我們要寫的代碼是下面的部分
void Write_24c02(unsigned char seat,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(seat);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
//========================
//========================
void EEPROM_Read(unsigned char* pucBuf,unsigned char addr,
unsigned char num)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
while(num--)
{
*pucBuf++ = IIC_RecByte();
if(num)
IIC_Ack(0);
else IIC_Ack(0);
}
IIC_Stop();
}

其實本質就是時序圖,大概總結了一下,寫入資料的如下
啟動總線-----發送設備地址+寫-----等待應答-----發送資料的儲存地址(0x00-0xFF,256個位元組)-----等待應答-----發送資料-----等待應答-----停止總線
讀入資料如下
啟動總線-----發送設備地址+寫-----等待應答-----發送資料存盤地址-----等待應答-----發送設備地址+讀-----等待應答-----讀取資料-----主機發送是否應答……
功能五、六

自己現在沒有一個直流電機,就用L1、L2d代替超過上限時作業和不作業
void Elect()
{
if(temp<min)
{
All_Init();
SelectHC573(5);
J=1;
}
else
{
All_Init();
SelectHC573(5);
J=0;
}
if(temp>max)
{
SelectHC573(4);
P0=0xfd;
}
else
{
SelectHC573(4);
P0=0xfe;
}
}
主函式
void main()
{
All_Init();
EEPROM_Read(&max,0x00,1);//讀取溫度上下限
EEPROM_Read(&min,0x01,1);
while(1)
{
Elect();
Key();
Dsip();
Ds18B20_temp();
}
}
具體檔案
鏈接:https://pan.baidu.com/s/1pRPqaDrWomakjsXBSTjPgA
提取碼:qwer
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/272955.html
標籤:其他
