

注:第五屆模擬題即第四屆藍橋杯單片機省賽試題




對賽題沒什么好分析的,跟第三屆相比難度差不多,都挺簡單的,直接上程式吧,注釋也都在程式里標明了,

main.c程式
#include<stc15f2k60s2.h>
#include "iic.h"
#include "ds1302.h"
#define uchar unsigned char //定義無符號字符型別uchar
#define uint unsigned int //定義無符號整型型別uint
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//數字0~9,“-”,“關”
uchar yi,er,san,si,wu,liu,qi,ba; //定義字符型變數yi,er,san,si,wu,liu,qi,ba,當作數碼管顯示控制變數
extern unsigned char shijian[]; //呼叫DS1302定義時間陣列
bit S7=0,S6=0,kai=0,relay=0,jia=0,jian=0;
uchar shidu,fazhi;
void delayms(int ms); //延時函式
void allinit(); //初始化函式
void keyscan(); //獨立按鍵函式
void display1(uchar yi,uchar er); //第一、二段數碼管函式
void display2(uchar san,uchar si); //第三、四段數碼管函式
void display3(uchar wu,uchar liu); //第五、六段數碼管函式
void display4(uchar qi,uchar ba); //第七、八段數碼管函式
void main()//主函式
{
allinit(); //初始化函式
DS_int(); //初始化DS1302
P2=0X80;P0=0XFE; //打開L1
fazhi=EEPROM_read(0x20); //從EEPROM里讀取閾值
while(1)
{
DS_get(); //呼叫時鐘讀取函式
shidu=AD_read(0x03); //讀取濕度
if(S7==0) //判斷是否在自動狀態下
{
if(shidu<fazhi){P2=0XA0;P0=0X10;} //濕度小于閾值的話繼電器打開
else{P2=0XA0;P0=0X00;} //濕度大于或等于閾值的話繼電器關閉
if(S6==1){ //判斷是否在濕度閾值調整頁面
if(jia==1){jia=0;fazhi=fazhi+1;} //判斷S5按鍵是否按下,如果是閾值加一
else if(jian==1){jian=0;fazhi=fazhi-1;} //判斷S5按鍵是否按下,如果是閾值減一
yi=10;er=10;san=11;si=11;wu=11;liu=11;qi=fazhi/10;ba=fazhi%10; //顯示閾值調整頁面
}
else if(S6==0){ //判斷是否在時間與濕度資料顯示頁面
yi=shijian[2]/10;er=shijian[2]%10;san=10;si=shijian[1]/10;wu=shijian[1]%10;liu=11;qi=shidu/10;ba=shidu%10; //顯示時間與濕度資料
}
}
else if(S7==1) //判斷是否在手動狀態下
{
if((shidu<fazhi)&&(kai==0)){ //判斷濕度是否小于閾值且蜂鳴器關狀態
if(relay==0){P2=0XA0;P0=0X00;} //如果此時繼電器關閉,則繼電器和蜂鳴器都不作業
else if(relay==1){P2=0XA0;P0=0X10;} //如果此時繼電器打開,則打開繼電器,蜂鳴器則不作業
}
if((shidu<fazhi)&&(kai==1)){ //判斷濕度是否小于閾值且蜂鳴器開狀態
if(relay==0){P2=0XA0;P0=0X40;} //如果此時繼電器關閉,則只打開蜂鳴器
else if(relay==1){P2=0XA0;P0=0X50;} //如果此時繼電器打開,則打開繼電器和蜂鳴器
}
if(shidu>fazhi){ //判斷濕度是否大于閾值
if(relay==0){P2=0XA0;P0=0X00;} //判斷繼電器是否為關狀態,如果是關狀態,則關閉繼電器
else if(relay==1){P2=0XA0;P0=0X10;} //判斷繼電器是否為開狀態,如果是開狀態,則開啟繼電器
}
yi=shijian[2]/10;er=shijian[2]%10;san=10;si=shijian[1]/10;wu=shijian[1]%10;liu=11; qi=shidu/10;ba=shidu%10; //顯示時間與濕度資料
}
keyscan(); //獨立按鍵函式
display1(yi,er); //第一、二段數碼管函式
display2(san,si); //第三、四段數碼管函式
display3(wu,liu); //第五、六段數碼管函式
display4(qi,ba); //第七、八段數碼管函式
}
}
void delayms(int ms)//延時函式
{
uint i,j;
for(i=ms;i>0;i--)
for(j=845;j>0;j--);
}
void allinit()//初始化函式
{
P2=0XA0;P0=0X00; //關閉蜂鳴器繼電器
P2=0X80;P0=0XFF; //關閉所有LED燈
P2=0XC0;P0=0XFF; //選中所有數碼管段選
P2=0XFF;P0=0XFF; //關閉所有數碼管
}
void display1(uchar yi,uchar er)//第一、二段數碼管函式
{
P2=0XC0;P0=0X01; //選中第一個數碼管位選
P2=0XFF;P0=tab[yi]; //讓第一個數碼管顯示yi指向的值
delayms(1); //延時1ms
P2=0XC0;P0=0X02; //選中第二個數碼管位選
P2=0XFF;P0=tab[er]; //讓第一個數碼管顯示er指向的值
delayms(1); //延時1ms
}
void display2(uchar san,uchar si)//第三、四段數碼管函式
{
P2=0XC0;P0=0X04; //選中第s三個數碼管位選
P2=0XFF;P0=tab[san]; //讓第一個數碼管顯示san指向的值
delayms(1); //延時1ms
P2=0XC0;P0=0X08; //選中第四個數碼管位選
P2=0XFF;P0=tab[si]; //讓第一個數碼管顯示si指向的值
delayms(1); //延時1ms
}
void display3(uchar wu,uchar liu)//第五、六段數碼管函式
{
P2=0XC0;P0=0X10; //選中第五個數碼管位選
P2=0XFF;P0=tab[wu]; //讓第一個數碼管顯示wu指向的值
delayms(1); //延時1ms
P2=0XC0;P0=0X20; //選中第六個數碼管位選
P2=0XFF;P0=tab[liu]; //讓第一個數碼管顯示liu指向的值
delayms(1); //延時1ms
}
void display4(uchar qi,uchar ba)//第七、八段數碼管函式
{
P2=0XC0;P0=0X40; //選中第七個數碼管位選
P2=0XFF;P0=tab[qi]; //讓第一個數碼管顯示qi指向的值
delayms(1); //延時1ms
P2=0XC0;P0=0X80; //選中第八個數碼管位選
P2=0XFF;P0=tab[ba]; //讓第一個數碼管顯示ba指向的值
delayms(1); //延時1ms
P2=0XC0;P0=0X80; //選中第八個數碼管位選
P2=0XFF;P0=0XFF; //讓第八個數碼管熄滅
}
void keyscan()//獨立按鍵函式
{
if(P30==0) //判斷P30是否等于0
{
delayms(5); //延時5ms
if(P30==0)
{
if(S7==0){S7=1;P2=0X80;P0=0XFD;}
else if(S7==1){S7=0;P2=0X80;P0=0XFE;}
}
while(!P30); //如果按鍵不松開,則一直回圈
}
else if(P31==0) //判斷P31是否等于0
{
delayms(5); //延時5ms
if(P31==0)
{
if(S7==0){ //判斷是否在自動狀態下
if(S6==0){S6=1;} //調整狀態下按鍵按下切換為資料顯示狀態
else if(S6==1){S6=0;EEPROM_write(0x20,fazhi);} //資料顯示狀態下按鍵按下切換為調整狀態并把閾值保存在EEPROM中
}
else if(S7==1){kai=~kai;} //在手動狀態下,蜂鳴器狀態取反
}
while(!P31); //如果按鍵不松開,則一直回圈
}
else if(P32==0) //判斷P32是否等于0
{
delayms(5); //延時5ms
if(P32==0)
{
if(S7==0){jia=1;} //判斷是否在自動狀態下按鍵,如果是按鍵功能為加
else if(S7==1){relay=1;} //判斷是否在手動狀態下按鍵,如果是按鍵功能為打開繼電器
}
while(!P32); //如果按鍵不松開,則一直回圈
}
else if(P33==0) //判斷P33是否等于0
{
delayms(5); //延時5ms
if(P33==0) //再次判斷P33是否等于0
{
if(S7==0){jian=1;} //判斷是否在自動狀態下按鍵,如果是按鍵功能為減
else if(S7==1){relay=0;} //判斷是否在手動狀態下按鍵,如果是按鍵功能為關閉繼電器
}
while(!P33); //如果按鍵不松開,則一直回圈
}
}
iic.c程式
#include<stc15f2k60s2.h>
#include "intrins.h"
#include "iic.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;
}
//等待應答
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_read(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();
temp=temp*0.39;
return temp;
}
unsigned char EEPROM_read(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_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
ds1302.c程式
#include<STC15F2K60S2.H>
#include <intrins.h>
#include <ds1302.h>
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302?′??
unsigned char shijian[]={0,30,8,0,0,0,0};
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SCK=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
RST=1;
_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
Write_Ds1302_Byte(address);
Write_Ds1302_Byte((dat/10<<4)|(dat%10)); /
RST=0;
}
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00,dat1,dat2;/
RST=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SCK=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
RST=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
RST=0;
SCK=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SCK=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SDA=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SDA=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
dat1=temp/16;
dat2=temp%16;
temp=dat1*10+dat2;/
return (temp);
}
void DS_int(void)
{
unsigned char i,add;
add=0x80;
Write_Ds1302(0x8e,0x00);
for(i=0;i<7;i++)
{
Write_Ds1302(add,shijian[i]);
add=add+2;
}
Write_Ds1302(0x8e,0x80);
}
void DS_get(void)
{
unsigned char i,add;
add=0x81;
Write_Ds1302(0x8e,0x00);
for(i=0;i<7;i++)
{
shijian[i]=Read_Ds1302(add);
add=add+2;
}
Write_Ds1302(0x8e,0x80);
}
iic.h程式
#ifndef _IIC_H
#define _IIC_H
void IIC_Start(void);
void IIC_Stop(void);
void IIC_SendByte(unsigned char byt);
bit IIC_WaitAck(void);
unsigned char IIC_RecByte(void);
unsigned char AD_read(unsigned char add);
unsigned char EEPROM_read(unsigned char add);
void EEPROM_write(unsigned char add,unsigned char dat);
#endif
ds1302.h程式
#ifndef __DS1302_H
#define __DS1302_H
void Write_Ds1302_Byte(unsigned char temp);
void Write_Ds1302( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302 ( unsigned char address );
void DS_int();
void DS_get();
#endif

第四屆藍橋杯單片機省賽作品演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/278930.html
標籤:其他
