电子系统综合设计报告(包括完整代码)

更新时间:2023-08-30 01:39:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

电视机预警系统,基于stc89c52rc单片机

2011级现代电子设计课程结题报告

学 院 电子与信息学院 班 级 2011级信工1班

姓 名 黄汉雄、陈家俊、钟峥、冯崇师 提交日期 2014 年 6 月 25 日

电视机预警系统,基于stc89c52rc单片机

摘要

本文研究的是新型智能电视机防近视预警系统,这个系统利用超声波测距通过检测人体到电视机的距离,和人为预先设定好的距离对比,如果少于设定距离,则会有语音提醒预警,提醒人们靠后观看电视。

当今几乎每个家庭都有电视机,日常中大家都会经常看电视,于此同时包括小孩在内的很多人都是不规范看电视,离电视机太过于靠近,容易导致近视。本系统可以在电视上安装一个装置(或者集成在遥控器上),通过对过于靠近观看电视的人语音提醒预警,从而达到规范大家观看电视的习惯,减少近视人群数量的目的。

另外,本系统价格不高,适合广大家庭使用。从国内的研究情况来看,目前这方面的研究也是持续进行。本系统非常具有现实意义,而且还具有一定的发展空间,所以总的来说具有一定的研究价值。

关键词:防近视、超声波测距、语音提醒

电视机预警系统,基于stc89c52rc单片机

一、研究背景与意义

1. 研究背景

目前,据中国、美国、澳大利亚合作开展的防治儿童近视研究项目前期调查显示,我国人口近视发生率为33%,全国近视眼人数已近4亿,使我国成为世界上近视发病率最高的国家,近视眼人数世界第一。造成这种现象有很多因素,其中不规范看电视是重要原因之一。

2. 研究意义

当今几乎每个家庭都有电视机,日常中大家都会经常看电视,于此同时包括小孩在内的很多人都是不规范看电视,离电视机太过于靠近,容易导致近视。本系统可以在电视上安装一个装置(或者集成在遥控器上),通过对过于靠近观看电视的人语音提醒预警,从而达到规范大家观看电视的习惯,减少近视人群数量的目的。

另外,本系统价格不高,适合广大家庭使用。从国内的研究情况来看,目前这方面的研究也是持续进行。本系统非常具有现实意义,而且还具有一定的发展空间,所以总的来说具有一定的研究价值。

二、研究内容及完成情况

1. 研究内容

1、当发现人离电视机屏幕小于设定值时,发出报警声,报警声使用语音。 2、人离电视机的报警距离可以设置。

2. 设计原理

电视机预警系统,基于stc89c52rc单片机

1) 总体模块图

2) 各模块实现

(1)超声波测距模块:

此次设计采用的是HC-SR04超声波模块,基本工作原理: 1、采用IO口TRIG出发测距,给至少10us的高电平信号; 2、模块自动发送8个40khz 的方波,自动检测是否有信号返回;

3、有信号返回,通过IO 输出一高电平,高电平持续的时间就是超声波从发射到返回的时间.测试距离=(高电平时间*声速(340M/S))/2。

其中,TRIG是发射超声波引脚,Echo是接收引脚,Echo接在单片机的P3^2口,作为外部中断0方便检测回波信号。高电持续时间则利用单片机自带的计时器来统计。

实物图如下:

电视机预警系统,基于stc89c52rc单片机

(2)数码管显示模块

此模块负责把超声波测得的距离显示出来; 本设计采用的单片机型号是STC89C52RC;

数码管是共阴数码管,P2^6引脚负责位选,P2^7引脚负责片选,时钟信号的下降沿到

来就把数据锁存在锁存器中,用3个数码管显示测得的距离,单位是厘米。 (3)语音提醒模块

本项目中使用的语音播放模块采用ISD1700系列多段语音录放芯片。 ISD1700引脚图如下:

芯片的工作模式分两种,一种是独立按键模式,PLAY、REC、ERASE按键分别代表放音、

电视机预警系统,基于stc89c52rc单片机

录音、擦除功能。还有一种是PSI模式,此模式通过上位机来控制芯片。

此次设计采用的是独立按键模式,简单方便。一个SPI处理开始于SS管脚的下降沿,数据在SCLK的上升沿所存在芯片的MOSI管脚,在SCLK的下降沿从MISO管脚输出。

通过对芯片的编程,控制芯片播放事先录好的声音。 实物图如下:

实现性能指标

在电视上安装我们的装置(或者集成在遥控器上),通过检测人到电视的距离,如果超过我们设置的规定距离,会有语音提醒预警,提醒人靠后观看电视。

成果展示 1、超声波测距:

测量与桌面的距离,显示15厘米:

电视机预警系统,基于stc89c52rc单片机

测量和书本之间的距离:

2、整体工作图:

电视机预警系统,基于stc89c52rc单片机

三、实施过程中存在的问题和建议

