赞
踩
今年十四届单片机国赛试题在程序题设计方面难度有所下降,但选择题没有了以往可以在手册中可以找到的单片机类选择题,选择题难度较高,因此想获得一个不错的成绩,需要在选择题方面有所加强
此次国赛采用了温度传感器DS18B20模块,LED模块,按键模块,Pcf8591DAC模块,iic,超声波模块,外设模块不算多,没有13届的定时器分配问题,思路很容易理清。
个人觉得难点在于S8.9两个按键的处理,最好是判断两个同时按下做一个标记在超过两秒后进行初始化功能,因为在松手时不一定能准确控制在10ms内。
- #include "bsp_key.h"
-
-
-
- unsigned char Key_Read(void)
- {
- unsigned int Key_New;
- unsigned char Key_Value;
-
- P44 = 0;P42 = 1;P35 = 1;P34 = 1;
- Key_New = P3&0X0F;
-
- P44 = 1;P42 = 0;P35 = 1;P34 = 1;
- Key_New = (Key_New<<4)|(P3&0X0F);
-
- P44 = 1;P42 = 1;P35 = 0;P34 = 1;
- Key_New = (Key_New<<4)|(P3&0X0F);
-
- P44 = 1;P42 = 1;P35 = 1;P34 = 0;
- Key_New = (Key_New<<4)|(P3&0X0F);
-
- switch(~Key_New)
- {
- case 0x8000:Key_Value = 4;break;
- case 0x4000:Key_Value = 5;break;
- case 0x2000:Key_Value = 6;break;
- case 0x1000:Key_Value = 7;break;
-
- case 0x0800:Key_Value = 8;break;
- case 0x0400:Key_Value = 9;break;
- case 0x0200:Key_Value = 10;break;
- case 0x0100:Key_Value = 11;break;
-
- case 0x0080:Key_Value = 12;break;
- case 0x0040:Key_Value = 13;break;
- case 0x0020:Key_Value = 14;break;
- case 0x0010:Key_Value = 15;break;
-
- case 0x0008:Key_Value = 16;break;
- case 0x0004:Key_Value = 17;break;
- case 0x0002:Key_Value = 18;break;
- case 0x0001:Key_Value = 19;break;
-
- case 0x0c00:Key_Value = 89;break;
- default :Key_Value = 0;
- }
- return Key_Value;
- }

