一、試題
1、 基本要求
1.1 使用大賽組委會提供的國信長天單片機競賽實訓平臺,完成本試題的程式設計
與除錯,
1.2 選手在程式設計與除錯程序中,可參考組委會提供的“資源資料包”,
1.3 請注意: 程式撰寫、除錯完成后選手應通過考試系統提交完整、可編譯的 Keil
工程檔案,選手提交的工程檔案應是最終版本, 要求 Keil 工程檔案以準考證
號(8 位數字)命名, 工程檔案夾內應包含以準考證號命名的 hex 檔案,該 hex
檔案是成績評審的依據, 不符合以上檔案提交要求的作品將被評為零分或者被
酌情扣分,
1.4 請勿上傳與作品工程檔案無關的其它檔案,
2、 競賽板配置要求
2.1將 IAP15F2K61S2 單片機內部振蕩器頻率設定為 12MHz,
2.2鍵盤作業模式跳線 J5 配置為 BTN 按鍵模式,
2.3擴展方式跳線 J13 配置為 IO 模式,
2.4請注意: 選手需嚴格按照以上要求配置競賽板,撰寫和除錯程式, 不符合以上
配置要求的作品將被評為零分或者被酌情扣分,
3、 硬體框圖

圖 1 系統硬體框圖
4、 功能描述
4.1基本功能
- 通過 DS18B20 完成溫度資料測量,
- 通過數碼管實作資料和引數界面的顯示,
- 通過按鍵實作界面切換、引數設定等功能,
- 通過 LED 指示燈實作狀態指示與報警輸出功能,
- 通過 PCF8591 完成 DAC 模擬電壓輸出功能,
4.2設計要求 - 溫度資料重繪時間:≤0.5 秒
- 顯示界面切換時間:≤0.3 秒
- DAC 模擬電壓輸出回應時間:≤0.3 秒
- 溫度引數可調整范圍:
? 溫度上限引數 0 ≤ TMAX < 100
? 溫度下限引數 0 ≤ TMIN < 100
4.3顯示功能 - 資料界面
資料界面如圖 2 所示,顯示內容包括提示符 C 和通過 DS18B20 溫度傳感器
采集到的溫度資料,溫度資料取整數,

圖 2 資料顯示界面
2) 引數界面如圖 3 所示,顯示內容包括提示符 P、溫度上限引數 TMAX和溫度下
限引數 TMIN,

