前言
蓝桥杯单片机——第十一届省赛赛题二解析
今年我也参加了第十三届的蓝桥杯单片机组省赛题,分享一下我在练习时写的代码,因为我是第一次
参加,如果有错误的地方欢迎大家指出来。我们大家一起加油进步,打造美好的明天!
一、题目
这次题目,就我个人而言难度还是比较简单的,没有什么特别难的地方,赛题总体难度中规中矩,考
的都是一些经常用到并考到的模块。
比如独立键盘、LED指示灯、数码管显示模块、DS18B20、PCF8591,这些都是蓝桥杯板子中基础的
模块,相信大家在平时的练习中都经常写过,都唯一需要注意的地方就是DAC输出,因为比赛考的比
较少,难免有可能一下子忘了怎么写。
其中那个按S4进行界面切换的时候,需要检测参数合理性,大家可以直接在进入参数界面时,将温度最大值和温度最小值分别赋给一个变量储存起来,在进入数据界面显示时在进行判定,不合理则分别将参数赋值回来。
二、代码部分
1.IIC.C
根据官方给出的驱动代码进行修改并加入自己的执行代码。(其中的ad_read函数在试题中并没有什
么大用,因为这套题根本用不了读取函数,纯粹是我在写代码时没怎么审题、直接就把这个给写出来
了。。。。。我也懒的删除了,大家直接忽略便是)
代码如下(示例):
#include "iic.h"
#define DELAY_TIME 5
//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//I2C总线启动信号
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//I2C总线停止信号
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//I2C总线发送一个字节数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//I2C总线接收一个字节数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
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_WaitAck();
IIC_Stop();
return temp;
}
void ad_write(unsigned char dat)
{
EA=0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
EA=1;
}
2.IIC.H
代码如下(示例):
#ifndef _IIC_H
#define _IIC_H
#include "stc15f2k60s2.h"
#include "intrins.h"
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
void IIC_Delay(unsigned char i);
unsigned char ad_read(unsigned char add);
void ad_write(unsigned char dat);
#endif
3.onewire.h
#include "onewire.h"
//单总线内部延时函数
void Delay_OneWire(unsigned int t)
{
while(t--);
}
//单总线写操作
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(50);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(50);
}
//单总线读操作
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
Delay_OneWire(1);
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(50);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(120);
DQ = 0;
Delay_OneWire(800);
DQ = 1;
Delay_OneWire(100);
initflag = DQ;
Delay_OneWire(50);
return initflag;
}
unsigned char ds_read()
{
unsigned char temp;
unsigned char low,high;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
Delay_OneWire(200);
low=Read_DS18B20();
high=Read_DS18B20();
temp=(high<<4)|(low>>4);
return temp;
}
4.onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include "stc15f2k60s2.h"
sbit DQ = P1^4;
unsigned char ds_read();
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
5. main.c
#include "IIC.H"
#include "onewire.h"
sbit S7=P3^0;
sbit S6=P3^1;
sbit S5=P3^2;
sbit S4=P3^3;
#define uchar unsigned char
uchar temp[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0XFF,0xc6,0x8c}; //12c,13P
uchar yi,er,san,si,wu,liu,qi,ba;
unsigned char tempare;
unsigned int voltage,mode=0,team=0,TMAX;TMIN,jia=30,jian=20,mode_tt=0,tempare_tt=0,sflg=1;
void delayms(int ms);
void us_waishe();
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 discan();
void Timer0Init(void);
void mode0_dis();
void mode1_dis();
void display();
void main()
{
Timer0Init();
us_waishe();
while(1)
{
voltage=ad_read(0x03);
mode1_dis();
mode0_dis();
display1(yi,er);
display2(san,si);
display3(wu,liu);
display4(qi,ba);
discan();
display();
}
}
void display()
{
if((jia>jian)||(jia=jian))
{
if(tempare>jia)
{
ad_write(204);P2=0X80;P0=0XFE;
}
else if((tempare>=jian)&&(tempare<=jia))
{
ad_write(153);P2=0X80;P0=0XFD;
}
else if(tempare<jian)
{
ad_write(102);P2=0X80;P0=0XFB;
}
}
else
{
P2=0X80;P0=0XFF;
}
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
void Timer0() interrupt 1
{
mode_tt++;tempare_tt++;
if(mode_tt==200) //每200ms选中的模块闪一次
{
if(mode==1)sflg=1; //sflg==1时全显
}
else if(mode_tt==400)
{
mode_tt=0;
if(mode==1)sflg=0;
}
if(tempare_tt==400) //每400ms刷新一次温度
{
tempare_tt=0;
tempare=ds_read();
}
}
void mode0_dis()
{
if(mode==0) //数据界面
{
yi=12;er=11;san=11;si=11;wu=11;liu=11;qi=tempare/10;ba=tempare%10;
}
}
void mode1_dis() //参数界面显示函数
{
if(mode==1)
{
if(sflg==1)
{
if((jia/10!=0)&&(jian/10!=0)) //判断是两位数还是一位数
{
yi=13;er=11;san=11;si=jia/10;wu=jia%10;liu=11;qi=jian/10;ba=jian%10;
}
else if((jia/10==0)&&(jian/10==0))
{
yi=13;er=11;san=11;si=11;wu=jia;liu=11;qi=11;ba=jian;
}
else if((jia/10!=0)&&(jian/10==0))
{
yi=13;er=11;san=11;si=jia/10;wu=jia%10;liu=11;qi=11;ba=jian;
}
else if((jia/10==0)&&(jian/10!=0))
{
yi=13;er=11;san=11;si=11;wu=jia;liu=11;qi=jian/10;ba=jian%10;
}
}
else if(sflg==0)
{
if(team==1) //TMIN
{
if(jia/10!=0) //判断是两位数还是一位数
{
yi=13;er=11;san=11;si=jia/10;wu=jia%10;liu=11;qi=11;ba=11;
}
else if(jia/10==0)
{
yi=13;er=11;san=11;si=11;wu=jia;liu=11;qi=11;ba=11;
}
}
else if(team==0) //TMAX
{
if(jian/10!=0) //判断是两位数还是一位数
{
yi=13;er=11;san=11;si=11;wu=11;liu=11;qi=jian/10;ba=jian%10;
}
else if(jian/10==0)
{
yi=13;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=jian;
}
}
}
}
}
void discan()
{
if(S4==0)
{
delayms(5);
if(S4==0)
{
if(mode==0)
{
TMAX=jia;TMIN=jian;
mode=1;team=1;
} //mode=0进入数据界面,mode=1进入参数界面。(有问题)
else if(mode==1)
{
mode=0;
if(jia<jian) //参数不合理则赋值;
{
jia=TMAX;jian=TMIN;
}
// else if(jia>=jian)
// {
// jia=jia;jian=jian;
// }
}
}
while(!S4);
}
else if(S5==0)
{
delayms(5);
if(S5==0)
{
if(team==0)team=1; //team=0时,选择TMAX,team=1时,选择TMIN
else if(team==1)team=0;
}
while(!S5);
}
else if(S6==0)
{
delayms(5);
if(S6==0)
{
if(mode==1)
{
if(team==0)
{
if((jia<100)&&(jia>=0))jia=jia+1;
}
else if(team==1)
{
if((jian>=0)&&(jian<100))jian=jian+1;
}
}
}
while(!S6);
}
else if(S7==0)
{
delayms(5);
if(S7==0)
{
if(mode==1)
{
if(team==0)
{
if((jia<100)&&(jia>0))jia=jia-1;
}
else if(team==1)
{
if((jian<100)&&(jian>0))jian=jian-1;
}
}
}
while(!S7);
}
}
void us_waishe()
{
P2=0X80;P0=0XFF;
P2=0XA0;P0=0X00;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
void delayms(int ms)
{
unsigned int i,j;
for(i=ms;i>0;i--)
for(j=845;j>0;j--);
}
void display1(uchar yi,uchar er)
{
P2=0XC0;
P0=0X01;
P2=0XE0;
P0=temp[yi];
delayms(1);
P2=0XC0;
P0=0X02;
P2=0XE0;
P0=temp[er];
delayms(1);
}
void display2(uchar san,uchar si)
{
P2=0XC0;
P0=0X04;
P2=0XE0;
P0=temp[san];
delayms(1);
P2=0XC0;
P0=0X08;
P2=0XE0;
P0=temp[si];
delayms(1);
}
void display3(uchar wu,uchar liu)
{
P2=0XC0;
P0=0X10;
P2=0XE0;
P0=temp[wu];
delayms(1);
P2=0XC0;
P0=0X20;
P2=0XE0;
P0=temp[liu];
delayms(1);
}
void display4(uchar qi,uchar ba)
{
P2=0XC0;
P0=0X40;
P2=0XE0;
P0=temp[qi];
delayms(1);
P2=0XC0;
P0=0X80;
P2=0XE0;
P0=temp[ba];
delayms(1);
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
总结
这些就是蓝桥杯单片机第十一届省赛题赛题二的解析部分,祝大家都能进郭赛!!!!!!!!!!!!