提示:一个第十三届蓝桥杯单片机 考生的考后总结
一、第十三届考的是什么?
1.电位器RB2的电压测量,用DAC输出
2.超声波测距
3.数码管
4.LED灯
5.定时器
二、数据代码
1,代码 MAIN
#include "stc15.h" #include "iic.h" #define uchar unsigned char #define uint unsigned int uchar code SMG_Duanma[22]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0xc1,0xc3,0x8c }; //ULP uchar Speed=340; sbit S4 = P3^3; sbit S5 = P3^2; sbit S6 = P3^1; sbit S7 = P3^0; sbit L1 = P0^0; sbit L2 = P0^1; sbit L3 = P0^2; sbit L8 = P0^7; sbit TX = P1^0; sbit RX = P1^1; uchar smg_flag=0; //数码管显示内容标志量 uchar model_flag=0; //参数上下限标志量 uint rb2=0; //显示电压值 uchar Dis_flag=0; //距离模式转换量 uint distance=0; //距离显示值 uint count_t=0; //计数值 uint dat=0; uchar count_d=0,count_led=0; //计算距离所用时间,灯亮的持续时间 bit LED_flag=0; //灯亮标志位 uint DAC=0; //DAC输出值 uchar Umax = 45; uchar Umin = 5; void Scankey(); void Display(); void Read_RB2(); void InitHC138(uchar n); void Timer0Init(void); void LED_function(); void PAN_duan(); void Jud_CONTI(); void Measure_DIS(); void main() { InitHC138(4); P0 = 0xff; Timer0Init(); LED_function(); while(1) { Jud_CONTI(); PAN_duan(); Read_RB2(); Display(); Scankey(); Measure_DIS(); } } void InitHC138(uchar n) { switch(n) { 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; } } void Delay100us(uint t) //@11.0592MHz { unsigned char i, j; uint n; for(n=0;n<t;n++) { _nop_(); _nop_(); i = 2; j = 15; do { while (--j); } while (--i); } } void SMG_BIT(uchar pos,dat) { InitHC138(6); P0 = 0x00; P0 = 0x01 << pos; InitHC138(7); P0 = 0xff; P0 = SMG_Duanma[dat]; Delay100us(25); P0 = 0xff; } void Display() { if(smg_flag==0) //电压显示 { InitHC138(4); L1 = 0; L2 = 1; L3 = 1; SMG_BIT(0,18); InitHC138(6); P0 = 0x00; P0 = 0x01 << 5; InitHC138(7); P0 = 0xff; P0 = SMG_Duanma[rb2/100%10]&(~0x80); Delay100us(25); P0 = 0xff; SMG_BIT(6,rb2/10%10); SMG_BIT(7,rb2%10); } else if(smg_flag==1) //距离显示 { InitHC138(4); L1 = 1; L2 = 0; L3 = 1; if(Dis_flag==0) //连续测量标志位 { SMG_BIT(0,19); if((distance /100) == 0) //判断距离长度 { SMG_BIT(6,distance/10); SMG_BIT(7,distance%10); } else { SMG_BIT(6,distance/100); SMG_BIT(6,distance/10%10); SMG_BIT(7,distance%10); } } else { SMG_BIT(0,19); SMG_BIT(5,10); SMG_BIT(6,10); SMG_BIT(7,10); } } else //参数显示 { InitHC138(4); L1 = 1; L2 = 1; L3 = 0; if(model_flag==0) { SMG_BIT(0,20); InitHC138(6); P0 = 0x00; P0 = 0x01 << 3; InitHC138(7); P0 = 0xff; P0 = SMG_Duanma[Umax/10%10]&(~0x80); Delay100us(25); P0 = 0xff; SMG_BIT(4,Umax%10); P0 = 0xff; } else { SMG_BIT(0,20); InitHC138(6); P0 = 0x00; P0 = 0x01 << 6; InitHC138(7); P0 = 0xff; P0 = SMG_Duanma[Umin/10%10]&(~0x80); Delay100us(25); P0 = 0xff; SMG_BIT(7,Umin%10); P0 = 0xff; } } } void Timer0Init(void) //50毫秒@11.0592MHz { TMOD = 0x01; //设置定时器模式 TL0 = (65535-50000)%256; //设置定时初值 TH0 = (65535-50000)/256; //设置定时初值 TR0 = 1; //定时器0开始计时 EA = 1; ET0 = 1; } void Service() interrupt 1 { count_led++; if(count_led==2) { LED_flag=~LED_flag; //L8 闪烁控制位 count_led=0; } } uchar Read_PCF8591() { uchar 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(); IIC_Start(); IIC_SendByte(0x43); IIC_WaitAck(); IIC_SendByte(temp); //表示选择DAC输出 IIC_WaitAck(); IIC_SendAck(1); IIC_Stop(); return temp; } float smg_adc=0; //换算电压值 uchar temp=0; //获取电压值 void Read_RB2() { temp = Read_PCF8591(); smg_adc = temp * 5.0/255; rb2 = smg_adc*100; } void DelayK(uint t) { while(t--) { Display(); } } void Scankey() { if(S4 == 0) { DelayK(15); if(S4 == 0) { smg_flag++; if(smg_flag==3) { smg_flag=0; } while(S4 == 0) { Display(); } } } if(S5 == 0) { DelayK(15); if(S5 == 0) { model_flag++; if(model_flag==2) { model_flag=0; } while(S5 == 0) { Display(); } } } if(S6 == 0) //?问题 { DelayK(15); if(S6 == 0) { if(smg_flag==2) { if(model_flag==0) { Umax = Umax+5; if(Umax >= 55) { Umax=5; } } else { Umin = Umin+5; if(Umin >= 55) { Umin=5; } } } while(S6 == 0) { Display(); } } } if(S7 == 0) //? { DelayK(15); if(S7 == 0) { if(smg_flag==2) { if(model_flag==0) { Umax = Umax-5; if(Umax <= 0) { Umax = 50; } } else { Umin = Umin-5; if(Umin <= 0) { Umin = 50; } } } while(S7 == 0) { Display(); } } } } void LED_function() { if(LED_flag==1) { InitHC138(4); L8 = 0; } else { InitHC138(4); L8 = 1; } } void Jud_CONTI() { if((rb2 > Umin)&&(rb2 < Umax)) { Dis_flag=0; } else { Dis_flag=1; } } void PAN_duan() { if(Dis_flag==0) //超声波启动位 { LED_flag=1; //启动L8 if(distance <= 20) { DAC = 200; } else if(distance >= 40) { DAC = 400; } else { DAC = 6.7*distance-30; } rb2 = DAC; //DAC输出显示 } else { DAC = 0; rb2 = DAC; } } void Send_Wave() //产生8个40khz超声波 { uchar i; for(i=0;i<8;i++) { TX = 1; Delay100us(1); TX = 0; Delay100us(1); } } void Measure_DIS() { uint time = 0; TMOD &= 0x0f; //定时器1模式 13位 TL1 = 0x00; TH1 = 0X00; Send_Wave(); //发送超声波信号 TR1 = 1; //开启 while((RX == 1)&&(TF1 = 0));//等待超声波信号返回或者等到测量超出范围 TR1 = 0; if(Dis_flag==0) { if(TF1 == 0) { time=TF1; time = (time << 8) | TL1; distance = ((time / 10)*17)/100+3; } else { TF1 = 0; distance = 999; } } else { TR1 = 0; } }
2.底层驱动代码
IIC.C:
#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; }
考完总结
去年报名了蓝桥杯第十三届比赛,原定于趁寒假这个时间段学完关于这个比赛的所有内容,当时我每天的主要任务就是学习C语言,看书(不是关于单片机的书)。在假期剩余十多天的时候,买的单片机板子到了,我在第一次开到单片机的小灯时开心的笑了,然后,我开始了“玩”单片机的时期,一直到开始考试前,我对于单片机的学习都是很看重的,可是这次的考试,我的发挥并不如意,我只看过一眼的超声波考到了,我在看到试题的时候,就觉得这次就连省三都保不住了,我刚开始的想法是尽量取得省一,还能用公费去北京考试,那可是与我每次上学或者回家的途中可不一样的体验,好吧,下次接着努力吧。
总结
在看了超声波的代码后,感觉到了超声波原理不难,基本代码也不是很难,可是我在准备的时候却没有想着要去准备一下他,想到前两个晚上都在搞温度如何换算才能显示更好的代码,我想对我说,你的学习方法以及思考方式有很大的问题,反正已经考完了,结果不是那么重要了。
现在来说一下我在这次的单片机的学习中的学习方式吧:和之前学习任何一门学科的学习方式没有什么区别,报名了这个比赛,那就学吧,学不懂也得学,我每天都会话大约三个小时时间去学习单片机的原理以及如何敲代码,还有搞清代码的意思,刚开始的学习是跟着小蜜蜂老师,在B站看他的单片机教程,小蜜蜂老师真的是一个非常优秀的老师,我强烈推荐想学习单片机比赛的人跟着小蜜蜂老师学习,不仅内容全,还会有意想不到的惊喜。刚开始真的就是看,看完之后敲代码,看到自己的代码和老师的一样了,一字不差了,就行了,然后我开始学习下一节,直到我看完所有的视频,敲完所有的代码,我开始自己写代码的时候,我发现我根本不会写,然后我将之前写的代码烧录到单片机运行的时候,才发现即使当时我跟老师的代码“一样”,可是我在单片机上呈现的内容完全不一样,甚至刚开始的流水灯,我连流水灯都无法点亮。我产生了或许是老师的代码有一些问题,我就去官网找那些测试代码,在成功显示后,我试图去理解代码的意思,我在延时函数那里卡住了,后来才发现那个直接可以再STC里面复制粘贴(我真的服了我的学习效率,强烈建议大家在学习单片机的时候,边实践边敲代码,不然最后可能只是浪费时间)。我又开始了新一轮的跟着小蜜蜂老师的学习,一般学习敲代码,然后在单片机上呈现出来,听老师讲解代码的意思是什么,并通过修改代码,查看单片机的反应,知道它是什么原理。慢慢的,我发现的单片机也没有那么难,流水灯和数码管的显示不再话下了,我可以真的懂得函数之间的联系是什么,我又想到过单片机比赛会考到超声波,但是我还是没有想去掌握这个内容,相对是等我拿到省一在学习吧。没想到真是因为这个,我才痛失了省一(或许)。打无准备之战,是我的“特色”,也许我要努力改变我的学习方法还有思维习惯,我相信我可以的,加油。