- #include "bsp_seg.h"
- void Seg_Tran(unsigned char *seg_string,unsigned char *seg_buf)
- {
- unsigned char i = 0;
- unsigned char j = 0;
- unsigned char temp;
- for(i = 0;i<= 7;i++,j++)
- {
- switch(seg_string[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 'A':temp = 0x88;break;
- case 'B':temp = 0x83;break;
- case 'C':temp = 0xc6;break;
- case 'D':temp = 0xa1;break;
- case 'E':temp = 0x86;break;
- case 'F':temp = 0x8e;break;
- case ' ':temp = 0xff;break;
- case '-':temp = 0xbf;break;
-
- case 'H':temp = 0x89;break;
- case 'L':temp = 0xc7;break;
- case 'N':temp = 0xc8;break;
- case 'P':temp = 0x8c;break;
- case 'U':temp = 0xc1;break;
-
- default:temp = 0xff;break;
- }
- if(seg_string[j+1] == '.')
- {
- temp &= 0x7f;
- j++;
- }
- seg_buf[i] = temp;
- }
- }
-
- void Seg_Disp(unsigned char *seg_buf,unsigned char pos)
- {
- P0 = 0XFF;
- P2 = P2 & 0X1F |0XE0;
- P2 &= 0X1F;
-
- P0 = 1<<pos;
- P2 = P2 & 0X1F |0Xc0;
- P2 &= 0X1F;
-
- P0 = seg_buf[pos];
- P2 = P2 & 0X1F |0XE0;
- P2 &= 0X1F;
- }

- unsigned int rd_temperature(void)
- {
- unsigned char low,high;
-
- init_ds18b20();
- Write_DS18B20(0xcc);//跳过rom只有一个温度传感器
- Write_DS18B20(0x44);//转换温度
-
- init_ds18b20();
- Write_DS18B20(0xcc);
- Write_DS18B20(0xbe); //将温度依次返回
-
- low = Read_DS18B20();//先读低温度
- high = Read_DS18B20();//先读低温度
-
- return((high<<8)|low);
- }

- #include "bsp_ultrasonic.h"
-
- sbit TX = P1^0;
- sbit RX = P1^1;
-
- void ultrasonic_Timer0init(void)
- {
- AUXR &= 0x7F; //定时器时钟12T模式
- TMOD &= 0xF0; //设置定时器模式
- TL0 = 0xF4; //设置定时初值
- TH0 = 0xFF; //设置定时初值
- TF0 = 0; //清除TF0标志
- TR0 = 0; //定时器0不开始计时
- }
-
-
- unsigned char ultrasonic_rec(void)
- {
- unsigned char num = 10;//与定时器12mhz形成40hz的超声波
- unsigned char Distance;
-
- TX = 0;
- TL0 = 0xF4; //设置定时初值
- TH0 = 0xFF; //设置定时初值
-
- TR0 = 1;
- while(num--)
- {
- while(!TF0);
- TX ^= 1;
- TF0 = 0;
- }
-
- TR0 = 0;
- TL0 = 0; //此时装0时将定时称0.017换算距离
- TH0 = 0; //设置定时初值
- TR0 = 1;
-
- while(RX && (~TF0));//RX平时为1变0是接收到40hz脉冲
- TR0 = 0;
- if(TF0 == 1)//距离溢出
- {
- Distance = 255;
- TF0 = 0;
- }
- else
- {
- Distance = (((TH0<<8)|TL0)*0.017);
- TF0 = 0;
- }
- return Distance;
- }
-

- #include "Timer.h"
-
- void Timer1Init(void) //1毫秒@12.000MHz
- {
- AUXR &= 0xBF; //定时器时钟12T模式
- TMOD &= 0x0F; //设置定时器模式
- TL1 = 0x18; //设置定时初值
- TH1 = 0xFC; //设置定时初值
- TF1 = 0; //清除TF1标志
- TR1 = 1; //定时器1开始计时
-
- ET1 = 1;
- }
- #include "bsp_led.h"
-
- void Led_Disp(unsigned char ucLed)
- {
- P0 = (~ucLed);
- P2 = P2 & 0X1F |0X80;
- P2 &= 0X1F;
- }
-
-
-
- void Relay(unsigned char relay)
- {
- P0 = relay;
- P2 = P2 & 0X1F |0Xa0;
- P2 &= 0X1F;
- }

- #include "bsp_iic.h"
-
- #define DELAY_TIME 5
- 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;
- 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;
- }
-
- //
- 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;
- }
-
-
-
- void Pcf8591_DAC(float Dac_data)
- {
- IIC_Start();
- IIC_SendByte(0x90);//选择选择pcf8591写东西模式
- IIC_WaitAck();
-
- IIC_SendByte(0x41);//选择写0x41通道
- IIC_WaitAck();
-
- IIC_SendByte(Dac_data);//发送写的内容
- IIC_WaitAck();
- IIC_Stop();//停止对iic的控制
- }

