做網(wǎng)站賣東西seo優(yōu)化培訓公司
題目要求:
1、 基本要求
2、 競賽板配置要求
3、 硬件框圖
系統(tǒng)硬件框圖
4、 功能描述
4.1基本功能
4.2顯示功能
和之前一樣建好工程文件夾,里邊包含User(放工程文件,mian.c)、Driver(存放底層文件如Led.c,Led.h等)
新建的工程先搭建框架,可以先書寫底層函數(shù)(此次書寫了五個函數(shù)并包含相應的頭文件共十個底層文件)
4.3按鍵功能

4.4LED 指示燈功能

4.5初始狀態(tài)說明
底層函數(shù)內容:
1.初始化底層驅動專用文件
比如先用3個IO口控制74HC138譯碼器,控制Y4為低電平;當Y4為低電平時,或非門74HC02控制Y4C為高電平,使74HC573的OE端口有效,OE端口有效時,可使用P0口控制LED的亮滅。
可以去多了解74HC138譯碼器,74HC02或非門,74HC573八路輸出透明鎖存器的相關內容會更好理解
#include <Init.h>
//關閉外設
void System_Init()
{
? ? P0 = 0xff;
? ? P2 = P2 & 0x1f | 0x80;
? ? P2 &= 0x1f;
? ? P0 = 0x00;
? ? P2 = P2 & 0x1f | 0xa0;
? ? P2 &= 0x1f;
}
#include <STC15F2K60S2.H>
void System_Init();
2.Led底層驅動專用文件
與初始化底層驅動專用文件同理,需要了解對應的鎖存器控制,可以在使用的芯片數(shù)據(jù)手冊查看
#include <Led.h>
void Led_Disp(unsigned char addr,enable)
{
? ? static unsigned char temp = 0x00;
? ? static unsigned char temp_old = 0xff;
? ? if(enable)
? ? ? ? temp |= 0x01 << addr;
? ? else
? ? ? ? temp &= ~(0x01 << addr);
? ? if(temp != temp_old)
? ? {
? ? ? ? P0 = ~temp;
? ? ? ? P2 = P2 & 0x1f |0x80;
? ? ? ? P2 &= 0x1f;
? ? ? ? temp_old = temp;
? ? }
}
#include <STC15F2K60S2.H>
void Led_Disp(unsigned char addr,enable);
3.按鍵底層驅動專用文件
(板子上的按鍵從按鍵4開始到按鍵19,可根據(jù)實際硬件修改)
#include <Key.h>
unsigned char Key_Read()
{
? ? unsigned char temp = 0;
? ? if(P33 == 0) temp = 4;
? ? if(P32 == 0) temp = 5;
? ? if(P31 == 0) temp = 6;
? ? if(P30 == 0) temp = 7;
? ? return temp;
}
#include <STC15F2K60S2.H>
unsigned char Key_Read();
4.數(shù)碼管底層驅動專用文件
(這個板子使用的為共陽數(shù)碼管,若使用的為共陰數(shù)碼管要更換對應的段碼表和位選表;與初始化底層驅動專用文件同理,需要了解對應的鎖存器控制,可以在使用的芯片數(shù)據(jù)手冊查看)
#include <Seg.h>
unsigned char Seg_Dula[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//數(shù)碼管段碼儲存數(shù)組
unsigned char Seg_Wela[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//數(shù)碼管位碼儲存數(shù)組
void Seg_Disp(unsigned char wela,dula,point)
{
? ? P0 = 0xff; //
? ? P2 = P2 & 0x1f |0xe0;
? ? P2 &= 0x1f;
? ? P0 = Seg_Wela[wela];
? ? P2 = P2 & 0x1f |0xc0;
? ? P2 &= 0x1f;
? ? P0 = Seg_Dula[dula];
? ? if(point)
? ? ? ? P0 &= 0x7f;
? ? P2 = P2 & 0x1f |0xe0;
? ? P2 &= 0x1f;
}
#include <STC15F2K60S2.H>
void Seg_Disp(unsigned char wela,dula,point);
5.數(shù)模轉換底層驅動專用頭文件
/*
? 程序說明: IIC總線驅動程序
? 軟件環(huán)境: Keil uVision 4.10?
? 硬件環(huán)境: CT107單片機綜合實訓平臺 8051,12MHz
? 日 ? ?期: 2011-8-9
*/
#include "iic.h"
#include "intrins.h"
#define DELAY_TIME 5
#define Photo_Res_Channel 0x41
#define Adj_Res_Channel 0x43
//總線引腳定義
sbit SDA = P2^1; ?/* 數(shù)據(jù)線 */
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);
}
//發(fā)送應答
void IIC_SendAck(bit ackbit)
{
? ? SCL = 0;
? ? SDA = ackbit; ??? ??? ??? ??? ??? ?// 0:應答,1:非應答
? ? 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總線發(fā)送數(shù)據(jù)
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總線上接收數(shù)據(jù)
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; ? ?
}
//函數(shù)名:ADC轉換函數(shù),這個要自己寫
//入口參數(shù):要進行轉換的通道控制位
//返回值:ADC轉換的數(shù)值
//函數(shù)功能:對指定的通道進行ADC轉換,函數(shù)返回轉換的數(shù)值
unsigned char Ad_Read(unsigned char addr)//AD讀取,要有一個入口參數(shù)
{
?? ?unsigned char temp;//接收返回值變量
?? ?IIC_Start();//啟動單總線
?? ?IIC_SendByte(0x90);//發(fā)送一個0x90,告訴單片機要寫數(shù)據(jù)了
?? ?IIC_WaitAck();//等待應答
?? ?IIC_SendByte(addr);//發(fā)送一個地址(獲取的數(shù)據(jù))
?? ?IIC_WaitAck();//等待應答
?? ?
?? ?IIC_Start();//啟動單總線
?? ?IIC_SendByte(0x91);//寫一個0x91
?? ?IIC_WaitAck();//等待應答
?? ?temp = IIC_RecByte();//讀取數(shù)據(jù)
?? ?IIC_SendAck(1);//發(fā)送一個非應答信號
?? ?IIC_Stop();//停止
?? ?return temp;
}
//函數(shù)名:DAC轉換函數(shù),這個要自己寫
//入口參數(shù):要進行轉換的數(shù)值
//返回值:無
//函數(shù)功能:對入口參數(shù)要轉換的DA數(shù)據(jù)進行轉換
void Da_Write(unsigned char dat)
{
?? ?IIC_Start();//啟動單總線
?? ?IIC_SendByte(0x90);//發(fā)送一個0x90,告訴單片機要寫數(shù)據(jù)了
?? ?IIC_WaitAck();//等待應答
?? ?IIC_SendByte(0x41);//使能DAC轉換
?? ?IIC_WaitAck();//等待應答
?? ?IIC_SendByte(dat);//發(fā)送一個地址(獲取的數(shù)據(jù))
?? ?IIC_WaitAck();//等待應答
?? ?IIC_Stop();
}
//頭文件? ?頭文件都需要自己編寫,目前最新的一版賽點資源包沒有頭文件。
#include <STC15F2K60S2.H>
void IIC_Start(void);?
void IIC_Stop(void); ?
bit IIC_WaitAck(void); ?
void IIC_SendAck(bit ackbit);?
void IIC_SendByte(unsigned char byt);?
unsigned char IIC_RecByte(void);?
unsigned char Ad_Read(unsigned char addr);
void Da_Write(unsigned char dat);
?
工程主函數(shù)內容:
1.頭文件聲明(把需要用到的頭文件添加進來)
#include <STC15F2K60S2.H>//單片機寄存器專用頭文件
#include "Init.h"//初始化底層驅動專用頭文件
#include "Led.h"//Led底層驅動專用頭文件
#include "Key.h"//按鍵底層驅動專用頭文件
#include "Seg.h"//數(shù)碼管底層驅動專用頭文件
#include "iic.h"//數(shù)模轉換底層驅動專用頭文件
2.變量聲明(把需要用到的所有變量現(xiàn)在這里進行聲明)
unsigned char Key_Val,Key_Old,Key_Down,Key_Up;//按鍵專用變量
unsigned char Seg_Pos;//數(shù)碼管掃描專用變量
unsigned char Key_Slow_Down;//按鍵減速專用變量
unsigned char Seg_Slow_Down;//數(shù)碼管減速專用變量
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};//數(shù)碼管顯示數(shù)據(jù)存放數(shù)組
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};//數(shù)碼管小數(shù)點數(shù)據(jù)存放數(shù)組
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};//Led顯示數(shù)據(jù)存放數(shù)組
unsigned int Timer_1000ms;//1000毫秒計時變量
unsigned int Freq;//實時頻率值
bit Seg_Disp_Mode;//數(shù)碼管顯示模式變量 0-頻率顯示界面 1-電壓顯示界面
float Voltage;//實時電壓值
bit Output_Mode;//DAC輸出模式標志位 0-固定2V 1-隨AD變化
float Vlotage_Output;//實時輸出電壓
bit Seg_Flag = 1;//數(shù)碼管使能標志位 默認開啟
bit Led_Flag = 1;//Led使能標志位 默認開啟
3.按鍵處理函數(shù)(在這里編寫按鍵控制的函數(shù))
void Key_proc()
{
?? ?if(Key_Slow_Down)return;
?? ?Key_Slow_Down = 1;//鍵盤減速程序
?? ?Key_Val = Key_Read();//實時讀取鍵碼值
?? ?Key_Down = Key_Val & (Key_Val ^ Key_Old);//捕捉按鍵下降沿
?? ?Key_Up = ~ Key_Val & (Key_Val ^ Key_Old);//捕捉按鍵上升沿
?? ?Key_Old = Key_Val;//輔助掃描變量
?? ?
?? ?switch (Key_Down)
?? ?{
?? ??? ?case 4://顯示界面切換
?? ??? ??? ?Seg_Disp_Mode ^= 1;
?? ??? ?break;
?? ??? ?case 5://輸出模式切換
?? ??? ??? ?Output_Mode ^= 1;
?? ??? ?break;
?? ??? ?case 6://LED 指示燈功能控制
?? ??? ??? ?Led_Flag ^= 1;
?? ??? ?break;
?? ??? ?case 7://數(shù)碼管顯示功能控制
?? ??? ??? ?Seg_Flag ^= 1;
?? ??? ?break;
?? ?}
}
4.信息處理函數(shù)(需要使用到到的函數(shù)進行簡單的預處理)
void Seg_Proc()
{
?? ?unsigned char i = 3;//高位熄滅專用變量
?? ?if(Seg_Slow_Down)return;
?? ?Seg_Slow_Down = 1;//數(shù)碼管減速程序
?? ?
?? ?/*信息讀取區(qū)*/
?? ?Voltage = Ad_Read(0x43) / 51.0;//實時獲取電壓值
?? ?
?? ?if(Output_Mode == 0)//處于固定輸出模式
?? ??? ?Vlotage_Output = 2;
?? ?else//處于隨AD輸出模式
?? ??? ?Vlotage_Output = Voltage;
?? ?
?? ??? ?/*數(shù)據(jù)顯示區(qū)*/
?? ?Seg_Point[5] = Seg_Disp_Mode;//小數(shù)點使能
?? ?if(Seg_Disp_Mode == 0)//頻率顯示
?? ?{
?? ??? ?
?? ??? ?Seg_Buf[0] = 11;//顯示F
?? ??? ?Seg_Buf[3] = Freq / 10000 % 10;
?? ??? ?Seg_Buf[4] = Freq / 1000 % 10;
?? ??? ?Seg_Buf[5] = Freq / 100 % 10;
?? ??? ?Seg_Buf[6] = Freq / 10 % 10;
?? ??? ?Seg_Buf[7] = Freq % 10;
?? ??? ?while(Seg_Buf[i] == 0)//數(shù)碼管高位熄滅
?? ??? ?{
?? ??? ??? ?Seg_Buf[i] = 10;
?? ??? ??? ?if(++i == 7)break;//保證最低位不熄滅 避免程序卡死
?? ??? ?}
?? ?}
?? ?else//處于電壓顯示界面
?? ?{
?? ??? ?Seg_Buf[0] = 12;//顯示U
?? ??? ?Seg_Buf[3] = 10;
?? ??? ?Seg_Buf[4] = 10;
?? ??? ?Seg_Buf[5] = (unsigned char)Voltage;
?? ??? ?Seg_Buf[6] = (unsigned int)(Voltage * 100) / 10 % 10;
?? ??? ?Seg_Buf[7] = (unsigned int)(Voltage * 100) % 10;
?? ?}
}
5.其他函數(shù)(其他編寫的函數(shù),在這里書寫會比較方便理解)
void Led_Proc()
{
?? ?unsigned char i;//For循環(huán)專用變量
?? ?/* DAC相關 */
?? ?Da_Write(Vlotage_Output * 51);//實時輸出電壓值
?? ?/* Led相關 */
?? ?for(i=0;i<2;i++) //互斥點亮
?? ?ucLed[i] = (i == Seg_Disp_Mode);
?? ?ucLed[2] = ((Voltage >= 1.5 && Voltage <= 2.5) || (Voltage >= 3.5));
?? ?ucLed[3] = ((Freq >= 1000 && Freq < 5000) || (Freq >= 10000));
?? ?ucLed[4] = Output_Mode;
}
6.定時器中斷初始化函數(shù)
(這個可以使用STC的定時器計算那里生成c代碼,后面要自己添加ET0,EA打開中斷)這里使用定時器0計數(shù),定時器1計時
/* 定時器1中斷初始化函數(shù) */
void Timer1Init(void)?? ??? ?//1毫秒@12.000MHz
{
?? ?AUXR &= 0xBF;?? ??? ?//定時器時鐘12T模式
?? ?TMOD &= 0x0F;?? ??? ?//設置定時器模式
?? ?TL1 = 0x18;?? ??? ?//設置定時初值
?? ?TH1 = 0xFC;?? ??? ?//設置定時初值
?? ?TF1 = 0;?? ??? ?//清除TF1標志
?? ?TR1 = 1;?? ??? ?//定時器1開始計時
?? ?ET1 = 1;
?? ?EA = 1;
}
//頻率測量定時器配置/* 定時器0中斷初始化函數(shù) */
void Timer0Init(void)?? ??? ?//0毫秒@12.000MHz
{
?? ?TMOD &= 0xF0;?? ??? ?//設置定時器模式
?? ?TMOD |= 0x05;?? ??? ?//GATE = 0 計數(shù)模式 16位不自動重裝//設置計數(shù)模式
?? ?TL0 = 0x00;?? ??? ?//設置定時初值
?? ?TH0 = 0x00;?? ??? ?//設置定時初值
?? ?TF0 = 0;?? ??? ?//清除TF0標志
?? ?TR0 = 1;?? ??? ?//定時器0開始計時
}
7.定時器1中斷服務函數(shù)
(為了定時執(zhí)行特定的任務,如此處設置了定時的時間觸發(fā)了數(shù)碼管和LED產(chǎn)生特定反應)//中斷在測試時可以先注釋掉,但是這里按鍵狀態(tài)有延時,測試按鍵時可以解除注釋void Timer1server()interrupt 3
{
?? ?if(++Key_Slow_Down == 10)Key_Slow_Down = 0;//鍵盤減速專用
?? ?if(++Seg_Slow_Down == 500)Seg_Slow_Down = 0;//數(shù)碼管減速專用
?? ?if(++Seg_Pos == 8)Seg_Pos = 0;//數(shù)碼管顯示專用
?? ?if(Seg_Flag == 1)//數(shù)碼管使能
?? ?Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
?? ?else
?? ??? ?Seg_Disp(Seg_Pos,10,0);//熄滅所有數(shù)碼管
?? ?if(Led_Flag == 1)//Led使能
?? ??? ?Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
?? ?else
?? ??? ?Led_Disp(Seg_Pos,0);//熄滅所有Led
?? ?if(++Timer_1000ms == 1000)//實時讀取頻率值
?? ?{
?? ??? ?Timer_1000ms = 0;
?? ??? ?Freq = TH0 << 8 | TL0;
?? ??? ?TH0 = TL0 = 0;
?? ??? ?
?? ?}
}
8.主函數(shù)Main(調用書寫的函數(shù)實現(xiàn)所需的相應功能)
void main()
{
?? ?Sys_Init();
?? ?Timer0Init();
?? ?Timer1Init();
?? ?while(1)
?? ?{
?? ??? ?Key_proc();
?? ??? ?Seg_Proc();
?? ??? ?Led_Proc();
? ? }
}
NE555相關資料:
通過Rb3調節(jié),電壓測量可以在這個圖的19,20腳測量。
GATE = 0,定時器計數(shù);C/T = 1,連接P34。
根據(jù)這兩個信息可知,定時器0設置成0101的模式,使用計數(shù)器。
定時器1計時