? ? 今年十四屆單片機(jī)國賽試題在程序題設(shè)計方面難度有所下降,但選擇題沒有了以往可以在手冊中可以找到的單片機(jī)類選擇題,選擇題難度較高,因此想獲得一個不錯的成績,需要在選擇題方面有所加強(qiáng)
試題展示
設(shè)計說明?
此次國賽采用了溫度傳感器DS18B20模塊,LED模塊,按鍵模塊,Pcf8591DAC模塊,iic,超聲波模塊,外設(shè)模塊不算多,沒有13屆的定時器分配問題,思路很容易理清。
個人覺得難點在于S8.9兩個按鍵的處理,最好是判斷兩個同時按下做一個標(biāo)記在超過兩秒后進(jìn)行初始化功能,因為在松手時不一定能準(zhǔn)確控制在10ms內(nèi)。
矩陣按鍵模塊
#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;
}
數(shù)碼管顯示模塊
#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;
}
DS18B20模塊
unsigned int rd_temperature(void)
{
unsigned char low,high;
init_ds18b20();
Write_DS18B20(0xcc);//跳過rom只有一個溫度傳感器
Write_DS18B20(0x44);//轉(zhuǎn)換溫度
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; //設(shè)置定時器模式
TL0 = 0xF4; //設(shè)置定時初值
TH0 = 0xFF; //設(shè)置定時初值
TF0 = 0; //清除TF0標(biāo)志
TR0 = 0; //定時器0不開始計時
}
unsigned char ultrasonic_rec(void)
{
unsigned char num = 10;//與定時器12mhz形成40hz的超聲波
unsigned char Distance;
TX = 0;
TL0 = 0xF4; //設(shè)置定時初值
TH0 = 0xFF; //設(shè)置定時初值
TR0 = 1;
while(num--)
{
while(!TF0);
TX ^= 1;
TF0 = 0;
}
TR0 = 0;
TL0 = 0; //此時裝0時將定時稱0.017換算距離
TH0 = 0; //設(shè)置定時初值
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; //設(shè)置定時器模式
TL1 = 0x18; //設(shè)置定時初值
TH1 = 0xFC; //設(shè)置定時初值
TF1 = 0; //清除TF1標(biāo)志
TR1 = 1; //定時器1開始計時
ET1 = 1;
}
LED及繼電器模塊
#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;
}
DAC模塊
#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);//發(fā)送寫的內(nèi)容
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;
}
主函數(shù)
#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;
///三大服務(wù)模塊
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;
//數(shù)碼管
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;//調(diào)整后的距離
bit Distance_M__CM_flag = 0;//CM和M標(biāo)志 0為初始CM
unsigned char Inter_Face = 0x11;//界面標(biāo)號 0x11測距界面 0x21參數(shù)界面-距離參數(shù) 0x22參數(shù)界面-溫度參數(shù) 0x31校準(zhǔn)值界面 0x32介質(zhì)傳輸速度界面 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;//距離參數(shù)
unsigned char Temperature_Canshu = 30;//溫度參數(shù)
int Distance_calibration = 0;//校準(zhǔn)值
unsigned int xdata Ultrasonic_medium = 340;//介質(zhì)傳播速度
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內(nèi)
{
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))//長按判斷標(biāo)志是否為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);//將標(biāo)準(zhǔn)環(huán)境下的速度進(jìn)行調(diào)整和校準(zhǔn)
//*****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);//距離參數(shù)界面
break;
case 0x22:
sprintf(seg_string,"P2 %02d",(unsigned int)Temperature_Canshu);//溫度參數(shù)界面
break;
case 0x31:
sprintf(seg_string,"F1 %3d",Distance_calibration);//距離校準(zhǔn)界面
break;
case 0x32:
sprintf(seg_string,"F2 %4d",Ultrasonic_medium);//介質(zhì)速度界面
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文章來源:http://www.zghlxwxcb.cn/news/detail-537548.html
免責(zé)聲明:函數(shù)模塊采用螞蟻工程科技子函數(shù)模塊,代碼僅供學(xué)習(xí)未商用,如有侵權(quán)請聯(lián)系。文章來源地址http://www.zghlxwxcb.cn/news/detail-537548.html
到了這里,關(guān)于藍(lán)橋杯十四屆單片機(jī)國賽試題及代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!