1、超声波测距过程中,经常出现没接收到回波的问题。超声波测距中,HC-SR04超声波模块在有信号返回时,通过IO 输出一高电平,高电平持续的时间就是超声波从发射到返回的时间。为此,超声波接收端要接在单片机的P3^2口,也就是外部中断0接口,这样方便在收到回波信号时配合计时器取出计数器的值,这样就可以统计出高电平持续时间,然后计算出距离。

2、数码管显示模块中,需要配合计时器1定时地显示三位数字。数码管是共阴数码管,P2^6引脚负责位选,P2^7引脚负责片选,时钟信号的下降沿到来就把数据锁存在锁存器中,依次显示三个数字。

3、语音提醒模块中,为方便起见,不采用和上位机通信的SPI模式,而是通过编程控制ISD1700芯片播放事先录好的声音。了解好几个引脚的工作原理:开始于SS管脚的下降沿,数据在SCLK的上升沿所存在芯片的MOSI管脚,在SCLK的下降沿从MISO管脚输出,然后可以上网查询这块芯片的一些相关函数,然后我们利用好这些函数完成我们需要的功能。

4、三个模块整合在一起时,写好主函数,然后语音提醒模块主要是我们调用其中相应的函数即可,所以总的来说整合难度不大。调用函数的位置也应该注意好,调用函数应该放在定时器1时的外部中断内部,在显示距离之前先检查距离是否少于设定距离,如果少于就语音提醒。

电视机预警系统,基于stc89c52rc单片机

四、系统源代码

1) 超声波测距模块:

while(1) //程序循环 {

EA=0; Trig=1;

delay_20us();

Trig=0; //产生一个20us的脉冲,在Trig引脚 while(Echo==0); //等待Echo回波引脚变高电平 succeed_flag=0; //清测量成功标志 EX0=1; //打开外部中断 TH1=0; //定时器1清零 TL1=0; //定时器1清零 TF1=0; //

TR1=1; //启动定时器1 EA=1;

while(TH1 < 30) //等待测量的结果,周期65.535毫秒(可用中断实现) { if(TH1==0xff) { TR1=0; k++; } }

TR1=0; //关闭定时器1 EX0=0; //关闭外部中断 if(succeed_flag==1) { distance_data=outcomeH; //测量结果的高8位 distance_data<<=8; //放入16位的高8位 distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据 distance_data=distance_data+k;

distance_data/=58; //微秒的单位除以58等于厘米 } //Y米=(X秒*344)/2 if(succeed_flag==0) {

distance_data=0; //没有回波则清零 test = !test; //测试灯变化 } a=distance_data;

if(b==a) CONT_1=0;

电视机预警系统,基于stc89c52rc单片机

if(b!=a) CONT_1++; if(CONT_1>=3) { CONT_1=0; b=a; conversion(b); } } }

//外部中断0,用做判断回波电平

INTO_() interrupt 0 // 外部中断是0号 {

outcomeH =TH1; //取出定时器的值 outcomeL =TL1; //取出定时器的值 succeed_flag=1; //至成功测量的标志 EX0=0; //关闭外部中断 }

2) 数码管显示模块:

timer0() interrupt 1 // 定时器0中断是1号 { //TH0=0xfd; //写入定时器0初始值 TH0=0xfd; TL0=0x77; yuyin(); switch(flag) { case 0x00:dual=1;P0=ge;dual=0;wela=1;P0=0xdf;wela=0;flag++;break; case 0x01:dual=1;P0=shi;dual=0;wela=1;P0=0xef;wela=0;flag++;break; case 0x02:wela=1;P0=0xf7;wela=0;dual=1;P0=bai;dual=0;flag=0;break; } }

//****************************************************************** //显示数据转换程序

void conversion(uint temp_data) {

uchar ge_data,shi_data,bai_data ; bai_data=temp_data/100 ;

temp_data=temp_data%100; //取余运算 shi_data=temp_data/10 ;

temp_data=temp_data%10; //取余运算 ge_data=temp_data; bai_data=SEG7[bai_data];

电视机预警系统,基于stc89c52rc单片机

shi_data=SEG7[shi_data]; ge_data =SEG7[ge_data];

EA=0;

bai = bai_data; shi = shi_data; ge = ge_data ; EA=1; }

3) 语音系统模块:

void yuyin() //语音播放函数 { if( b < 60) //少于60厘米会有语音提醒 { spi_pu(); spi_play(); } else spi_pd(); }

void spi_play(void) //播放录音 { ISD_SS=0; isd1700_Npar_comm(ISD1700_PLAY|ISD_LED,2); ISD_SS=1; }

void isd1700_Npar_comm (uchar comm_par,comm_byte_count) //无参数命令 { uchar i; i=0; ISD_COMM_RAM[0]=comm_par; isd_comm_ptr=&ISD_COMM_RAM[1]; do{ *isd_comm_ptr++=NULL; }while(++i<comm_byte_count-1); rest_isd_comm_ptr(); i=0; do{