圖 3 引數設定界面
4.4按鍵功能
- 按鍵功能說明
? S4: 定義為“界面切換”按鍵,按下 S4 按鍵,切換選擇資料顯示界
面和引數設定界面,3 / 3
? S5:定義為“引數切換” 按鍵,按下 S5 按鍵,切換選擇溫度上限參
數 TMAX和溫度下限引數 TMIN,
? S6:定義為“加” 按鍵, 按下 S6 按鍵,當前選擇的溫度引數增加 1℃,
? S7:定義為“減”按鍵,按下 S7 按鍵,當前選擇的溫度引數減少 1℃, - 按鍵功能設計要求
? 按鍵 S6 和按鍵 S7 的加、 減功能僅在引數設定界面有效,
? 合理設定引數邊界范圍, 防止出現引數越界和邏輯錯誤,
? 每次從資料界面切換到引數界面,默認當前選擇的引數是溫度下限參
數 TMIN,
? 通過 S4 按鍵,從引數設定界面退出,進入資料顯示界面時,需要進行
必要的引數合理性檢查( TMAX≥TMIN);若設定的引數合理,引數生效,
進入資料界面;反之, 自動恢復進入引數設定界面前的有效引數, 進
入資料界面,
4.5DAC 輸出功能 - 當前溫度 T > TMAX時,控制 DAC 輸出 4.0V,
- 當前溫度 TMIN ≤ T ≤ TMAX時,控制 DAC 輸出 3.0V,
- 當前溫度 T < TMIN時,控制 DAC 輸出 2.0V,
4.6LED 指示燈功能 - 當前溫度滿足 T > TMAX,指示燈 L1 點亮,否則熄滅,
- 當前溫度滿足 TMIN ≤ T ≤ TMAX,指示燈 L2 點亮,否則熄滅,
- 當前溫度滿足 T < TMIN,指示燈 L3 點亮,否則熄滅,
- 如出現錯誤的引數設定操作,指示燈 L4 點亮,直至下一次正確的引數設
置后,指示燈熄滅,
4.7初始狀態說明 - 初始狀態上電默認處于資料顯示界面,
- 默認引數
? 溫度上限引數 TMAX = 30℃
? 溫度下限引數 TMIN = 20℃
二、原始碼(有瑕疵)
1、main.c
#include<STC15F2K60S2.H>
#include"onewire.h"
#include"iic.h"
#define uchar unsigned char
#define uint unsigned int
void delayms(uint ms);
void Select573(char channel);
void allinit();
void display1();
void display2();
void display3();
void display4();
void keyscan();
void work_key();
void work_led();
void work_dac();
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xFF,0xc6,0x8c};
uchar code dot[]={0x40,0x79,0x24,0x30,0x19,0x12,0x20,0x78,0x00,0x10};//&0x7f
uchar yi,er,san,si,wu,liu,qi,ba;
int temper;
bit mode=0;
bit choose=1;
char tmax;
char tmin;
char tomax;
char tomin;
void main()
{
allinit();
temper=temperature_rd_F();
tmax=30;
tmin=20;
while(1)
{
work_key();
work_led();
work_dac();
display1();
display2();
display3();
display4();
keyscan();
}
}
void work_key()
{
if(mode==0)
{
yi=12;
er=11;san=11;si=11;wu=11;liu=11;
qi=temper/10;ba=temper%10;
}
else
{
yi=13;
er=11;san=11;
si=tmax/10;wu=tmax%10;
liu=11;
qi=tmin/10;ba=tmin%10;
}
}
void work_led()
{
Select573(4);
if(tmax<tmin)
{
P03=0;
P00=1;P01=1;P02=1;
}
else P03=1;
if(tmax>=tmin)
{
if(temper>tmax)P00=0;
else P00=1;
if(temper<tmin)P02=0;
else P02=1;
if(temper<tmax&&temper>tmin)P01=0;
else P01=1;
}
Select573(0);
}
void work_dac()
{
if(temper>tmax)
AD_write(0x40,204);
if(temper<tmin)
AD_write(0x40,102);
if(temper<tmax&&temper>tmin)
AD_write(0x40,153);
if(tmax<tmin)
AD_write(0x40,0);
}
void delayms(uint ms)
{
uint i,j;
for(i=ms;i>0;i--)
for(j=845;j>0;j--);
}
void Select573(char channel)
{
switch(channel)
{
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
case 0:
P2=(P2&0x1f)|0x00;
break;
}
}
void allinit()
{
Select573(4);
P0=0xff;
Select573(5);
P0=0x00;
Select573(6);
P0=0xff;
Select573(7);
P0=0xff;
Select573(0);
}
void display1()
{
Select573(6);
P0=0x01;
Select573(7);
P0=tab[yi];
delayms(1);
Select573(6);
P0=0x02;
Select573(7);
P0=tab[er];
delayms(1);
}
void display2()
{
Select573(6);
P0=0x04;
Select573(7);
P0=tab[san];
delayms(1);
Select573(6);
P0=0x08;
Select573(7);
P0=tab[si];
delayms(1);
}
void display3()
{
Select573(6);
P0=0x10;
Select573(7);
P0=tab[wu];
delayms(1);
Select573(6);
P0=0x20;
Select573(7);
P0=tab[liu];
delayms(1);
}
void display4()
{
Select573(6);
P0=0x40;
Select573(7);
P0=tab[qi];
delayms(1);
Select573(6);
P0=0x80;
Select573(7);
P0=tab[ba];
delayms(1);
Select573(6);
P0=0xff;
Select573(7);
P0=0xff;
}
void keyscan()
{
if(P33==0)
{//S4
delayms(5);
if(P33==0)
{
if(mode==0)
{
mode=1;
tomax=tmax;
tomin=tmin;
}
else if(mode==1)
{
mode=0;
if(tmax<tmin)
{
tmax=tomax;
tmin=tomin;
}
}
}
while(!P33);
}
if(P32==0)
{//S5
delayms(5);
if(P32==0)
{
if(mode==1)
{
if(choose==0)choose=1;
else if(choose==1)choose=0;
}
}
while(!P32);
}
if(P31==0)
{//S6
delayms(5);
if(P31==0)
{
if(mode==1)
{
if(choose==0)
{
if(tmax<99)tmax++;
}
else if(choose==1)
{
if(tmin<99)tmin++;
}
}
}
while(!P31);
}
if(P30==0)
{//S7
delayms(5);
if(P30==0)
{
if(mode==1)
{
if(choose==0)
{
if(tmax>0)tmax--;
}
else if(choose==1)
{
if(tmin>0)tmin--;
}
}
while(!P30);
}
}
}
2、icc.c
/*
程式說明: IIC總線驅動程式
軟體環境: Keil uVision 4.10
硬體環境: CT107單片機綜合實訓平臺 8051,12MHz
日 期: 2011-8-9
*/
#include "reg52.h"
#include "intrins.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//總線引腳定義
sbit SDA = P2^1; /* 資料線 */
sbit SCL = P2^0; /* 時鐘線 */
//總線啟動條件
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(bit 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;
}
}
//通過I2C總線發送資料
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;
}
}
//從I2C總線上接收資料
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;
}
unsigned char AD_get(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
void AD_write(unsigned char add,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char EEPROM_get(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
void EEPROM_write(unsigned char add,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_WaitAck();
IIC_SendByte(dat);
IIC_Stop();
}
3、onewire.c
/*
程式說明: 單總線驅動程式
軟體環境: Keil uVision 4.10
硬體環境: CT107單片機綜合實訓平臺(外部晶振12MHz) STC89C52RC單片機
日 期: 2011-8-9
*/
#include "reg52.h"
sbit DQ = P1^4; //單總線介面
//單總線延時函式
void Delay_OneWire(unsigned int t) //STC89C52RC
{
char i;
while(t--)
{
for(i=12;i>0;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;
}
unsigned char temperature_rd(void)
{
unsigned char low,high;
unsigned char temp;
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<<4;
temp|=low>>4;
return temp;
}
float temperature_rd_F(void)
{
unsigned char low,high;
unsigned int temp;
float temperature;
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&0x0f;
temp<<=8;
temp|=low;
temperature=temp*0.0625;
return temperature;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/183363.html
標籤:其他
上一篇:做站程序中域名注冊重要嗎?
