第十四届蓝桥杯单片机组(赛题+程序)
该赛题考于2023.4.8 ,于2023.4.28 复盘。
今年的题目是比较难的了,模块多,而且逻辑也更加复杂,考了NE555、I2C、DS1302、DS18B20,同时客观题也不好做。
笔者客观题只对3个,程序题大概完成80%,勉强进入省一。
答案: 1.D 2.B 3.ABC 4.D 5.A 6.AC 7.A 8.B 9.D 10.ABD
/* ***************************
第十四届蓝桥杯单片机组程序
by wull
2023.4.28
**************************** */
#include "STC15.h"
#include "iic.h"
#include "onewire.h"
#include "ds1302.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e, //F 15
0xff, //灭 16
0xbf, //- 17 10111111
0x89, //H 18 10001001
0x8c //P 19 10001100
};
//********************温湿度采集数据记录变量**************
uchar xdata temper_caiji[100]={0}; // 温度存放
uchar temper_max; // 温度最大值
long int temper_sum=0; // 温度总和
float temper_ave; // 温度平均值(浮点数)
uint temper_aver; // 温度平均值(整数)
uchar xdata shidu_caiji[100]={0}; // 湿度存放
uchar shidu_max; // 湿度最大值
long int shidu_sum=0; // 湿度总和
float shidu_ave; // 湿度平均值(浮点数)
uint shidu_aver; // 湿度平均值(整数)
//******************************************************
uchar dspcom=0; // 数码管位选标志位
uchar dspbuff[8]={16,16,16,16,16,16,16,16}; // 8个数码管
uchar now[7]={0}; // 时间的 时分秒存放
uchar ad_value; // 光敏电阻电压
uint v_value; // 光敏电阻电压*10
uchar temper,Shidu,Canshu=30,Chufa=0; // 温度,湿度,参数,触发值
uchar Jiemian=1,Huixian=1; // 界面切换值,回显界面切换值
uint count_t=0,intr=0,intr1=0,intr2=0; // 计数变量
uint count_f; // 频率计数
uint dat_f; // 频率值
bit F_key = 0,Lightstate; // 按键按下标志
uint keycount= 0; // 按键计数变量
bit flag,flag1,flag2; // 标志位
//***********************初始化**************************
void InitAll() // 初始化 关闭LED 蜂鸣器等
{
P2=(P2&0x1f)|0xa0;
P0=0x00;
P2=(P2&0x1f)|0x80;
P0=0xff;
P2=(P2&0x1f);
}
void Timer0_Init(void) // 定时器1 计数
{
TMOD = 0x1F; //设置定时器模式
TL0 = 0xff; //设置定时初始值
TH0 = 0xff; //设置定时初始值
TR0 = 1; //定时器1开始计时
ET0=1;
EA=1;
}
void Timer1_Init(void) //2毫秒@12.000MHz // 定时器2 定时2ms
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x30; //设置定时初始值
TH1 = 0xF8; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1=1;
EA=1;
}
void DisplaySMG() //数码管显示 位选+段选
{
P2=(P2&0x1f)|0xe0;
P0=0xff;
P2=(P2&0x1f)|0xc0;
P0=1<999999) dspbuff[1]=dat_f/1000000;
// else dspbuff[1]=19;
// if(dat_f>99999) dspbuff[2]=dat_f/100000%10;
// else dspbuff[2]=19;
// if(dat_f>9999) dspbuff[3]=dat_f/10000%10;
// else dspbuff[3]=19;
// if(dat_f>999) dspbuff[4]=dat_f/1000%10;
// else dspbuff[4]=19;
// if(dat_f>99) dspbuff[5]=dat_f/100%10;
// else dspbuff[5]=19;
// if(dat_f>9) dspbuff[6]=dat_f/10%10;
// else dspbuff[6]=19;
// dspbuff[7]=dat_f%10;
// dspbuff[5]=v_value/100;
// dspbuff[6]=v_value/10%10;
// dspbuff[7]=v_value%10;
}
void Display4() // 温湿度界面
{
dspbuff[0]=14;
dspbuff[1]=16;dspbuff[2]=16;
dspbuff[3]=temper/10;
dspbuff[4]=temper%10;
dspbuff[5]=17;
if((Shidu>10)&&(Shidu<90))
{
dspbuff[6]=Shidu/10;
dspbuff[7]=Shidu%10;
}
else
{
dspbuff[6]=10;
dspbuff[7]=10;
}
}
void DisplayLED() // LED指示灯功能
{
P2=(P2&0x1f)|0x80;
if(Jiemian==1) P00=0; // LED1亮
else P00=1;
if(Jiemian==2) P01=0; // LED2亮
else P01=1;
if(Jiemian==3) P02=0; // LED3亮
else P02=1;
if(temper>Canshu)
{
if(intr1<50) P03=0; // LED4闪烁
else P03=1;
}
else P03=1;
if((Shidu>10)&&(Shidu<90))
{
P04=1;
}
else
{
P04=0; // LED5亮
}
if(Chufa>=2)
{
if((temper_caiji[Chufa]50)
{
Lightstate=1; //亮状态
}
if(Lightstate==1)
{
if(v_value<50)
{
Lightstate=0;
Chufa++; //触发值+1
temper_caiji[Chufa-1]=temper; //温度值采集
if((Shidu>10)&&(Shidu<90))
{
shidu_caiji[Chufa-1]=Shidu; //湿度值采集
}
flag2=1;
Display4(); //界面4 温湿度界面
Delay3000ms(); // 持续3s
flag2=0;
}
}
temper_max=temper_caiji[0]; //求温度最大值,平均值
temper_sum=temper_caiji[0];
for(i=1;i98) Canshu=0;
else Canshu++;
}
}
while(!P33);
}
if(P32==0) //S9
{
Delay5ms();
if(P32==0)
{
keycount = 0;
F_key = 1; //标志按键按下状态
while(P32== 0) //等待按键松开
{
}
F_key = 0;
if(keycount> 1000) //按下时间大于2秒,长按
{
if((Huixian==3)&&(Jiemian==2))
{
Chufa = 0; //触发次数清除为00
}
}
else //按下时间小于2秒,短按 温度参数-1
{
if(Jiemian==3)
{
if(Canshu<1) Canshu=99;
else Canshu--;
}
}
}
}
}
//***************************************************************
//******************************MAIN********************************
void main()
{
InitAll();
Timer0_Init();
Timer1_Init();
ds1302_writepro(0);
ds1302_Settime(0x13,0x03,0x05); // DS1302初始时间
ds1302_writepro(1);
while(1)
{
if(flag) //定时器每隔0.2s读取数据
{
flag=0;
ReadTime(); //读时间
Init_PCF8591();
ad_value=Read_PCF8591(); //读光敏电阻电压
v_value=ad_value*100/51;
temper=ReadTemper(); //读温度
}
if(Jiemian==1)
{
Display1();
}
else if(Jiemian==2)
{
Display2();
}
else if(Jiemian==3)
{
Display3();
}
Keyscan();
DisplayLED();
CaijiChufa();
}
}
//************************中断服务函数***********************
void intr_Timer0() interrupt 1
{
count_f++; //频率值计数
}
void intr_Timer1() interrupt 3
{
DisplaySMG();
if(F_key == 1) //在按键按下期间进行计数
{
keycount++; //按键按下的持续时间
}
if(++intr==50) //数据读取间隔时间
{
flag=1;
intr=0;
}
if(++intr1==100) //闪烁0.1S定时
{
intr1=0;
}
if(++count_t==500) //1S定时
{
dat_f=count_f; //频率值
count_f=0;
count_t=0;
Shidu=2*dat_f/45+(10/9); //湿度值换算
}
}
//*************************************************************
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "STC15.h"
#include "intrins.h"
sbit scl=P2^0;
sbit sda=P2^1;
#define DELAY_TIME 5
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
void Init_PCF8591()
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x01);
I2CWaitAck();
I2CStop();
}
unsigned char Read_PCF8591()
{
unsigned char temp;
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
temp=I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return temp;
}
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "STC15.h"
#include "intrins.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;
//
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "STC15.h"
sbit DQ=P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
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);
}
//
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;
}
//
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 ReadTemper()
{
unsigned char temp;
unsigned LSB,MSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
while(!DQ);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
temp=LSB>>4;
temp=temp|(MSB<<4);
return temp;
}
第十四届蓝桥杯单片机演示视频