- #include <REG52.h> //调用51单片机的头文件
- #include <intrins.h>
- #include <math.h>
- #include <string.h>
- //---------------------------------------
- //1602液晶相关I/O设置
- sbit E=P0^5; //1602液晶的E脚接在P2.3口上
- sbit RW=P0^6; //1602液晶的RW脚接在P2.4口上
- sbit RS=P0^7; //1602液晶的RS脚接在P2.5口上
- //---------------------------------------
- //---------------------------------------
- //HC-SR04相关I/O设置
- sbit TIRG=P3^4; //定义IO口,具体可以去查看原理图
- sbit ECHO=P3^2; //定义IO口,具体可以去查看原理图
- //---------------------------------------
- sbit mang= P0^7;
- unsigned long BJS=50;//报警距离50CM
- //unsigned char disbuff[4] ={0,0,0,0};
- //unsigned char disbuff_BJ[4] ={0,0,0,0};//报警信息
- unsigned int time=0;
- bit flag =0;
- unsigned char k;
- //名称:1602液晶用延时函数
- void Delay1602(unsigned int t)
- {
- unsigned int k; //定义一个16位寄存器用来做延时用
- for(k=0;k<t;k++); //延时
- }
- //名称:1602液晶忙检测函数
- void LCD1602_busy(void)
- {
- mang=1; //将P0.7置1,为读状态做准备
- RS=0; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
- RW=1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
- E=1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
- while(mang==1); //由P0.7读入1,表示1602液晶忙,需要等待
- E=0; //读完以后,恢复E的电平
- }
- //名称:1600写命令函数
- void LCD1602_Write_com(unsigned char combuf)
- {
- RS=0; //选择指令寄存器
- RW=0; //选择写状态
- P2=combuf; //将命令字通过P0口送至DB
- E=1; //E高电平将命令字写入1602液晶
- E=0; //写完以后,恢复E的电平
- }
- //名称:1602写命令函数(带忙检测)
- void LCD1602_Write_com_busy(unsigned char combuf)
- {
- LCD1602_busy(); //调用忙检测函数
- LCD1602_Write_com(combuf); //调用忙检测函数
- }
- //名称:1602写数据函数(带忙检测)
- void LCD1602_Write_data_busy(unsigned char databuf)
- {
- LCD1602_busy(); //调用忙检测函数
- RS=1; //选择数据寄存器
- RW=0; //选择写状态
- P2=databuf; //将命令字通过P0口送至DB
- E=1; //E高电平将命令字写入1602液晶
- E=0; //写完以后,恢复E的电平
- }
- //名称:1602液晶显示地址写函数
- void LCD1602_Write_address(unsigned char x,unsigned char y)
- {
- x&=0x0f; //列地址限制在0-15间
- y&=0x01; //行地址限制在0-1间
- if(y==0) //如果是第一行
- LCD1602_Write_com_busy(x|0x80); //将列地址写入
- else //如果是第二行
- LCD1602_Write_com_busy((x+0x40)|0x80); //将列地址写入
- }
- //名称:1602液晶初始化函数
- void LCD1602_init(void)
- {
- Delay1602(1500); //调用延时函数
- LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
- Delay1602(500); //调用延时函数
- LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
- Delay1602(500); //调用延时函数
- LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
- LCD1602_Write_com_busy(0x38); //8位数据总线,两行显示模式,5*7点阵显示
- LCD1602_Write_com_busy(0x08); //显示功能关,无光标
- LCD1602_Write_com_busy(0x01); //清屏
- LCD1602_Write_com_busy(0x06); //写入新的数据后,光标右移,显示屏不移动
- LCD1602_Write_com_busy(0x0C); //显示功能开,无光标
- }
- void chuankou()
- {
- // 串口的初始化
- TL1 = 0xFA; // 在11.0592MHz 下,设置波特率9600bps,工作方式2
- TH1 = 0xFA;
- TMOD|=0x21;
- TMOD = 0x21;
- SCON = 0x50; // 串口工作方式1,允许接收
- PCON = 0x80;
- EA = 0;
- REN = 1;
- TI = 0; //发送中断标志位置零
- RI = 0; //接收中断标志位置零
- TR1 = 1; //定时器1 用作波特率发生
- }
- //名称:1602液晶指定地址显示函数
- void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
- {
- LCD1602_Write_address(x,y); //先将地址信息写入
- LCD1602_Write_data_busy(buf); //再写入要显示的数据
- }
- //名称:定时器0中断服务程序
- void Timer0(void) interrupt 1
- {
- //
- flag=0;
-
- //******************************************
- }
- void yuyin()
- {
- //需要发送的文本
- char code text[] = {"观看时间太长了!"};
- unsigned char headOfFrame[5];
- unsigned char length;
- unsigned char ecc = 0; //定义校验字节
- unsigned int i=0;
- length =sizeof(text); //需要发送文本的长度
- chuankou();
- //发送过程/
- headOfFrame[0] = 0xFD ; //构造帧头FD
- headOfFrame[1] = 0x00 ; //构造数据区长度的高字节
- headOfFrame[2] = length + 3; //构造数据区长度的低字节
- headOfFrame[3] = 0x01 ; //构造命令字:合成播放命令
- //带背景音乐
- // headOfFrame[4] = 0x21 ; //构造命令参数:编码格式为GBK
- //不带背景音乐
- headOfFrame[4] = 0x01 ; //构造命令参数:编码格式为GBK
- for(i = 0; i<5; i++) //依次发送构造好的5个帧头字节
- {
- ecc=ecc^(headOfFrame[i]); //对发送的字节进行异或校验
- SBUF = headOfFrame[i];
- while (TI== 0) {;} //等待发送中断标志位置位
- TI = 0; //发送中断标志位清零
- }
- for(i = 0; i<length; i++) //依次发送待合成的文本数据
- {
- ecc=ecc^(text[i]); //对发送的字节进行异或校验
- SBUF = text[i];
- while (TI== 0) {;}
- TI = 0;
- }
- SBUF=ecc; //最后发送校验字节
- while (TI== 0) {;}
- TI=0;
- while(1);
- }
- void main(void) //主函数,单片机开机后就是从这个函数开始运行
- {
- long S;
- unsigned int i;
- unsigned int Timeout;
- LCD1602_init(); //调用1602液晶初始化函数
- //***定时器Timer0初始化***
- TMOD&=0xF0; //将TMOD的低4位定时器0控制部分清零
- TMOD|=0x01; //设置定时器0为方式1
- TMOD=0x01;
- TL0=0; //设置定时器0初值低8位
- TH0=0; //设置定时器0初值高8位
- TR0=0; //停止定时器0
- ET0=1; //Timer0中断允许
- //**********************
- //***开全局中断设置****
- //定时器Timer0设置了中断允许,此处要开全局中断
- EA=1; //开全局中断
- // ES=1;
- //*********************
- while(1)
- {
- TIRG=1; //发一个脉冲触发信号
- i=4; //维持约17US,符合不低于10US的要求
- while(i>0) //维持约17US,符合不低于10US的要求
- i--; //维持约17US,符合不低于10US的要求
- TIRG=0; //撤销触发信号
- TR0=0; //关闭定时器
- TL0=0; //设置定时器0初值低8位为0
- TH0=0; //设置定时器0初值高8位为0
- k=0; //清除溢出标志
- flag=0;
- Timeout=0;
- while((ECHO==0)&&((Timeout++)<50000)); //等待回响高电平
- TR0=1; //回响高电平来后启动定时器
- Timeout=0;
- while((ECHO==1)&&((Timeout++)<50000)); //等待回响高电平结束后
- TR0=0; //关闭定时器
- S=((TH0*256+TL0)*1.7)/100;
- if(S<=50)
- {
- yuyin();
- }
- if(flag==1||S>400) //超出测量范围显示“-”
- {
- LCD1602_Disp(0, 0, '-'); //显示百位-
- LCD1602_Disp(1, 0, '-'); //显示十位-
- LCD1602_Disp(2, 0, '-'); //显示个位-
- LCD1602_Disp(3, 0, 'C'); //显示C
- LCD1602_Disp(4, 0, 'M'); //显示M
- }
- else
- {
- if(S<=50){
- //yuyin();
- LCD1602_Disp(0, 0, S%1000/100+'0'); //显示百位
- LCD1602_Disp(1, 0, S%1000%100/10+'0'); //显示十位
- LCD1602_Disp(2, 0, S%1000%100%10+'0'); //显示个位
- LCD1602_Disp(3, 0, 'C'); //显示C
- LCD1602_Disp(4, 0, 'M'); //显示M
-
- }
- }
- i=18000; //维持约77400US,符合不低于60MS的要求
- while(i>0) //维持约77400US,符合不低于60MS的要求
- i--; //维持约77400US,符合不低于60MS的要求
- }
- }
复制代码 |