一、真題



二、模塊構建
1.編寫初始化函數(init.c)?
void Cls_Peripheral(void);
- 關閉led? ? led對應的鎖存器由Y4C控制
- 關閉蜂鳴器和繼電器
2.編寫LED函數(led.c)
void Led_Disp(unsigned char ucLed);
-
將ucLed取反的值賦給P0
-
開啟鎖存器
-
關閉鎖存器
3.編寫數碼管函數(seg.c)
void Seg_Tran(unsigned char *pucSeg_Buf,unsigned char *pucSeg_Code);
(1)段碼轉換函數
- 定義兩個變量i,j
- for循環加Switch語句進行段碼轉換,在資源數據包查找段碼表,并根據題目要求進行段碼轉換
- 注意添加空格代表都不顯示
- case記得加' '
- 判斷是否有 .
void Seg_Disp(unsigned char *pucSeg_Code,unsigned char ucSeg_Pos);
(2)數碼管顯示函數
- 要對數碼管進行消隱
- 顯示的位置
- 顯示的內容
4.獨立按鍵代碼編寫
unsigned char Key_Read_BTN(void)
- 有返回值函數(unsigned char)
- if語句判斷按鍵是否按下
- 返回按鍵所對應的數字
?5.超聲波代碼編寫
unsigned char Wave_Recv(void);
- 定義Tx和Rx引腳
- 將定時器里的TR0設置為0
- 定義變量,初始值為10,發射10個周期的波形
- 為了規范,將定時器的初值進行再次賦值
- 再令TR0=1,讓定時器開始計時
- 發送10個周期的信號
- 每12us,TF0溢出,將Tx進行異或運算,while循環加分號
- TF0清零
- 關閉定時器,將定時器初值清零,打開定時器進行正計時
- while(RX&&!TF0)如果接收到信號,或TF0溢出,則退出循環
- 退出循環后關閉定時器
- 如果TF0溢出導致退出循環,返回最大值255,否則返回計時時間
- 返回的時間單位是us,需要統一單位,*0.017 進而換算成距離單位為厘米
6.定時器代碼編寫
void Timer0Init(void);
void Timer1Init(void);?? ?
- 定時器0作為超聲波定時器,將TR0=0
- ?設置定時器0供超聲波代碼使用,時間為12us,12T,12MHz
- 定時器1作為主定時器,加上ET1=1
7.編寫AD/DA代碼
unsigned char PCF8591_ADC(void);
void PCF8591_DAC(unsigned char dat);
- ?定義SCL,SDA
- 添加"intrins.h"頭文件
- 定義變量用于存儲采集的電壓
- 寫入流程:開始--發送寫入地址--等待應答--發送電位器地址--等待應答
- 讀取流程:開始--發送讀取地址--等待應答--變量接收數據--發送應答--終止
- 讀取地址為0x91 寫入地址為0x90
- 電位器地址為0x43 光敏電阻地址為0x41
三、主函數編寫?
1.調用初始化,定時器0,定時器1,打開中斷總開關,stdio.h
2.編寫數碼管函數
- ?每200ms檢測一次
- if模式(Disp_Mode)判斷
- 不要忘記調用數碼管轉換函數(否則數碼管會全部點亮)
3. 中斷服務函數
- 為各個變量進行自加
- ?數碼管的動態顯示
4.模式界面編寫
- ?電壓數據為unsigned char類型,要轉化成浮點數? %4.2f
- 參數界面注意上下限的值
- 測距界面注意超聲波狀態是否開啟
5.ADC函數編寫
- ?沒有規定時間,任意即可
- 將采集來的數據賦值給變量
- 對采集的數據進行判斷,看是否在上下限里,從而對超聲波設置不同的狀態
6.key函數編寫?
- ?定義兩個變量
- 時間為20ms
- if判斷兩個變量是否相等,相等返回
- 不相等進入Switch語句,判斷哪個按鍵被按下
- 最后不要忘記加上Key_Val_Old=Key_Val
- s4按下,Disp_Mode+1對3取模,因為是三個界面進行切換,根據題目要求,判斷是否到參數界面,到參數界面,默認選擇電壓上限
- s6按下,參數值加0.5,注意要判斷是否在參數界面
- s7按下,參數值減0.5,注意要判斷是否在參數界面
- 注意s4按鍵按下界面切換的順序和題目給的順序不一致
- 由于要求對參數的調整在s4按下后才生效,所以需要增加兩個參數,同時記得更改其他按鍵參數變量
7.超聲波函數編寫
- 性能指標未規定時間,任意即可
- 在將測距結果賦值給變量前,先判斷狀態,為0直接返回,不進行測距
8.編寫DAC函數
- 判斷超聲波狀態,未開啟輸出0
- 若開啟,判斷超聲波測距結果,用if else語句來實現相應功能?
- 關于呈線性關系的那部分圖像,可以用數學方法計算出y=kx+b中的k和b
?9.編寫led函數
- 性能要求led響應時間小于0.2s
- 判斷處于那個界面
- 點亮置1,熄滅置0
- 點亮用|=,熄滅用&=(置1再取反)切換亮滅狀態用^=
- 切換亮滅狀態,把它放到定時器中斷里
?四、難點解析
1.按鍵切換界面的順序和題目所給順序不一致
2.調整參數時,參數值不生效,當按鍵按下時才生效
3.加,減模式的循環,用到了if判斷
4.DAC的數據轉換——通過數學方法解出來
易錯點?
將不同函數的計時變量復制粘貼時忘記更改
五、主函數代碼
#include "led.h"
#include "init.h"
#include "seg.h"
#include "key.h"
#include "tim.h"
#include "ultrasonic.h"
#include "iic.h"
#include "stdio.h"
//seg
unsigned char pucSeg_Buf[12],pucSeg_Code[8],ucSeg_Pos=0;
//time
unsigned long ulms=0;
unsigned int uiSeg_Dly=0;
unsigned int uiADC_Dly=0;
unsigned int uiDAC_Dly=0;
unsigned int uiKey_Dly=0;
unsigned int uiLed_Dly=0;
unsigned int uiUltrasonic_Dly=0;
//led
unsigned char ucLed=0x00;
//ADC
unsigned char ucADC=0;
float ADC_Pram_Max=4.5 ,ADC_Pram_Min= 0.5;
float ADC_Pram_Max_temp=4.5 ,ADC_Pram_Min_temp= 0.5;
//key
unsigned char Key_Val=0,Key_Val_Old=0;
//ultrasonic
unsigned char ucDist=0;
unsigned char Ultrasonic_Status=0;
//function
void Seg_Proc(void);
void Led_Proc(void);
void ADC_Proc(void);
void DAC_Proc(void);
void Key_Proc(void);
void Ultrasonic_Proc(void);
//mode
unsigned char Disp_Mode=0;
unsigned char Pram_Mode=0;//0--max 1--minvoid main(void)
{Cls_Peripheral();Timer0Init();Timer1Init();EA=1;while(1){Seg_Proc();ADC_Proc();DAC_Proc();Key_Proc();Led_Proc();Ultrasonic_Proc();}
}
void Seg_Proc(void)
{if(uiSeg_Dly<200)return;uiSeg_Dly=0;if(Disp_Mode==0){sprintf(pucSeg_Buf,"U %4.2f",ucADC/51.0);}else if(Disp_Mode==2){sprintf(pucSeg_Buf,"P %3.1f %3.1f",ADC_Pram_Max_temp,ADC_Pram_Min_temp);}else{if(Ultrasonic_Status==0){sprintf(pucSeg_Buf,"L AAA");}else {sprintf(pucSeg_Buf,"L %3u",(unsigned int)ucDist);}}Seg_Tran(pucSeg_Buf,pucSeg_Code);
}
void Led_Proc(void)
{if(uiLed_Dly<100)return;uiLed_Dly=0;if(Disp_Mode==0){ucLed|=0x01;ucLed&=~0x06;}else if(Disp_Mode==1){ucLed|=0x02;ucLed&=~0x05;}else{ucLed|=0x04;ucLed&=~0x03;}if(Ultrasonic_Status==1){ucLed^=0x80;}else{ucLed&=~0x80;}Led_Disp(ucLed);
}
void ADC_Proc(void)
{if(uiADC_Dly<200)return;uiADC_Dly=0;ucADC=PCF8591_ADC();if((ucADC/51.0>ADC_Pram_Min)&&(ucADC/51.0<ADC_Pram_Max)){Ultrasonic_Status=1;}else{Ultrasonic_Status=0;}
}
void Key_Proc(void)
{if(uiKey_Dly<20)return;uiKey_Dly=0;Key_Val=Key_Read_BTN();if(Key_Val==Key_Val_Old)return;switch(Key_Val){case 4:Disp_Mode=(Disp_Mode+1)%3;if(Disp_Mode==2){Pram_Mode=0;ADC_Pram_Max_temp=ADC_Pram_Max;ADC_Pram_Min_temp=ADC_Pram_Min;}else if(Disp_Mode==0){ADC_Pram_Max=ADC_Pram_Max_temp;ADC_Pram_Min=ADC_Pram_Min_temp;}break;case 5:if(Disp_Mode==2){Pram_Mode=(Pram_Mode+1)%2;}break;case 6:if(Disp_Mode==2){if(Pram_Mode==0){if(ADC_Pram_Max_temp==5.0){ADC_Pram_Max_temp=0.5;}else{ADC_Pram_Max_temp+=0.5;}}else{if(ADC_Pram_Min_temp==5.0){ADC_Pram_Min_temp=0.5;}else{ADC_Pram_Min_temp+=0.5;}}}break;case 7:if(Disp_Mode==2){if(Pram_Mode==0){if(ADC_Pram_Max_temp==0.5){ADC_Pram_Max_temp=5.0;}else{ADC_Pram_Max_temp-=0.5;}}else{if(ADC_Pram_Min_temp==0.5){ADC_Pram_Min_temp=5.0;}else{ADC_Pram_Min_temp-=0.5;}}}break;}Key_Val_Old=Key_Val;
}
void Ultrasonic_Proc(void)
{if(uiUltrasonic_Dly<500)return;uiUltrasonic_Dly=0;if(Ultrasonic_Status==0)return;ucDist=Wave_Recv();
}
void DAC_Proc(void)
{if(uiDAC_Dly<200)return;uiDAC_Dly=0;if(Ultrasonic_Status==0){PCF8591_DAC(0);}else {if(ucDist<=20){PCF8591_DAC(51);}else if(ucDist>=80){PCF8591_DAC(255);}else{PCF8591_DAC(3.4*ucDist-17);}}
}
void Time_1(void) interrupt 3
{ulms++;uiSeg_Dly++;uiADC_Dly++;uiDAC_Dly++;uiKey_Dly++;uiLed_Dly++;uiUltrasonic_Dly++;if (ulms%2==0){ucSeg_Pos=(ucSeg_Pos+1)%8;Seg_Disp(pucSeg_Code,ucSeg_Pos);}}