主板介紹:P3^2~P^5為四個按鍵;P1^0~P1^7為8個LED燈

#include "reg52.h" //此文件中定義了單片機的一些特殊功能寄存器 typedef unsigned int uint; //對數據類型進行聲明定義 typedef unsigned char u8; sbit k1=P3^5; //定義P31口是k1 sbit led=P1^0; //定義P10口是led /******************************************************************************* * 函 數 名 : delay * 函數功能 : 晶振11.0592M延時函數 *******************************************************************************/ void delay(uint z) { uint i,j; for(j=z;j>0;j--) for(i=112;i>0;i--); } /******************************************************************************* * 函 數 名 : keypros * 函數功能 : 按鍵處理函數,判斷按鍵K1是否按下 *******************************************************************************/ void keypros() { if(k1==0) { delay(50); if(k1==0) //再次判斷按鍵是否按下 led=~led; //led狀態取反 } while(!k1); //檢測按鍵是否松開 } /******************************************************************************* * 函 數 名 : main * 函數功能 : 主函數 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void main() { while(1) { keypros(); //按鍵處理函數 } }
計數器(計數器0用P3^4按鈕,計數器1用P3^5按鈕,不懂)

/*----------------------------------------------- 名稱:計數器0 論壇:www.doflye.net 編寫:shifang 日期:2009.5 修改:無 內容:通過外部按鍵計數進入中斷執行LED取反 ------------------------------------------------*/ #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 sbit LED=P1^0; //定義LED端口 /*------------------------------------------------ 定時器初始化子程序(按鈕P3^4控制,不知為什么) ------------------------------------------------*/ void Init_Timer0(void) { TMOD |= 0x01 | 0x04; //使用模式1,16位計數器,使用"|"符號可以在使用多個定時器時不受影響 TH0=0xFF; //給定初值 TL0=245; //從245計數到255 EA=1; //總中斷打開 ET0=1; //定時器中斷打開 TR0=1; //定時器開關打開 } /*------------------------------------------------ 主程序 ------------------------------------------------*/ main() { Init_Timer0(); while(1); } /*------------------------------------------------ 定時器中斷子程序 ------------------------------------------------*/ void Timer0_isr(void) interrupt 1 using 1 { TH0=0xFF; //重新給定初值 TL0=245; LED=~LED; //指示燈反相,可以看到閃爍 }

