51单片机007:由上位机发送1给单片机时,蜂鸣器以400ms频率发声,发2时以200ms频率发声,发3时以100ms频率发生。发4时关闭蜂鸣器。 (使用定时器)

一、串行口特殊功能寄存器:

1、串行数据缓冲器SBUF

SBUF是串行发送寄存器和串行接收寄存器的总称。在逻辑上,SBUF只有一个,既表示发送寄存器,又表示接收寄存器。具有同一个单元地址99H。在物理上,SBUF有两个,一个是发送寄存器,另一个是接收寄存器。

2、串行控制寄存器SCON

功能说明:
A、SM0,SM1:串行口工作方式选择位

串口4种工作方式不同之处在于其通信协议不同,即帧格式与波特率的不同。

工作方式帧格式

波特率

方式0

8位全是数据位,没有起始位,停止位固定,每个周期传送一位数据
方式110位,其中1位起始位,8位数据位,1位停止位不固定,取决于T1溢出率和SMOD
方式211位,其中1位起始位,9位数据位,1位停止位固定,2^SMOD*fosc/64
方式311位,其中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;  
			}
	}		
}

posted @ 2023-12-07 20:31  Flying3080  Views(70)  Comments(0Edit  收藏  举报  来源