第十届蓝桥杯单片机省赛题目解析
·
话不多说,我们一起来看看第十届(2019)的题目吧。
题目
这次的题目还是三大模块(数码管、LED、按键),还用到了ADC、DAC、NE555,除了NE555之前没有见过,其他也都是一些常见的外设,只要平常都练习过,也就不难,最重要的还是编程逻辑。
1 数码管显示
数码管有电压测量界面和频率测量界面。
2 LED
界面为电压测量界面L1亮,频率测量界面L2亮,电压在[1.5,2.5)或者>=3.5V时L3亮,频率在[1k,5k)或者>=10k时L4亮,当输出固定电压时L5灭,否则L5亮。
3 按键模块
使用的是独立按键,s4是电压测量界面和频率测量界面的切换,s5是DAC固定输出电压或者DAC输出随电压器输出电压变化而变化,s6是LED的开关,s7是数码管显示的开关。
4 NE555
NE555就是使用两个定时器,一个用来计数,一个用来定时。其中定时1ms看计数记录了多少,转动RB3,频率会改变。
5 ADC
就是改写底层驱动代码部分(IIC)。
6 DAC
就是改写底层驱动代码部分(IIC)。
IIC.c
#include"IIC.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
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;
}
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;
}
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 Read_AD()
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
void DA_out(unsigned char date)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(date);
IIC_WaitAck();
IIC_Stop();
}
IIC.h
#ifndef _IIC_H_
#define _IIC_H_
#include<stc15f2k60s2.h>
#include<intrins.h>
void IIC_Delay(unsigned char i);
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
unsigned char Read_AD();
void DA_out(unsigned char date);
#endif
init.c
#include"init.h"
#define u8 unsigned char
#define u16 unsigned int
#define state_0 0
#define state_1 1
#define state_2 2
static u8 key_state,key_num,key_press,segadder;
u8 value=0;
extern bit mode,tube;
extern u8 a;
u8 code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc1,0xce};
u8 seg[]={11,11,11,11,11,11,11,11};
void all_init() //关闭无关外设
{
P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xa0;P04=0;P06=0;P2&=0x1f;
P2=(P2&0x1f)|0xc0;P0=0x00;P2&=0x1f;
P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
}
void display() //数码管显示函数
{
P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xc0;P0=1<<segadder;P2&=0x1f;
P2=(P2&0x1f)|0xe0;
if((a==1||mode==0)&&segadder==5&&tube==1)
P0=tab[seg[segadder]]&0x7f;
else
P0=tab[seg[segadder]];
P2&=0x1f;
if(++segadder==8)segadder=0;
}
u8 Read_key() //独立键盘
{
key_press=P3&0x0f;
switch(key_state)
{
case state_0:
if(key_press!=0x0f)
key_state=state_1;
break;
case state_1:
if(key_press!=0x0f)
{
if((key_press & 0x08)==0) key_num=4;
if((key_press & 0x04)==0) key_num=5;
if((key_press & 0x02)==0) key_num=6;
if((key_press & 0x01)==0) key_num=7;
key_state=state_2;
}
else
key_state=state_0;
break;
case state_2:
if(key_press==0x0f)
key_state=state_0;
break;
}
value=key_num;
key_num=0;
return value;
}
void Timer1Init(void) //定时器1定时1ms
{
AUXR |= 0x40;
TMOD &= 0x0F;
TL1 = 0xCD;
TH1 = 0xD4;
TF1 = 0;
TR1 = 1;
EA = 1;
ET1 = 1;
}
void Timer0Init(void) //定时器0 调到计数模式
{
TMOD = 0x04;
TL0 = 0;
TH0 = 0;
TF0 = 0;
TR0 = 1;
ET0 = 1;
}
init.h
#ifndef _INIT_H_
#define _INIT_H_
#include<stc15f2k60s2.h>
void all_init();
void display();
unsigned char Read_key();
void Timer1Init(void);
void Timer0Init(void);
#endif
jm.c
#include"jm.h"
#define u8 unsigned char
#define u16 unsigned int
extern bit mode,v,led,tube; // extern表示此变量是在别处定义的,要在此处引用
extern u8 seg[];
extern u16 F,RB2;
void jm4()
{
if(mode==0)
jm5(); //电压测量界面
else //频率测量界面
{
seg[0]=13;
seg[1]=11;
seg[2]=11;
if(F/10000!=0)
{
seg[3]=F/10000;
seg[4]=F/1000%10;
seg[5]=F/100%10;
seg[6]=F/10%10;
seg[7]=F%10;
}
else if(F/1000!=0)
{
seg[3]=11; //未使用到的数码管熄灭
seg[4]=F/1000;
seg[5]=F/100%10;
seg[6]=F/10%10;
seg[7]=F%10;
}
else if(F/100!=0)
{
seg[3]=11;
seg[4]=11;
seg[5]=F/100;
seg[6]=F/10%10;
seg[7]=F%10;
}
else
{
seg[3]=11;
seg[4]=11;
seg[5]=11;
seg[6]=F/10;
seg[7]=F%10;
}
}
}
void jm5()
{
if(v==0)
{
seg[0]=12;
seg[1]=11;
seg[2]=11;
seg[3]=11;
seg[4]=11;
seg[5]=2;
seg[6]=0;
seg[7]=0;
}
else if(v==1)
{
seg[0]=12;
seg[1]=11;
seg[2]=11;
seg[3]=11;
seg[4]=11;
seg[5]=RB2/100;
seg[6]=RB2/10%10;
seg[7]=RB2%10;
}
}
void jm6() //LED函数
{
u8 i=0xff;
if(led==1)
{
if(mode==0)
{
P2=(P2&0x1f)|0x80;P0=0xfe;P2&=0x1f;
}
else
{
P2=(P2&0x1f)|0x80;P0=0xfd;P2&=0x1f;
}
if((RB2>=150&&RB2<250)||(RB2>350))
{
P2=(P2&0x1f)|0x80;P02=0;P2&=0x1f;
}
else
{
P2=(P2&0x1f)|0x80;P02=1;P2&=0x1f;
}
if((F>=1000&&F<5000)||(F>=10000))
{
P2=(P2&0x1f)|0x80;P03=0;P2&=0x1f;
}
else
{
P2=(P2&0x1f)|0x80;P03=1;P2&=0x1f;
}
if(v==1)
{
P2=(P2&0x1f)|0x80;P04=0;P2&=0x1f;
}
else
{
P2=(P2&0x1f)|0x80;P04=1;P2&=0x1f;
}
}
else
{
P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;
}
}
void jm7() //数码管开关函数
{
if(tube==0)
{
seg[0]=11;
seg[1]=11;
seg[2]=11;
seg[3]=11;
seg[4]=11;
seg[5]=11;
seg[6]=11;
seg[7]=11;
}
else
jm4();
}
jm.h
#ifndef _JM_H_
#define _JM_H_
#include<stc15f2k60s2.h>
void jm4();
void jm5();
void jm6();
void jm7();
#endif
main.c
#include"init.h"
#include"IIC.h"
#include"jm.h"
#define u8 unsigned char
#define u16 unsigned int
u8 num=0,a=0,b=0;
u16 RB2_count=0,F_count=0,F=0,RB2=0;
bit mode=0,v=0,led=1,tube=1,F_flag=0,RB2_flag=0;
void main()
{
all_init();
Timer1Init();
Timer0Init();
while(1)
{
num=Read_key();
switch(num)
{
case 4:
mode^=1;
a=0;
break;
case 5:
v^=1;
a=1;
break;
case 6:
led^=1;
b=0;
break;
case 7:
tube^=1;
jm7();
break;
}
if(a==0&&tube==1)jm4();
if(a==1&&tube==1)jm5();
if(b==0)jm6();
if(F_flag==1) //计算频率
{
F_flag=0;
TR0=0;
F=TH0*256+TL0;
TL0=0;
TH0=0;
TR0=1;
}
if(RB2_flag==1)
{
RB2_flag=0;
RB2=Read_AD();
if(v==0)DA_out(102.4); //DAC输出
else DA_out(RB2);
RB2=(RB2*100)/51.0+0.5;
}
}
}
void Timer1() interrupt 3
{
display();
if(++RB2_count==500)
{
RB2_count=0;
RB2_flag=1;
}
if(++F_count==1000)
{
F_count=0;
F_flag=1;
}
}
更多推荐
已为社区贡献9条内容
所有评论(0)