/*----------------------------------------------- 名稱:計數器1 論壇:www.doflye.net 編寫:shifang 日期:2009.5 修改:無 內容:通過外部按鍵計數進入中斷執行LED取反 ------------------------------------------------*/ #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 sbit LED=P1^0; //定義LED端口 /*------------------------------------------------ 定時器初始化子程序 ------------------------------------------------*/ void Init_Timer1(void) { TMOD |= 0x10 | 0x40; //使用模式1,16位計數器,使用"|"符號可以在使用多個定時器時不受影響 TH1=0xFF; //給定初值 TL1=245; //從245計數到255 EA=1; //總中斷打開 ET1=1; //定時器中斷打開 TR1=1; //定時器開關打開 } /*------------------------------------------------ 主程序 ------------------------------------------------*/ main() { Init_Timer1(); while(1); } /*------------------------------------------------ 定時器中斷子程序 ------------------------------------------------*/ void Timer1_isr(void) interrupt 3 { TH1=0xFF; //重新給定初值 TL1=245; LED=~LED; //指示燈反相,可以看到閃爍 }
中斷定義:
當機器正在執行程序的過程中,一旦遇到一些異常或者特殊請求時,停止正在 執行的程序轉入必要的處理,處理完畢后,立即返回斷點繼續執行。
51單片機中的中斷源:
①外部中斷
②定時器/計數器中斷
③串口中斷三類
單片機與外設數據傳遞方式
1.無條件傳送: 不考慮外設狀態信息,直接傳送數據
2.查詢傳送: 不斷查詢外設狀態信息,判斷后決定是否傳送數據
3.中斷傳送: 由外設主動向控制器提出申請的數據傳送方式
4.DMA傳送: 直接存儲器存取,需要DMA控制器來完成而不需CPU干預
外部中斷源
外部中斷0 => 12號引腳(INT0/P3.2)
外部中斷1 => 13號引腳(INT1/P3.3)
1、IE – 中斷允許控制寄存器
2、TCON – 控制寄存器
EA 全局中斷允許位,當此位是1時中斷可用。(重要)
ET2 定時器/計數器2中斷允許位
ES 串口中斷允許位
ET1 定時器/計數器1中斷允許位
EX1 外部中斷1允許位
ET0 定時器/計數器0中斷允許位
EX0 外部中斷0允許位 (重要)
和定時器中斷類似,使用外部中斷需要開啟全局中斷允許位EA
,以及開啟外部中斷0允許位EX0
EA = 1; //開啟總中斷 EX0 = 1; //開啟0號外部中斷
TCON
TF1 定時器1溢出標志位
TR1 定時器1運行控制位
TF0 定時器0溢出標志位
TR0 定時器0運行控制位
IE1和IE0為狀態位,即表示CPU對當前的中斷執行狀態,一般無需手動設置。需要設置的寄存器位是IT0
,以選擇低電平信號觸發還是負跳變信號觸發。
低電平信號 :即該引腳電平信號為0時有效。
負跳變信號 :意思是電平從高跳至低時有效,即1→0的信號,而一直維持低電平則不會觸發中斷。
void initEx0() { //中斷允許寄存器IE EA = 1; //開啟總中斷 EX0 = 1; //開啟0號外部中斷 //控制寄存器TCON IT0 = 1; //設置外部中斷觸發方式 //0 - 低電平觸發 //1 - 負跳變觸發 }
#include <reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 typedef unsigned char u8; //重新定義數據類型名 typedef unsigned int u16;//重新定義數據類型名 sbit key=P3^2; sbit led=P1^0; void delay(u16 num) { u16 x,y; for(x=num;x>0;x--) for(y=110;y>0;y++); } //外部中斷1 void timer0() interrupt 0 { delay(10); if(key==0) led=~led; while(key); } void main()//主函數 { TCON |=0x01; IE=0x81; while(1) //主函數大循環 { } }
按鈕外部中斷0

/*----------------------------------------------- 名稱:外部中斷0電平觸發 內容:通過中斷接口P3.2連接的獨立按鍵測試,按一次P1口的LED燈反向, 這里使用電平觸發,所以一直按鍵不松開和一次按鍵效果不相同,按下會看到燈全部亮 說明中斷一直在作用,用示波器看則是高頻方波 ------------------------------------------------*/ #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 /*------------------------------------------------ 外部中斷程序 ------------------------------------------------*/ void ISR_Key(void) interrupt 0 using 1 { P1=~P1; //進入中斷程序執行程序, //此時可以通過 EA=0指令暫時關掉中斷 } typedef unsigned int uint; //對數據類型進行聲明定義 void delay(uint i) { while(i--); } sbit btn=P3^2; sbit led=P1^0; /*------------------------------------------------ 主程序 ------------------------------------------------*/ main() { P1=0x55; //P1口初始值 EA=1; //全局中斷開 EX0=1; //外部中斷0開 IT0=0; //電平觸發 while(1); }
先整理通用的代碼,有些不知所以然

#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 #include <intrins.h> //頭文件包含 typedef unsigned char u8; //重新定義數據類型名 typedef unsigned short u16;//重新定義數據類型名 typedef unsigned long u32; //重新定義數據類型名 sbit PWM_OUT=P1^1; u8 idata PWM_Write_Byte[3]=0; //****************************祁緒電子 2020年5月*** // 定時器0初始化 晶振11059200,12T,輸出50Hz的PWM,占空比0~255 // 定時器初值為:256-(11059200÷12÷50Hz÷256) = 184 = 0xB8 void PWM_Init(void) { TMOD &= 0xF0; //配置定時器工作模式 TMOD |= 0x02; //配置定時器工作模式 8位自動重裝模式 TL0 = 0xB8;; //定時器初值 TH0 = 0xB8; //定時器重裝初值 TR0 = 1; //啟動定時器0 ET0=1; //允許定時器0申請中斷 EA=1; //中斷總閘閉合 } //****************************祁緒電子 2020年5月*** //定時器0的CPU處理函數,位置任意寫都行 void PWM_Display_timer0() interrupt 1 { static u8 pwm_t=0; //局部變量,不丟失數據 if(pwm_t<PWM_Write_Byte[0]) { PWM_OUT=1; } else PWM_OUT=0; pwm_t++; } //***************************祁緒電子 2020年5月*** // PWM 數模變換數據分配 void PWM_Allot() { static u8 kkk=0; static u8 count=0; count++; if(count>150) { count=0; kkk++; PWM_Write_Byte[0]=kkk; //kkk為占空比自動增加 PWM_Write_Byte[1]=10; PWM_Write_Byte[2]=10; } } void main()//主函數 { PWM_Init(); while(1) //主函數大循環 { PWM_Allot(); } }
外部中斷1電平觸發

#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 sbit LED=P1^0; //定義LED端口 void DelayUs2x(unsigned char t);//us級延時函數聲明 void DelayMs(unsigned char t); //ms級延時 /*------------------------------------------------ 主程序 ------------------------------------------------*/ main() { LED=0; //LED燈點亮 EA=1; //全局中斷開 EX1=1; //外部中斷0開 IT1=0; //琁T1=0表示電平觸發 while(1) { //在此添加其他程序 } } /*------------------------------------------------ 外部中斷程序 ------------------------------------------------*/ void ISR_INT1(void) interrupt 2 { if(!INT1) { DelayMs(10);//在此處可以添加去抖動程序,防止按鍵抖動造成錯誤 if(!INT1) while(!INT1);//等待按鍵釋放 { LED=!LED; } } } /*------------------------------------------------ uS延時函數,含有輸入參數 unsigned char t,無返回值 unsigned char 是定義無符號字符變量,其值的范圍是 0~255 這里使用晶振12M,精確延時請使用匯編,大致延時 長度如下 T=tx2+5 uS ------------------------------------------------*/ void DelayUs2x(unsigned char t) { while(--t); } /*------------------------------------------------ mS延時函數,含有輸入參數 unsigned char t,無返回值 unsigned char 是定義無符號字符變量,其值的范圍是 0~255 這里使用晶振12M,精確延時請使用匯編 ------------------------------------------------*/ void DelayMs(unsigned char t) { while(t--) { //大致延時1mS DelayUs2x(245); DelayUs2x(245); } }
外部中斷0下降沿觸發

/*----------------------------------------------- 名稱:外部中斷0邊沿觸發 論壇:www.doflye.net 編寫:shifang 日期:2009.5 修改:無 內容:通過中斷接口P3.2連接的獨立按鍵測試,按一次P1口的LED燈反向, 這里使用邊沿觸發,所以一直按鍵不松開和一次按鍵效果相同,區 別於電平觸發 ------------------------------------------------*/ #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 /*------------------------------------------------ 主程序 ------------------------------------------------*/ main() { P1=0x55; //P1口初始值 EA=1; //全局中斷開 EX0=1; //外部中斷0開 IT0=1; //邊沿觸發 while(1) { //在此添加其他程序 } } /*------------------------------------------------ 外部中斷程序 ------------------------------------------------*/ void ISR_Key(void) interrupt 0 using 1 { P1=~P1; //s3按下觸發一次,P1取反一次 }
外部中斷1下降沿觸發

/*----------------------------------------------- 名稱:外部中斷1電下降沿平觸發 論壇:www.doflye.net 編寫:shifang 日期:2009.5 修改:無 內容:通過中斷接口P3.3連接的獨立按鍵測試,按一次P1.0口的LED燈反向, 作用效果和中斷0相同 ------------------------------------------------*/ #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 sbit LED=P1^0; //定義LED端口 void DelayUs2x(unsigned char t);//us級延時函數聲明 void DelayMs(unsigned char t); //ms級延時 /*------------------------------------------------ 主程序 ------------------------------------------------*/ main() { LED=0; //LED燈點亮 EA=1; //全局中斷開 EX1=1; //外部中斷1開 IT1=1; //IT1=1表示邊沿觸發 while(1) { //在此添加其他程序 } } /*------------------------------------------------ 外部中斷程序 ------------------------------------------------*/ void ISR_INT1(void) interrupt 2 { if(!INT1) { DelayMs(10);//在此處可以添加去抖動程序,防止按鍵抖動造成錯誤 if(!INT1) //while(!INT1);//等待按鍵釋放 { LED=!LED; } } } /*------------------------------------------------ uS延時函數,含有輸入參數 unsigned char t,無返回值 unsigned char 是定義無符號字符變量,其值的范圍是 0~255 這里使用晶振12M,精確延時請使用匯編,大致延時 長度如下 T=tx2+5 uS ------------------------------------------------*/ void DelayUs2x(unsigned char t) { while(--t); } /*------------------------------------------------ mS延時函數,含有輸入參數 unsigned char t,無返回值 unsigned char 是定義無符號字符變量,其值的范圍是 0~255 這里使用晶振12M,精確延時請使用匯編 ------------------------------------------------*/ void DelayMs(unsigned char t) { while(t--) { //大致延時1mS DelayUs2x(245); DelayUs2x(245); } }