去年的省赛补赛及其离谱,竟然考了从来没考过的超声波……由于考前没有那么自信觉得自己一定能进决赛,所以超声波是一点也没碰呀,开考的时候打开试题,还以为发错题目了……怎么看着那么像决赛的风格呢……
于是在考场写完其他模块之后就开始罚坐,并感叹官方发的板子好好看(起码有跳帽可以制裁Beep哈哈哈,旋钮也比买的板子高级)……没提前看过驱动程序,再聪明也编不出来吧……
不过其实归根到底还是自己准备不充分,毕竟人家也没有明确说明什么知识只在什么阶段考。所以啊,想要当狮子,就要有狮子的自觉,命运的礼物是赠送给有准备的人的。
本文作者在去年的省赛中获得了省二较靠前的名次,应该是差一道客观题的分数进决赛,分享一下考场上自己写的代码,供各位赛友们参考。
#include "reg52.h"
#include "stdio.h"
#include "iic.h"
#include "ul.h"
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sfr AUXR=0x8e;
ulong ulms;
uint uiSeg_Dly;
uchar pucSeg_Buf[10],pucSeg_Code[8],ucSeg_Pos;
uchar ucLed;
uchar ucKey_Old,ucKey_Dly;
uchar ucVol;
uint uiVolH,uiVolL,uiVolH_Real,uiVolL_Real;
uchar ucMode,ucSet;
uchar ucSur,ucSur_Flag,ucSur_Led;
void HC(uchar channel)
{
switch(channel)
{
case 4:P2=(P2&0x1f)|0x80;break;
case 5:P2=(P2&0x1f)|0xa0;break;
case 6:P2=(P2&0x1f)|0xc0;break;
case 7:P2=(P2&0x1f)|0xe0;break;
case 0:P2=(P2&0x1f)|0x00;break;
default:break;
}
}
void Init_Sys()
{
P0=0x00;HC(5);HC(0);
P0=0xff;HC(4);HC(0);
ucMode=0;ucSet=0;uiVolH=459;uiVolL=51,uiVolH_Real=459,uiVolL_Real=51;
}
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1=1;
EA=1;
}
void Led_Disp(uchar ucLed)
{
P0=~ucLed;HC(4);HC(0);
}
void Seg_Tran(uchar *pucSeg_Buf,uchar *pucSeg_Code)
{
uchar i,j=0,temp;
for(i=0;i<8;i++,j++)
{
switch(pucSeg_Buf[j])
{
case '0':temp=0xc0;break;
case '1':temp=0xf9;break;
case '2':temp=0xa4;break;
case '3':temp=0xb0;break;
case '4':temp=0x99;break;
case '5':temp=0x92;break;
case '6':temp=0x82;break;
case '7':temp=0xf8;break;
case '8':temp=0x80;break;
case '9':temp=0x90;break;
case 'U':temp=0xc1;break;
case 'L':temp=0xc3;break;
case 'A':temp=0x88;break;
case 'P':temp=0x8c;break;
default:temp=0xff;
}
if(pucSeg_Buf[j+1]=='.')
{
temp&=0x7f;
j++;
}
pucSeg_Code[i]=temp;
}
}
void Seg_Disp(uchar *pucSeg_Code,uchar ucSeg_Pos)
{
P0=0xff;HC(7);HC(0);
P0=0x01<<ucSeg_Pos;HC(6);HC(0);
P0=pucSeg_Code[ucSeg_Pos];HC(7);HC(0);
}
uchar Key_Read()
{
uchar Key_Val,Key_New;
Key_New=P3&0x0f;
switch(~Key_New)
{
case 0xf8:Key_Val=4;break;
case 0xf4:Key_Val=5;break;
case 0xf2:Key_Val=6;break;
case 0xf1:Key_Val=7;break;
default:Key_Val=0;
}
return Key_Val;
}
void Key_Proc();
void Seg_Proc();
void Led_Proc();
void main()
{
Init_Sys();
Timer1Init();
while(1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}
void Key_Proc()
{
unsigned char ucKey_Val,ucKey_Down;
if(ucKey_Dly)return;
ucKey_Dly=1;
ucKey_Val=Key_Read();
ucKey_Down=ucKey_Val&(ucKey_Val^ucKey_Old);
ucKey_Old=ucKey_Val;
switch(ucKey_Down)
{
case 4:
ucMode++;ucMode%=3;break;
case 5:
if(ucMode==2)
{
ucSet++;ucSet%=2;break; //检查
}
else break;
case 6:
if(ucMode==2)
{
if(ucSet==0)
{
if(uiVolH==510)uiVolH=51;
else uiVolH+=51;
break;
}
if(ucSet==1)
{
if(uiVolL==510)uiVolL=51;
else uiVolL+=51;
break;
}
}
else break;
case 7:
if(ucMode==2)
{
if(ucSet==0)
{
if(uiVolH==51)uiVolH=510;
else uiVolH-=51;
break;
}
if(ucSet==1)
{
if(uiVolL==51)uiVolL=510;
else uiVolL-=51;
break;
}
}
else break;
}
if(ucMode!=2)
{
ucSet=0;
uiVolH_Real=uiVolH;
uiVolL_Real=uiVolL;
}
}
void Seg_Proc()
{
if(uiSeg_Dly)return;
uiSeg_Dly=1;
ucVol=PCF8591_Adc();
ucSur=Wav_Rec();
if(((ucVol*2)>=uiVolL_Real)&&((ucVol*2)<=uiVolH_Real))
{
ucSur_Flag=1;
}
else
{
ucSur_Flag=0;
}
switch(ucMode)
{
case 0:
sprintf(pucSeg_Buf,"U %3.2f",(float)ucVol/51.0);break;
case 1:
if(ucSur_Flag)
{sprintf(pucSeg_Buf,"L %3d",(uint)ucSur);break;}
else
sprintf(pucSeg_Buf,"L AAA");break;
case 2:
sprintf(pucSeg_Buf,"P %2.1f %2.1f",(float)uiVolH/102.0,(float)uiVolL/102.0);break;
}
switch(ucSur_Flag)
{
case 0:PCF8591_Dac(0);break;
case 1:
if((ucSur>=0)&&(ucSur<=20))PCF8591_Dac(51);
if((ucSur>=20)&&(ucSur<=80))PCF8591_Dac(((ucSur-15)*51)/15.0);
if(ucSur>=80)PCF8591_Dac(255);
}
Seg_Tran(pucSeg_Buf,pucSeg_Code);
}
void Led_Proc()
{
switch(ucMode)
{
case 0:
ucLed=0x01;break;
case 1:
ucLed=0x02;break;
case 2:
ucLed=0x04;break;
}
}
void Service() interrupt 3
{
ulms++;
if(++ucKey_Dly==10)ucKey_Dly=0;
if(++uiSeg_Dly==100)uiSeg_Dly=0;
Seg_Disp(pucSeg_Code,ucSeg_Pos);
if(++ucSeg_Pos==8)ucSeg_Pos=0;
if(ucSur_Flag)
{
if(!(ulms%100))
{
ucLed^=0x80;
}
}
else
ucLed&=(~0x80);
Led_Disp(ucLed);
}
#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);
}
//发送应答或非应答信号
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit;
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 PCF8591_Adc()
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
void PCF8591_Dac(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
以上是除了超声波之外的驱动程序。
下面是我考场上凭借看过一眼的印象胡编乱造的超声波驱动……最后怎么试示数都是255,过段时间复习看看到底如何编写。
#include "ul.h"
sbit AUXR=0x8e;
sbit TX=P1^0;
sbit RX=P1^1;
void Timer0Init(void) //12微秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xF4; //设置定时初始值
TH0 = 0xFF; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 0; //定时器0开始计时
}
unsigned char Wav_Rec()
{
unsigned char ucDist,ucNum=10;
TL0=0xF4;
TH0=0xFF;
TR0=1;
while(ucNum--)
{
while(TF0)
{
TX^=1;
TF0=0;
}
TR0=0;
TF0=0;
TH0=0;
TR0=1;
}
while(RX&&(!TF0));
TR0=1;
if(TF0)
{
TF0=0;
ucDist=255;
}
else
ucDist=((TH0<<4)+TL0)*0.017;
return ucDist;
}
其实题目真的不难,但是还是败于自己的疏忽大意。想要进决赛,就要有一颗决赛的心。
诸赛友,舞台广阔,共勉。