蓝桥杯单片机 第三届到十三届历年真题及部分代码
可以先在草稿纸上,把基础的界面显示,按键功能,LED的亮灭功能,以及参数的设定等等,有大致的了解之后再进行代码的编写。蓝桥杯单片机比赛需要用到的知识有:数电知识+模电知识+C语言知识+单片机知识(考试时可用比赛时给的PDF阅读器查看STC手册的知识)。(选择题的基础,本人学习在参加蓝桥杯之前都已学过,若没有学习过的同学需要多加准备了。注:以上内容大多数都是小蜜蜂老师的内容,可能存在部分的问题,希望
一、本人在准备过程中遇到的问题:
1、矩阵键盘不稳定的情况:可以看看下面链接的内容,有多种按键的处理方法。
2、串口通信时ISP软件无法接受到信息:
例如stc-isp-15xx-v6.86r,可以将最低波特率和最高波特率调节相同的波特率。
3、使用DS18B20时会读到85℃:在主程序中引用下面的代码,并且加上750ms的延时函数
void ds18b20_init()
{
unsigned char lsb,msb;
unsigned int tep;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
do
{
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
lsb=Read_DS18B20();
msb=Read_DS18B20();
tep=msb;
tep=(msb<<4)|(lsb>>4);
}while(tep==85);
void Delay750ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
void ds18b20_init();
void Delay750ms();
while(1)
{
}
}
4、使用DS1302时,时钟停止不动:这是一个小常识
void main()
{
ds1302_wirte();
while(1)
{
ds1302_read();
}
}
二、比赛准备与学习
蓝桥杯单片机比赛需要用到的知识有:数电知识+模电知识+C语言知识+单片机知识(考试时可用比赛时给的PDF阅读器查看STC手册的知识)。
选择题有15分,10小题,一题1.5分。(选择题的基础,本人学习在参加蓝桥杯之前都已学过,若没有学习过的同学需要多加准备了。)
设计题:应该先把考试会考到的几大模块摸索清楚,这里推荐B站【小蜜蜂笔记】的视频。清楚基本的内容后可以看历年的真题。看到真题时,不要盲目的下手,直接就开始打代码。可以先在草稿纸上,把基础的界面显示,按键功能,LED的亮灭功能,以及参数的设定等等,有大致的了解之后再进行代码的编写。
三、主要的学习资源
2、历年选择题答案与解析
小蜜蜂老师的宝藏网站!!!
https://www.xmf393.com/2019/06/11/lqbmcu/https://www.xmf393.com/2019/06/11/lqbmcu/
3、设计题的代码驱动修改 (以14届为例)
4、历年设计https://pan.baidu.com/s/1GNSoH7eSqL-r3zMhZoxTEg 提取码:235u
四、各模块的主要程序(考前模块总结)
下面的内容需要对各模块功能有一定了解。
1、PCF8591 (iic.h)
unsigned char adc_value=0;//采样电压
float adc_volt=0; //换算电压
unsigned int smg_volt; //数码管显示电压
void read_adc()//ADC
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
adc_value=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
adc_volt=adc_value*(5.0/255);
smg_volt=adc_volt*100;
}
void read_dac(float dat)//DAC
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);//0x01为光敏电阻的A/D转换通道,0x03为电位器的A/D转换通道
//0x41为光敏电阻的A/D转换通道或者D/A,0x43为电位器的A/D转换通道或者D/A
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
2、24C02 (iic.h)
void write_24c02(unsigned char addr,unsigned char dat)//单字节写入
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);//需要存放的地址
IIC_WaitAck();
IIC_SendByte(dat);//需要存放的数据
IIC_WaitAck();
IIC_Stop();
}
unsigned char read_24c02(unsigned char addr)//单字节读出
{
unsigned char tmp=0;
//伪操作
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);//读指令
IIC_WaitAck();
tmp=IIC_RecByte();//读出数据
IIC_SendAck(1);
IIC_Stop();
return tmp;//返回读到的数据
}
3、DS18B20 (onewire.h)
//DS18B20 温度的读出与显示
void read_display_ds18b20()
{
unsigned char LSB,MSB;
unsigned int temp;
init_ds18b20();
Write_DS18B20(0xcc);//忽略ROM操作
Write_DS18B20(0x44);//启动温度转换
smg_dispalay();//延时
init_ds18b20();
Write_DS18B20(0xcc);//忽略ROM操作
Write_DS18B20(0xbe);//读出内部存储器
LSB=Read_DS18B20();//第0字节,温度的低8位
MSB=Read_DS18B20();//第1字节,温度的高8位
init_ds18b20();
temp=MSB;
temp=(temp<<8)|LSB;
if((temp&0xf800)==0x0000)//判断是否为正温度
{
temp_ds18b20=temp*0.0625;//计算实际温度
}
smg_ds18b20=temp_ds18b20;//若要保留一位小数点则temp_ds18b20*10,
//保留两位则 temp_ds18b20*100;
smg_dispalay();
}
4、DS1302 (ds1302.h)
void DS1302_W()
{
char i;
Write_Ds1302_Byte( 0x8e,0x00);//允许写入
for(i=0;i<7;i++)
{
Write_Ds1302_Byte( Write_DS1302_add[i],Timer[i]);
}
Write_Ds1302_Byte( 0x8e,0x80);//禁止写入
}
void DS1302_R()
{
char i;
for(i=0;i<7;i++)
{
Timer[i]=Read_Ds1302_Byte( Read_DS1302_add[i] );//将时钟读出
}
}
5、PWM信号
unsigned char count=0;//计数
unsigned char pwm_duty=0;//脉冲宽度,占空比
void Init_Timer0()//定时100us
{
TMOD = 0x01;
TH0=(65535-100)/256;
TL0=(65535-100)%256;
ET0=1;
EA=1;
}
void ServiceTimer0() interrupt 1
{
TH0=(65535-100)/256;
TL0=(65535-100)%256;
count++;
if(count==pwm_duty)
{
L1=1;
}
else if(count==100)//count==100,宽度为10ms
{
L1=0;
count=0;
}
}
6、NE555频率发生器
unsigned int count_t=0; //时间计数
unsigned int dat_f=0; //得到的实际频率
unsigned char count_f; //频率计数
void Init_Timer() //T0计数,模式二。T1定时,模式一。
{
TH0=0xff;
TL0=0xff;
TH1=(65535 - 50000 +1)/256;
TL1=(65535 - 50000 +1)%256;
TMOD=0x16;//0001 0110
ET0=1;
ET1=1;
EA=1;
TR0=1;
TR1=1;
}
void Service_T0() interrupt 1
{
count_f++; //频率计数
}
void Service_T1() interrupt 3
{
TH1=(65535 - 50000 +1)/256;
TL1=(65535 - 50000 +1)%256;
count_t++;
if(count_t==20) //当定时50ms*20=1s,
{
dat_f=count_f; //得到实际频率
count_f=0; //重新测频率,先清零
count_t=0; //定时计数重新开始,先清零
}
}
7、超声波
sfr AUXR=0x8e;
sbit TX=P1^0;
sbit RX=P1^1;
void Delay13ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 1;
j = 152;
k = 187;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void send_wave() //产生8个40KHZ的信号
{
unsigned char i;
for(i=0;i<8;i++)
{
TX=0; //发送
Delay13us();
TX=1;
Delay13us();
}
}
unsigned int get_distance() //得到测量距离
{
unsigned long distant;
AUXR |=0x80;
TL0=0x00;
TH0=0x00;
send_wave();
TR0=1; //打开定时器
while((RX==1)&&(TF0==0)); //等待超声波返回,或者等待测量距离超出范围
TR0=0; //关闭定时器
if(TF0==0) //在正常的距离范围
{
distant=TH0*256+TL0;
distant=(distant*170)/110592;
}
else //不正常的距离范围
{
TF0=0;
distant=999;
}
return distant;
}
8、串口通信
void InitUart()
{
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
TR1=1;
SCON=0x50;
AUXR=0x00;
ES=1;
EA=1;
}
unsigned char command=0x00;//上位机内容
void ServiceUart() interrupt 4 //接受完成用中断
{
if(RI==1)
{
command=SBUF; //接受完成则将内容传给上位机
RI=0;;
}
}
void SendByte(unsigned char dat) //发送完成用查询
{
SBUF=dat;
while(TI==0);
TI=0;
}
void SendString(unsigned char *s) //发送字符串
{
while(*s!='\0')
{
SendByte(*s++);
}
}
注:以上内容大多数都是小蜜蜂老师的内容,可能存在部分的问题,希望大家给予指正。
更多推荐
所有评论(0)