*back_data_ptr++=T_R_comm_byte(*isd_comm_ptr++); i++;

电视机预警系统,基于stc89c52rc单片机

}while(i<comm_byte_count); }

void rest_isd_comm_ptr(void) //复位 { isd_comm_ptr=ISD_COMM_RAM; back_data_ptr=ISD_COMM_RAM_C; }

uchar T_R_comm_byte( uchar comm_data ) {

uchar bit_nuber; uchar temp; bit_nuber=0; temp=0; do{ ISD_SCLK=0; delay(1); if((comm_data>>bit_nuber&0x01)!=0) {ISD_MOSI=1;} else {ISD_MOSI=0;} if(ISD_MISO) {temp=(temp>>1)|0x80;} else {temp=temp>>1;} ISD_SCLK=1; delay(1); }while(++bit_nuber<=7); ISD_MOSI=0; return (temp); }

void delay_isd(uint time) //延迟函数 { while(time--!=0); }

void delay(int x) { uchar i; for(; x>=1; x--) {for(;i<=20;i++);}

电视机预警系统,基于stc89c52rc单片机

}

void spi_pu (void) //器件上电 { ISD_SS=0;

isd1700_Npar_comm(ISD1700_PU,2); ISD_SS=1; }

void spi_pd(void) //器件下电 { ISD_SS=0;

isd1700_Npar_comm(ISD1700_PD,2); ISD_SS=1; }

4) 其他代码:

#include <reg52.h> //包括一个52标准内核的头文件 #include "ISD1700.H" #include "sound.h"

#define uchar unsigned char //定义一下方便使用 #define uint unsigned int #define ulong unsigned long

//********管脚定义

sbit Trig = P3^3; //产生脉冲引脚 sbit Echo = P3^2; //回波引脚 sbit test = P1^1; //测试用引脚

sbit wela=P2^7; //数码管位选和片选 sbit dual=P2^6;

sbit ISD_SS=P0^7; //ISD1700芯片四个引脚 sbit ISD_MISO=P0^4; sbit ISD_MOSI=P0^5; sbit ISD_SCLK=P0^6;

//********变量定义

uchar code SEG7[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管0-9 uint distance[4]; //测距接收缓冲区

uchar ge,shi,bai,temp,flag,outcomeH,outcomeL,i,k; //自定义寄存器 bit succeed_flag; //测量成功标志 uint b; //b定义为全局变量 bit re_fig,playflg;

电视机预警系统,基于stc89c52rc单片机

uchar data ISD_COMM_RAM[7]; uchar data ISD_COMM_RAM_C[7]; uchar data *isd_comm_ptr; uchar data *back_data_ptr;

//********函数声明

void conversion(uint temp_data); void delay_20us();

void delay_ms(unsigned int time); void voice();

void isd1700_Npar_comm (uchar comm_par,comm_byte_count); void init(void);

void spi_play(void);

void rest_isd_comm_ptr(void);

uchar T_R_comm_byte( uchar comm_data ); void delay_isd(uint time); void delay(int x); void spi_pu (void); void yuyin(void); void spi_pd(void);

主函数代码:

void main(void) // 主程序 { uint distance_data,a; uchar CONT_1; i=0; k=0; flag=0; Trig=0; //首先拉低脉冲输入引脚 TMOD=0x11; //定时器0,定时器1,16位工作方式 TR0=1; //启动定时器0

IT0=0; //由高电平变低电平,触发外部中断 ET0=1; //打开定时器0中断 EX0=0; //关闭外部中断 EA=1; //打开总中断0

while(1) //程序循环 { EA=0; Trig=1;

delay_20us();

Trig=0; //产生一个20us的脉冲,在Trig引脚 while(Echo==0); //等待Echo回波引脚变高电平

电视机预警系统,基于stc89c52rc单片机

succeed_flag=0; //清测量成功标志 EX0=1; //打开外部中断 TH1=0; //定时器1清零 TL1=0; //定时器1清零 TF1=0; //

TR1=1; //启动定时器1 EA=1; while(TH1 < 30) //等待测量的结果,周期65.535毫秒(可用中断实现) { if(TH1==0xff) { TR1=0; k++; } } TR1=0; //关闭定时器1 EX0=0; //关闭外部中断 if(succeed_flag==1) { distance_data=outcomeH; //测量结果的高8位 distance_data<<=8; //放入16位的高8位 distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据 distance_data=distance_data+k;

distance_data/=58; //微秒的单位除以58等于厘米 } //Y米=(X秒*344)/2 if(succeed_flag==0) {

distance_data=0; //没有回波则清零 test = !test; //测试灯变化 } a=distance_data;

if(b==a) CONT_1=0; if(b!=a) CONT_1++; if(CONT_1>=3) { CONT_1=0; b=a; conversion(b); } } }

本文来源:https://www.bwwdw.com/article/832i.html

Top