一、比赛总结
趁着清明放假,对前一阶段比赛做做总结。这次蓝桥杯比赛还是相当可以的,没有取得好成绩也是在意料之中。虽说不是很难,但如果之前没有充分的准备是不可能完完整整做出来的。尤其考了555定时器,虽说是很简单的应用,让P3.4输出正弦波,测它的频率,蓝桥杯单片机CT107D 555方波发生器可以产生实验所需的 200Hz 到 20Khz 的方波信号。通过改变Rb3大小即可调整555方波发生器输出方波频率,定时器0设为计数模式,但当时比赛就是做不出来,赛前我还看了那个官方的模拟题,就是简单的瞥了一眼,个人感觉不可能考吧。看到题的一瞬间,崩了,竟让出了。前一天晚上,我疯狂准备的DS1302实时时钟、DS18B20、EEPROM 都没用到,就用到了一个AD。总的来说,比赛重在参与,积累经验,不断提升自己的实力,当自己实力达到一定水平,奖这东西还不是信手拈来。不得补充一句这个比赛客观题也很重要,基本那个二十多分,再加上程序稍微做出来一点,省三不成问题。
二、程序设计分析
1.读取Rb2上的电压,利用竞赛提供的IIC底层驱动代码,设计程序,实现对电压的采集。
[注意]:PCF8591是具有IIC接口的8位A/D和D/A转换芯片,具有4路模拟输入、一路DAC输出和一个IIC总线接口。所以我们读取AIN3通道,得到数据应该是(0~255),为使显示到数码管上的数据为电压数据,要对读取的数据做一下处理,请看具体程序
“IIC,H”
#ifndef _IIC_H
#define _IIC_H
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
unsigned char IIC_Read(unsigned char add);
#endif
“IIC.C”
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "stc15f2k60s2.h"
#include "intrins.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);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
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 IIC_Read(unsigned char add)
{
unsigned char date;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
date = IIC_RecByte();
IIC_Stop();
return date;
}
2.555定时器相关函数
计数器T0和定时器T1中断来实现
这里我们设置C/T(计数定时器)0为计数器模式,C/T 1为定时器模式,因为C/T 0计数器模式的触发IO口(P3.4)就与SIGNAL相邻,因此用一个跳线帽连接即可。
/****************************定时器函数*****************/
void Timer0Init(void) //@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD = 0x05;
TL0 = 0x00; //设置定时初值
TH0 = 0x00; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer1Init(void) //5毫秒@11.0592MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x00; //设置定时初值
TH1 = 0x28; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA=1;
ET1=1;
}
void Service_time1() interrupt 3
{
static unsigned int counter=0;
counter++;
if(counter==200)
{ counter =0;
Fout=(TH0<<8)+TL0;
TL0=0x00;
TH0=0x00;
TF0=0;
TR0=1;
}
}
/****************************周期显示****************/
void Display_F()
{
DisplaySmg(0,smgDuan[11]);
Delay1ms();
DisplaySmg(1,smgDuan[12]);
Delay1ms();
DisplaySmg(2,smgDuan[12]);
Delay1ms();
if(Fout<=9999) // 对第四位数码管进行判断,是否显示
{
DisplaySmg(3,smgDuan[12]);
Delay1ms();
}
else
{
DisplaySmg(3,smgDuan[Fout/10000]);
Delay1ms();
}
DisplaySmg(4,smgDuan[(Fout%10000)/1000]);
Delay1ms();
DisplaySmg(5,smgDuan[(Fout%1000)/100]);
Delay1ms();
DisplaySmg(6,smgDuan[(Fout%100)/10]);
Delay1ms();
DisplaySmg(7,smgDuan[Fout%10]);
Delay1ms();
}
/****************************电压显示**********************/
void Display_U()
{
DisplaySmg(0,smgDuan[10]);
Delay1ms();
DisplaySmg(1,smgDuan[12]);
Delay1ms();
DisplaySmg(2,smgDuan[12]);
Delay1ms();
DisplaySmg(3,smgDuan[12]);
Delay1ms();
DisplaySmg(4,smgDuan[12]);
Delay1ms();
DisplaySmg(5,smgDuan1[Vrb2*2/100]);
Delay1ms();
DisplaySmg(6,smgDuan[Vrb2*2%100/10]);
Delay1ms();
DisplaySmg(7,smgDuan[Vrb2*2%10]);
Delay1ms();
}
void Display_U_zero() //电压固定2.00V显示
{
DisplaySmg(0,smgDuan[10]);
Delay1ms();
DisplaySmg(1,smgDuan[12]);
Delay1ms();
DisplaySmg(2,smgDuan[12]);
Delay1ms();
DisplaySmg(3,smgDuan[12]);
Delay1ms();
DisplaySmg(4,smgDuan[12]);
Delay1ms();
DisplaySmg(5,smgDuan1[2]);
Delay1ms();
DisplaySmg(6,smgDuan[0]);
Delay1ms();
DisplaySmg(7,smgDuan[0]);
Delay1ms();
DisplaySmg(7,smgDuan1[12]);
}
void Display_zero() //关闭所有数码管
{
DisplaySmg(0,smgDuan[12]);
Delay1ms();
DisplaySmg(1,smgDuan[12]);
Delay1ms();
DisplaySmg(2,smgDuan[12]);
Delay1ms();
DisplaySmg(3,smgDuan[12]);
Delay1ms();
DisplaySmg(4,smgDuan[12]);
Delay1ms();
DisplaySmg(5,smgDuan[12]);
Delay1ms();
DisplaySmg(6,smgDuan[12]);
Delay1ms();
DisplaySmg(7,smgDuan[12]);
Delay1ms();
}
4.独立按键扫描函数
/*******************************独立按键扫描*************/
void Scan_keys()
{
if(P33==0) //S4
{
Delay1ms();
if(P33==0)
{
if(flag4==0)
{
flag4=1;
}
else if(flag4==1)
{
flag4=0;
}
}
}
if(P32==0) //S5
{
Delay1ms();
if(P32==0)
{
if(flag5==1)
{
flag5=0;
}
else if(flag5==0)
{
flag5=1;
}
}
}
if(P31==0) //S6
{
Delay1ms();
if(P31==0)
{
if(flag6==1)
{
flag6=0;
}
else if(flag6==0)
{
flag6=1;
}
}
}
if(P30==0) //S7
{
Delay1ms();
if(P30==0)
{
if(flag7==1)
{
flag7=0;
}
else if(flag7==0)
{
flag7=1;
}
}
}
}
/****************************判断函数**********************/
void panduan_U() //L3指示灯亮灭
{
if(Vrb2<75)
{
XBYTE[0X8000]=0XFf;
}
else if((Vrb2>=75) &&(Vrb2<125))
{
XBYTE[0X8000]=0XFB;
}
else if((Vrb2>=125) &&(Vrb2<175))
{
XBYTE[0X8000]=0XFf;
}
else if(Vrb2>=175)
{
XBYTE[0X8000]=0XFb;
}
}
void panduan_F() //L4 指示灯亮灭
{
if(Fout<1000)
{
XBYTE[0X8000]=0XF7;
}
else if((Fout>=1000)&&(Fout<5000))
{
XBYTE[0X8000]=0XF7;
}
else if((Fout>=5000)&&(Fout<10000))
{
XBYTE[0X8000]=0XFf;
}
else if(Fout>=10000)
{
XBYTE[0X8000]=0XF7;
}
}
/****************************系统初始化*****************/
void Init_System()
{
XBYTE[0Xa000]= 0X00;
XBYTE[0X8000]= 0XFF;
Timer1Init();
Timer0Init();
}
/*****************************主函数********************/
void main()
{
Init_System();
while(1)
{
Scan_keys();
if(T_flag==1) //频率采集
{
T_flag=0;
Fout=(TH0<<8)+TL0;
TL0=0x00;
TH0=0x00;
TF0=0;
TR0=1;
}
if(flag7==0)
{ if(flag4==0)
{ XBYTE[0X8000]=0XFE;
if(flag5==1)
{
Vrb2=IIC_Read(0x03);
XBYTE[0X8000]=0XEF;
Display_U();
}
if(flag5==0)
{
Vrb2=103; XBYTE[0X8000]=0XFF;
Display_U_zero();
}
if(flag6==0)
{ if(flag5==0)
{panduan_U();}
else if(flag5==1)
{
panduan_U();}
}
else if(flag6==1)
{
XBYTE[0X8000]=0XFF;
}
}
else if(flag4==1) //S4界面切换
{ XBYTE[0X8000]=0XFd;
Display_F();
if(flag6==0)
{
panduan_F();
}
else if(flag6==1)
{
XBYTE[0X8000]=0XFF;
}
}
}
if(flag7==1)
{
Display_zero();
}
}
}
三、比赛经验分享
蓝桥杯作为一个全国性赛事,比赛比较人性化,五个小时的开发时间,作为比赛,一定会有选拔的作用,所以一定要要好好准备。不要抱着投机取巧的心态,今年就是对违纪的处理相当严格,不管是电子类还是软件类,甚至一个赛点的成绩全部取消,可见对比赛的违纪的处罚力度相当的狠。一定要准备客观题,即便程序写的不是很完整,也能有个不错的分数。其次,要多看看官网的模拟题,今年就是因为没看官网那个模拟题,成绩不是很理想,要注重综合性训练,即便你每个模块都很熟练,比如(DS1302 DS18B20 24C02 PCF8591 IIC )单个模块可能你用的得心应手,但当遇到综合性题目时,没有一个整体任务的理解是不行的,只有不断的训练,将历届真题含金量比较高的,跳出重点训练,当你融汇贯通的时候,不管它题目千变万化,依然可以有条不紊的完成对任务的程序的设计。
**========================================================**
到此,第十届省赛试题已经解析完毕,以上代码,仅供参考之用。
2019.4.6 星期六 我们都是追梦人,我们都在努力奔跑。考研加油!