第七届蓝桥杯单片机省赛题目解析
今天給大家帶來第七屆(2016)省賽題目的解析,題目總體不算難,我們一起來看看吧。
?題目
?這次省賽題整體還是不難的,做起來除了PWM不是很好理解以外,其他的還是很好理解的,最重要的是編程的邏輯。題目考察了LED顯示、按鍵、數碼管顯示(這三個模塊是每套題目都會考的,我們應該要很熟悉了)、PWM、DS18B20。
1 數碼管顯示
數碼管有兩種模式,一種是工作模式,一種是室溫模式。我們可以寫兩個界面函數,一個用來顯示工作模式,另一個顯示室溫模式,通過按鍵來選擇顯示哪種模式。
2 LED顯示
定義一個變量mode,通過按鍵來控制mode的值讓它在1-3之間循環。mode為1時L1亮,mode為2時L2亮,mode為3時L3亮。
3 按鍵模塊
題目是用了s4,s5,s6,s7四個按鍵,是獨立鍵盤。s4用來控制mode的值。s5用來控制倒計時,也定義一個countdown_mode變量在1-3之間循環,countdown_mode為1時倒計時為0,countdown_mode為2時倒計時為60,countdown_mode為3時倒計時為120。s6就是把countdown_mode設置為1。s7有兩個狀態,定義一個temp_m變量來控制,為1時顯示室溫模式,為0時顯示工作模式。
4 pwm
由于pwm的信號頻率為1KHz,就是1ms。P34引腳有連接定時器0,我們用1ms的定時器0來控制pwm的占空比,比如當pwm的占空比為20%時,就可以用定時器0控制讓L1亮0.2ms,滅0.8ms來顯示pwm的占空比。具體看代碼。
5 DS18B20
就是改寫底層驅動代碼部分(onewire),然后放在定時器里,每隔一段時間去測量一次。
onewire.c
#include"onewire.h"#define u8 unsigned char #define u16 unsigned int bit initflag; sbit DQ=P1^4;void Delay1us() {_nop_();_nop_();_nop_(); }void delay_us(unsigned int us) {while(us--){Delay1us();} }bit init_ds18b20() {DQ=0;delay_us(500);DQ=1;delay_us(20);initflag=DQ;delay_us(50);return initflag; }unsigned int get_temp() {unsigned char low,high;unsigned int result;float i;init_ds18b20();//3?ê??ˉds18b20_wirteByte(0xcc);ds18b20_wirteByte(0x44);init_ds18b20();ds18b20_wirteByte(0xcc);ds18b20_wirteByte(0xbe);low=ds18b20_readByte();high=ds18b20_readByte();result=high&0x0f;result<<=8;result=result|low;i=result*0.0625;result=i*100;return result;}void ds18b20_wirteByte(unsigned char dat) {unsigned char i=0;for(i;i<8;i++){DQ=0;DQ=dat&0x01;delay_us(65);DQ=1;dat=dat>>1;} }u8 ds18b20_readByte() {unsigned char i=0;unsigned char dat;for (i;i<8;i++){DQ=0;dat=dat>>1;DQ=1;if(DQ){dat|=0x80; }delay_us(15);}return dat; }onewire.h
#ifndef _ONEWIRE_H_ #define _ONEWIRE_H_#define u8 unsigned char #define u16 unsigned int #include<STC15F2K60S2.h> #include"intrins.h"void Delay1us(); void delay_us(u16 us); bit init_ds18b20(); u16 get_temp(); void ds18b20_wirteByte(u8 dat); u8 ds18b20_readByte();#endifINIT.c
個人喜歡把初始化、定時器、數碼管顯示、鍵盤放在一個模塊里。
#include"INIT.h"#define u8 unsigned char #define u16 unsigned int #define state P3 #define state_0 0 #define state_1 1 #define state_2 2u8 tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6}; u8 seg[]={11,11,11,11,11,11,11,11};static u8 key_state=0; static u8 segadder=0;u8 row=0,key_press=0,key_num=0;void all_init() //關閉無關的外設 {P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;P2=(P2&0x1f)|0xa0;P04=0;P06=0;P2&=0x1f;P2=(P2&0x1f)|0xc0;P0=0x00;P2&=0x1f;P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f; }void display() //數碼管顯示函數 {P2=(P2&0x1f)|0xe0; //消隱P0=0xff;P2&=0x1f;P2=(P2&0x1f)|0xc0; //位選P0=1<<segadder;P2&=0x1f;P2=(P2&0x1f)|0xe0; //段選P0=tab[seg[segadder]];P2&=0x1f;if(++segadder==8)segadder=0; }u8 read_key() //獨立鍵盤 {switch(key_state){case state_0:state=0x0f;key_press=state;if(key_press!=0x0f)key_state=state_1;break;case state_1:key_press=state; if(key_press!=0x0f){if((key_press & 0x08)==0) row=4;if((key_press & 0x04)==0) row=5;if((key_press & 0x02)==0) row=6;if((key_press & 0x01)==0) row=7;key_state=state_2;}elsekey_state=state_0;break;case state_2:state=0x0f;key_press=state;if(key_press==0x0f)key_state=state_0; break; }key_num=row;row=0;return key_num; }void Timer0Init(void) //100us {AUXR |= 0x80; TMOD &= 0xF0; TL0 = 0xAE; TH0 = 0xFB; TF0 = 0; TR0 = 1; EA = 1; }void Timer1Init(void) //1ms {AUXR |= 0x40; TMOD &= 0x0F; TL1 = 0xCD; TH1 = 0xD4; TF1 = 0; TR1 = 1; ET1 = 1;EA = 1; }INIT.h
#ifndef _INIT_H_ #define _INIT_H_#define u8 unsigned char #define u16 unsigned int #include<STC15F2K60S2.h> #include"intrins.h"void all_init(); void display(); u8 read_key(); void Timer0Init(void); void Timer1Init(void);#endifjm.c
這個模塊是每個按鍵所控制的功能。
#include"jm.h" #include"onewire.h"#define u8 unsigned char #define u16 unsigned intextern u8 seg[],countdown,moude,temp_flag; // extern表示此變量是在別處定義的,要在此處引用u16 temp;void jm4() //s4所控制的功能 {seg[0]=10;seg[1]=moude;seg[2]=10;seg[3]=11; }void jm5() //s5所控制的功能 {seg[4]=countdown/1000;seg[5]=countdown/100%10;seg[6]=countdown/10%10;seg[7]=countdown%10; }void jm6() //s6所控制的功能 {seg[4]=countdown/1000;seg[5]=countdown/100%10;seg[6]=countdown/10%10;seg[7]=countdown%10; }void jm7() //s7所控制的功能 {if(temp_flag==1){temp_flag=0;temp=get_temp();}seg[0]=10;seg[1]=4;seg[2]=10;seg[3]=11;seg[4]=11;seg[5]=temp/1000;seg[6]=temp/100%10;seg[7]=12; }jm.h
#ifndef _JM_H_ #define _JM_H_#define u8 unsigned char #define u16 unsigned int #include<STC15F2K60S2.h> #include"intrins.h"void jm4(); void jm5(); void jm6(); void jm7();#endifmain.c
#include"INIT.h" #include"jm.h" #include"onewire.h"#define u8 unsigned char #define u16 unsigned intstatic u16 moude_count=0,pwm; u8 num=0,moude=1,countdown=0,temp_m=0,countdown_moude=1; u8 temp_flag=0; u8 jma,jmb; u16 countdown_count=0,temp_count=0;extern seg[];void main() {all_init();Timer0Init();Timer1Init();while(1){if(countdown>0) ET0 = 1; //倒計時大于0打開定時器0 else ET0 = 0; num=read_key();switch(num){case 4:if(++moude==4) moude=1; //三種工作模式if(moude==1) pwm=2;if(moude==2) pwm=3;if(moude==3) pwm=7;jma=0,jmb=0;break;case 5:if(++countdown_moude==4) countdown_moude=1; //設定倒計時if(countdown_moude==1) countdown=0;if(countdown_moude==2) countdown=60;if(countdown_moude==3) countdown=120;jma=0,jmb=1;break;case 6: //停止,清零countdown=0;jma=1,jmb=0;break;case 7: //工作或室溫界面temp_m^=1;if(temp_m==1){jma=1,jmb=1;}else{jma=0,jmb=0;}break;}num=0;if(jma==0&&jmb==0) {jm4();jm5();}if(jma==0&&jmb==1) jm5(); if(jma==1&&jmb==0) jm6();if(jma==1&&jmb==1) jm7();} }void Timer1() interrupt 3 {display();countdown_count++;temp_count++;if(countdown_count==1000) //每一秒倒計時減一{if(countdown>0) countdown--; countdown_count=0;}if(temp_count==200) //每200ms獲取一次室溫{temp_flag=1;temp_count=0;} }void Timer0() interrupt 1 {if(moude_count<pwm) pwm的占空比越大,led燈越亮。{if(moude==1&&countdown!=0){P2=(P2&0x1f)|0x80;P0=0xfe;P2&=0x1f;}if(moude==2&&countdown!=0){P2=(P2&0x1f)|0x80;P0=0xfd;P2&=0x1f;}if(moude==3&&countdown!=0){P2=(P2&0x1f)|0x80;P0=0xfb;P2&=0x1f;}}else{P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f; }if(++moude_count>=10) moude_count=0; }最后,這是本人第一次寫博客,寫的不好的地方,還希望大家指正。我也會往后寫,打算寫完一題,就和大家討論一下。
總結
以上是生活随笔為你收集整理的第七届蓝桥杯单片机省赛题目解析的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: yapi连接mongodb集群
- 下一篇: maya骨骼绑定——蒙皮中的权重问题
