|
/*一. 程序功能
由上位機發送1給單片機,蜂鳴器以400ms頻率發聲,發送2時以200ms頻率發聲,發送3時以100ms頻率發聲,發送4時關閉蜂鳴器.
二. 程序源碼*/
#include <reg52.h>
//聲明程序需要的全局變量
unsigned char flag, a, num, benum;
//聲明單片機的蜂鳴器
sbit beep = P2 ^ 3;
//聲明初始化函數
void init();
//主函數
void main()
{
//初始化
init();
while (1)
{
//檢測是否發生串口中斷
if (flag == 1)
{
//手動將flag置0,方便下次檢測
flag = 0;
//關閉中斷???為什么需要關閉總中斷而不僅僅是串口中斷
EA = 0;
//開啟計數器0
TR0 = 1;
//根據串口接收的數據設置蜂鳴器的頻率基數
switch(a)
{
case 1:
benum = 4;
break;
case 2:
benum = 2;
break;
case 3:
benum = 1;
break;
case 4:
TR0 = 0;
beep = 1;
}
//開啟總中斷
EA = 1;
}
}
}
void init()
{
//設置定時器1為工作方式2, 定時器0為工作方式1
TMOD = 0x21;
//波特率 = (2的SMOD次方/32) * (T1溢出率) //T1溢出率 = [256 - X]*12/晶振頻率
//根據SMOD的0,1取值得到的X分別為TH1,TL1
//波特率選取9600,晶振頻率為11.0592
TH1 = 0xfd;
TL1 = 0xfd;
//以50s作為計數器0的基數
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
//ET1 = 1; 這里不需要開啟定時器1中斷,因為定時器1工作在方式2,為8位自動重裝方式,進入中斷也無事可做
//啟動T1定時器
TR1 = 1;
//開啟T0定時器
ET0 = 1;
//TR0 = 1; TR0的初始化放在主函數的while中,從而啟動T0定時器,使蜂鳴器按頻率發聲
//設定串口工作方式
//10位異步收發(8位數據), 波特率可變(由定時器溢出率控制)
SM0 = 0;
SM1 = 1;
//容許串口中斷
REN = 1;
//開啟總中斷
EA = 1;
//開啟串口中斷
ES = 1;
}
void ser() interrupt 4
{
//RI為接收中斷標志位, 在方式0時, 當串行接收第8位數據結束時, 或在其他方式, 串行接收停止位的
//中間時, 由內部硬件使RI置1, 向CPU發出中斷申請, 也必須在中斷服務程序中, 用軟件將其清0,取消
//此中斷申請, 以方便下一次中斷申請檢測, 即這樣才能產生下一次中斷.
//這里RI清0, 因為程序既然產生了串口中斷, 肯定是收到或發送了數據, 在開始時沒有發送任何數據
//那必然是收到了數據, 此時RI會被硬件置1, 所以進入串口中斷服務程序后必須由軟件清0, 這樣才能
//產生下一次中斷.
RI = 0;
//將SBUF中的數據讀走給a, 這是此中斷服務程序最重要的目的
a = SBUF;
//將串口中斷標志位置1,方便主程序檢測
flag = 1;
}
void T0_timer() interrupt 1
{
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
num++;
if (num == benum)
{
num = 0;
beep = ~beep;
}
}
仿真也測試了 我在串口助手里面輸入1不來米 幫忙看看
|
|