×
嵌入式 > 嵌入式开发 > 详情

串行口通信单片机根据上位机发送的数字控制蜂鸣器发声

发布时间:2021-03-18 发布时间:
|
一. 程序功能
上位机发送1给单片机,蜂鸣器以400ms频率发声,发送2时以200ms频率发声,发送3时以100ms频率发声,发送4时关闭蜂鸣器.
二. 程序源码
#include
//声明程序需要的全局变量
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;
}
}


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
MSP430单片机硬件知识-复位