51单片机007:由上位机发送1给单片机时,蜂鸣器以400ms频率发声,发2时以200ms频率发声,发3时以100ms频率发生。发4时关闭蜂鸣器。 (使用定时器)
一、串行口特殊功能寄存器:
1、串行数据缓冲器SBUF
SBUF是串行发送寄存器和串行接收寄存器的总称。在逻辑上,SBUF只有一个,既表示发送寄存器,又表示接收寄存器。具有同一个单元地址99H。在物理上,SBUF有两个,一个是发送寄存器,另一个是接收寄存器。
2、串行控制寄存器SCON
功能说明:
A、SM0,SM1:串行口工作方式选择位
串口4种工作方式不同之处在于其通信协议不同,即帧格式与波特率的不同。
工作方式 | 帧格式 | 波特率 |
方式0 | 8位全是数据位,没有起始位,停止位 | 固定,每个周期传送一位数据 |
方式1 | 10位,其中1位起始位,8位数据位,1位停止位 | 不固定,取决于T1溢出率和SMOD |
方式2 | 11位,其中1位起始位,9位数据位,1位停止位 | 固定,2^SMOD*fosc/64 |
方式3 | 11位,其中1位起始位,9位数据位,1位停止位 | 不固定,取决于T1溢出率和SMOD |
B、SM2:多机通信控制位
在进行多机通信时,需要用SM2控制从机是准备接收地址还是接收数据。
当串行口以方式2或方式3接收时,若SM2=1,则只有当接收到的第九位数据(RB8)为1,才将接收到的前8位地址送入SBUF,并置位RI产生中断请求;否则,将接收到的8位地址丢弃。而当SM2=0时,则不论第九位数据为0还是为1,都将前8位数据装入SBUF中,并产生中断请求。在方式0,1时,SM2必须为0。
C、REN:允许接受位
REN位用于对串行数据的接收进行控制:REN=0,禁止接收;REN=1,允许接收。
D、TB8:发送数据的第九位
在方式2和方式3时,TB8是发送的第9位数据。在多机通信中,以TB8位的状态表示主机发送的是地址还是数据;TB8=0为数据,TB8=1为地址。该位由软件置位或复位。
E、RB8:接收数据位的第9位数据
在方式2或方式3时,RB8存放接收到的第9位数据。
F、TI :发送中断标志
当方式0时,发送完第8位数据后,该位由硬件置位。在其它方式下,于发送停止位之前,由硬件置位。因此TI=1,表示帧发送结束。TI位由软件清0。
G、RI: 接收中断标志
当方式0时,接收完第8位数据后,该位由硬件置位。在其它方式下,当接收到停止位时,该位由硬件置位。因此RI=1,表示帧接收结束。其状态既可供软件查询使用,也可以请求中断。RI位由软件清0。
3、电源控制寄存器PCON
PCON主要是为CHMOS型单片机的电源控制而设置的专用寄存器。在HMOS的单片机中,该寄存器中除最高位之外,其它位都是虚设的。
最高位(SMOD)是串行口波特率的倍增位,当SMOD=1时串行口波特率加倍。系统复位时,SMOD=0。
二、思路
题目:由上位机发送1给单片机时,蜂鸣器以400ms频率发声,发2时以200ms频率发声,发3时以100ms频率发生。发4时关闭蜂鸣器。 (使用定时器)
1、“400ms发声……200ms发声……100ms发声”
以200ms发声为例,1s变换200次,1s=1000ms=200次,1次=5ms,定时器定时1ms,如果计数变量count累加到5时,拉低蜂鸣器电源使其发声
2、进行串口中断和定时器中断的初始化和中断服务函数的编写。
当定时器T1用作波特率发生器时,通常选用定时初值自动重装的工作方式2,从而避免通过程序反复装入计数初值而引起的定时误差。
三、原理图
四、代码
#include "reg52.h"
sbit BEEP=P2^5; //将P2.5管脚定义为BEEP
static unsigned int count=0; //定义静态变量i
unsigned char rec_data;
/************************* 串口 *********************************************/
void uart_init(unsigned char baud)
{
TMOD|=0X20; //设置为定时器1,工作方式2 自动重装
SCON=0X50; //设置为工作方式1 允许串行接收
PCON=0X80; //SMOD=1 波特率加倍
TH1=baud; //计数器初始值设置
TL1=baud;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
void uart() interrupt 4 //串口通信中断函数
{
if(RI==1)
{
rec_data=SBUF; //存储接收到的数据
RI = 0; //清除接收中断标志位
}
}
/************************ 定时器 *********************************************/
void time0_init(void)
{
TMOD|=0X01; //选择为定时器0模式,工作方式1
TL0=0x18; //给定时器赋初值,1ms
TH0=0xFC;
ET0=1; //打开定时器0中断允许
EA=1; //打开总中断
TR0=1; //打开定时器
}
void time0() interrupt 1 //定时器0中断函数
{
TL0=0x18; //给定时器赋初值,1ms
TH0=0xFC;
count++;
}
void main()
{
uart_init(0XFA);//波特率为9600 (11.0592 × 10^6 Hz / 12) / 9600 - 0×256
time0_init();
while(1)
{
if(rec_data == '1')//400ms频率发声
{
count=0;
BEEP=1;
while(count!=2);
count=0;
BEEP=0;
}
if(rec_data == '2')//200ms频率发声
{
count=0;
BEEP=1;
while(count!=4);
count=0;
BEEP=0;
}
if(rec_data == '3')//100ms频率发声
{
count=0;
BEEP=1;
while(count!=9);
count=0;
BEEP=0;
}""
if(rec_data == '4')//关闭蜂鸣器
{
count=0;
BEEP=1;
}
}
}