- #include "bsp_init.h"
-
-
-
- void Clc_Peripheral(void)
- {
- P0 = 0XFF;
- P2 = P2 & 0X1F |0X80;
- P2 &= 0X1F;
-
- P0 = 0X00;
- P2 = P2 & 0X1F |0XA0;
- P2 &= 0X1F;
- }
- #include "STC15F2K60S2.H"
- #include "bsp_init.h"
- #include "Timer.h"
- #include "bsp_led.h"
- #include "bsp_key.h"
- #include "bsp_seg.h"
- #include "stdio.h"
- #include "bsp_onewire.h"
- #include "bsp_iic.h"
- #include "bsp_ultrasonic.h"
-
- //程序减速
- unsigned int Seg_Slow_Down = 0;
- unsigned int Key_Slow_Down = 0;
- unsigned int Led_Slow_Down = 0;
-
- ///三大服务模块
- void Key_Proc(void);
- void Seg_Proc(void);
- void Led_Proc(void);
-
- void Delay500ms() //@12.000MHz
- {
- unsigned char i, j, k;
-
- _nop_();
- _nop_();
- i = 23;
- j = 205;
- k = 120;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
-
-
-
- //按键
- unsigned char Key_Value,Key_Down,Key_Old,Key_Up;
-
- //数码管
- unsigned char seg_string[10];
- unsigned char seg_buf[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
- unsigned char pos;
-
- //LED
- unsigned char ucLed;
-
- //其他变量
- float Temperature;//测得的距离
- float Distance;//测得的距离
- float Distance_Disp;//调整后的距离
- bit Distance_M__CM_flag = 0;//CM和M标志 0为初始CM
-
- unsigned char Inter_Face = 0x11;//界面标号 0x11测距界面 0x21参数界面-距离参数 0x22参数界面-温度参数 0x31校准值界面 0x32介质传输速度界面 0x33DAC下限界面
- unsigned long ms_Tick = 0;
- unsigned long Key_ms_Tick = 0;
- unsigned long xdata Data_record_ms_Tick = 0;
- unsigned char Distance_DAC;
- unsigned char Distance_Canshu = 40;//距离参数
- unsigned char Temperature_Canshu = 30;//温度参数
- int Distance_calibration = 0;//校准值
- unsigned int xdata Ultrasonic_medium = 340;//介质传播速度
- float DAC_Low_Vlaue = 1.0;//DAC下限
- bit Key_89_2s_flag = 0;
- bit Data_record = 0;
- bit DAC_flag = 0;
- float DAC_Data;
- void main(void)
- {
- Clc_Peripheral();
- Timer1Init();
- rd_temperature();
- Delay500ms();
- EA = 1;
-
- ultrasonic_Timer0init();
-
- while(1)
- {
- Key_Proc();
- Seg_Proc();
- Led_Proc();
-
- }
- }
- void tm1_isr() interrupt 3
- {
- ms_Tick++;
- if(++Key_Slow_Down == 10)Key_Slow_Down = 0;
- if(++Seg_Slow_Down == 70)Seg_Slow_Down = 0;
- if(++Led_Slow_Down == 100)Led_Slow_Down = 0;
-
- else if(((Inter_Face >> 4) == 0x03)&&(ms_Tick % 100) == 0)
- {
- ucLed &= 0x7f;
- ucLed ^= 0x01;
- }
-
- Led_Disp(ucLed);
- Seg_Disp(seg_buf,pos);
- if(++pos == 8)pos = 0;
- }
- void Key_Proc(void)
- {
- if(Key_Slow_Down) return;
- Key_Slow_Down = 1;
-
-
- Key_Value = Key_Read();
- Key_Down = Key_Value & (Key_Old ^ Key_Value);//按键按下
- Key_Up = ~Key_Value & (Key_Old ^ Key_Value);//按键弹起
- Key_Old = Key_Value;
-
- if(Key_Down)
- {
- if(Key_Down == 89)Key_89_2s_flag = 1;
- Key_ms_Tick = ms_Tick;
- }
- if(((ms_Tick - Key_ms_Tick) <= 2000)&&(Data_record == 0))//短按 按下2s内
- {
- switch(Key_Up)
- {
- case 4:
- if((Inter_Face >> 4) == 0x01) Inter_Face = 0x21;
- else if((Inter_Face >> 4) == 0x02) Inter_Face = 0x31;
- else if((Inter_Face >> 4) == 0x03) Inter_Face = 0x11;
- break;
- case 5:
- if(Inter_Face == 0x11)Distance_M__CM_flag ^= 1;
- else if(Inter_Face == 0x21)Inter_Face = 0x22;
- else if(Inter_Face == 0x22)Inter_Face = 0x21;
- else if(Inter_Face == 0x31)Inter_Face = 0x32;
- else if(Inter_Face == 0x32)Inter_Face = 0x33;
- else if(Inter_Face == 0x33)Inter_Face = 0x31;
- break;
- case 8://按键++判断 以及记录功能
- if(Inter_Face == 0x11)
- {
- Data_record = 1;
- Data_record_ms_Tick = ms_Tick;
- }
- else if(Inter_Face == 0x21)
- {
- Distance_Canshu += 10;
- if(Distance_Canshu == 100)Distance_Canshu = 90;
- }
- else if(Inter_Face == 0x22)
- {
- Temperature_Canshu += 1;
- if(Temperature_Canshu == 81)Temperature_Canshu = 80;
- }
- else if(Inter_Face == 0x31)
- {
- Distance_calibration += 5;
- if(Distance_calibration == 95)Distance_calibration = 90;
- }
- else if(Inter_Face == 0x32)
- {
- Ultrasonic_medium += 10;
- if(Ultrasonic_medium == 10000)Ultrasonic_medium = 9990;
- }
- else if(Inter_Face == 0x33)
- {
- DAC_Low_Vlaue += 0.1;
- if(DAC_Low_Vlaue >= 2.0)DAC_Low_Vlaue = 2.0;
- }
- break;
- case 9://按键--判断 以及DAC输出功能
- if(Inter_Face == 0x11)DAC_flag = 1;
- else if(Inter_Face == 0x21)
- {
- Distance_Canshu -= 10;
- if(Distance_Canshu == 0)Distance_Canshu = 10;
- }
- else if(Inter_Face == 0x22)
- {
- Temperature_Canshu -= 1;
- if(Temperature_Canshu == 255)Temperature_Canshu = 0;
- }
- else if(Inter_Face == 0x31)
- {
- Distance_calibration -= 5;
- if(Distance_calibration == -95)Distance_calibration = -90;
- }
- else if(Inter_Face == 0x32)
- {
- Ultrasonic_medium -= 10;
- if(Ultrasonic_medium == 0)Ultrasonic_medium = 10;
- }
- else if(Inter_Face == 0x33)
- {
- DAC_Low_Vlaue -= 0.1;
- if(DAC_Low_Vlaue <= 0.1)DAC_Low_Vlaue = 0.1;
- }
- break;
- }
- }
- else if(((ms_Tick - Key_ms_Tick) > 2000)&&(Key_89_2s_flag == 1))//长按判断标志是否为1
- {
- ucLed ^=0xff;
- Key_89_2s_flag = 0;
- Distance_M__CM_flag = 0;
- Distance_Canshu = 40;
- Temperature_Canshu = 30;
- Distance_calibration = 0;
- Ultrasonic_medium = 340;
- DAC_Low_Vlaue = 1.0;
- }
- if((Data_record == 1)&&((ms_Tick - Data_record_ms_Tick) < 6000))
- {
- if((ms_Tick%1000) == 0)Distance_DAC = ultrasonic_rec();
- }
- else if((Data_record == 1)&&((ms_Tick - Data_record_ms_Tick) > 6000))Data_record = 0;
-
- }
-
- void Seg_Proc(void)
- {
- if(Seg_Slow_Down) return;
- Seg_Slow_Down = 1;
-
- Temperature = (rd_temperature()/16.0);
- Distance = ultrasonic_rec();
- Distance_Disp = ((Ultrasonic_medium/340.0)*Distance+Distance_calibration);//将标准环境下的速度进行调整和校准
-
- //*****DAC输出*****
- if(Distance_Disp >= 90)DAC_Data = 255;
- else if(Distance_Disp <= 10)DAC_Data = 51;
- else if((Distance_Disp > 10)&&(Distance_Disp < 90))DAC_Data = 51*(((5-DAC_Low_Vlaue)/80.0)*Distance_Disp+(DAC_Low_Vlaue - ((5-DAC_Low_Vlaue)/8.0)));
-
- if(DAC_flag == 1)Pcf8591_DAC(DAC_Data);
- //****************
- switch(Inter_Face)
- {
- case 0x11:
- if(Distance_M__CM_flag == 0)sprintf(seg_string,"%03.1f-%4d",Temperature,(unsigned int)Distance_Disp); //cm
- else if(Distance_M__CM_flag == 1)sprintf(seg_string,"%03.1f-%4.2f",Temperature,(Distance_Disp/100.0)); //m
- break;
- case 0x21:
- sprintf(seg_string,"P1 %02d",(unsigned int)Distance_Canshu);//距离参数界面
- break;
- case 0x22:
- sprintf(seg_string,"P2 %02d",(unsigned int)Temperature_Canshu);//温度参数界面
- break;
- case 0x31:
- sprintf(seg_string,"F1 %3d",Distance_calibration);//距离校准界面
- break;
- case 0x32:
- sprintf(seg_string,"F2 %4d",Ultrasonic_medium);//介质速度界面
- break;
- case 0x33:
- sprintf(seg_string,"F2 %2.1f",DAC_Low_Vlaue);//dac下限界面
- break;
-
- }
-
- Seg_Tran(seg_string,seg_buf);
- }
-
- void Led_Proc(void)//Led 和继电器
- {
- if(Led_Slow_Down) return;
- Led_Slow_Down = 1;
- if(Inter_Face == 0x11)
- {
- if(Distance_Disp > 255)ucLed = 0xff;
- else if(Distance_Disp < 255)
- {
- ucLed = Distance_Disp;
- }
- }
- else if((Inter_Face >> 4) == 0x02)//L8
- {
- ucLed &= 0x0;
- ucLed |= 0x80;
- }
- //继电器
- if((Distance_Disp < (Distance_Canshu+5))&&(Distance_Disp > (Distance_Canshu -5))&&(Temperature <= Temperature_Canshu))Relay(0x10);//L10
- else Relay(0x0);
-
- }
-
-

B站视频连接: https://b23.tv/ixYMJaB
免责声明:函数模块采用蚂蚁工程科技子函数模块,代码仅供学习未商用,如有侵权请联系。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。