/////////======基于51单片机的ISD4004多段语音录放实验=======/////////
/////////==================== isd.c ===================//////////
///////// 控制IC: AT89C51/52,STC89C51/52RC//////////
///////// 系统晶振:22.1184MHz //////////
///////// 程序编写:东冬(自然风) //////////
///////// 调试时间:2009/02/13 //////////
///////// 版本:ISD4004_1.0V //////////
////////////////////////////////////////////////////////////////////
/* *** 作说明:1、按住K1键开始录音,放开K1键结束录音;再按住K1键,开始录第二段;以此类推;
2、按一下K2键,开始放音,等该段放音结束,继续等待;再按下K2键,放第二段,以此类推
PS:每一段录音长度要手动设置,不能自主控制录音长度(以待后改)*/
#include "STC89C52RC.H"
//#include <reg52.h>
#include <intrins.h>
#include "MyType.h"
//=======分段录音首地址定义======================
#define ISD_ADDS1 0x0000 //录音存放地址1
#define ISD_ADDS2 0x0100 //录音存放地址2
#define ISD_ADDS3 0x0200 //录音存放地址3
#define ISD_ADDS4 0x0300 //录音存放地址4
#define ISD_ADDS5 0x0400 //录音存放地址5
//========ISD4004指令定义========================
#define POWER_UP 0x20 //上电指令
#define SET_PLAY 0xE0 //指定放音指令
#define PLAY 0xF0 //当前放音指令
#define SET_REC 0xA0 //指定录音指令
#define REC 0xB0 //当前录音指令
#define SET_MC 0xE1 //指定快进指令
#define MC 0xF1 //快进执行指令
#define STOP 0x30 //停止当前 *** 作
#define STOP_WRDN 0xF1 //停止当前 *** 作并掉电
#define RINT 0x30 //读状态:OVF和EOM
//=========ISD4004--c51接口定义=================
sbit ISD_SS = P0^0//片选
sbit ISD_MOSI = P0^1//数据输入
sbit ISD_SCLK = P0^2//ISD4004 时钟
sbit ISD_INT = P3^3//溢出中断
sbit ISD_RAC = P3^2//行地址时钟
sbit ISD_MISO = P3^6//数据输出
//==========按键定义==========================
sbit K1 = P1^0 //录音键
sbit K2 = P1^1 //放音键
//==========BEEP开关定义======================
#define Beep_ON (P0&=0x7f) //蜂鸣器开
#define Beep_OFF (P0|=0x80) //蜂鸣器关
//==========ISD4004函数定义===================
void ISD_SPI_Send8( uchar isdx8 )//spi 串行发送子程序,8位数据,从低到高
void ISD_SPI_Send16( uint isdx16 )//spi 串行发送子程序,16位数据.从低到高
uint ISD_SPI_Radd(void) //读取标行地址
void ISD_Stop(void) //发送 stop 指令
void ISD_PowerUp(void) //发送上电指令,并延迟 50ms
void ISD_PowerDown(void) //发送掉电指令,并延迟 50ms
void ISD_Play(void) //发送放音指令,并延迟 50ms
void ISD_SetPlay(uint add) //发送指定放音指令,并延迟 50ms
void ISD_Rec(void)//发送录音指令,并延迟 50ms
void ISD_SetRec(uint add) //发送指定录音指令,并延迟 50ms
uchar ISD_Chk_Isdovf(void)
void PLAY_now(uchar add_sect) //按指定地址开始放音
void REC_now(uchar add_sect) //按指定地址开始录音
//========延时函数===========================
void Delay1Ms(uchar t) //延时t*1毫秒
void Delay()
////////////////////////////////////////////////////////////////////////
//程序开始 //
////////////////////////////////////////////////////////////////////////
/*******************************主程序*********************************/
main ()
{
uchar i,j
while (1)
{
//=========================K1录音键================================
if(K1==0) //K1键按下。录音
{
REC_now(i++) //录第一段
if(i>5) i = 0
while(K1==0) //等待录音完毕
{
if (ISD_INT==0) //如果芯片OVF溢出,进行 蜂鸣器 提示,如果取消录音(松开 AN 键)则停止录音,芯片复 位
{
while(K1==0)
{
Beep_ON
Delay1Ms(250)
Beep_OFF
Delay1Ms(250)
}
}
}
ISD_Stop() //发送停止命令
ISD_PowerDown()
}
//============================K2放音键================================
if(K2==0)
{
PLAY_now(j++)//放第一段
if(j>5) j = 0
while(ISD_INT==1)//等待一段放音完毕的 EOM 中断信号
ISD_Stop()//放音完毕,发送 stop 指令
ISD_PowerDown()
}
}
}
/******************************************************************
名称:PLAY_now(uchar add_sect)
功能:按指定地址段开始播放
指令:
调用:无
返回:无
/*****************************************************************/
void PLAY_now(uchar add_sect)
{
ISD_PowerUp()//ISD 上电
Delay1Ms(50)
switch (add_sect) //发送 setplay 指令,从 0x0000 地址开始放
{
case 1: ISD_SetPlay(ISD_ADDS1)break//发送地址的 SetRec 指令
case 2: ISD_SetPlay(ISD_ADDS2)break//发送地址的 SetRec 指令
case 3: ISD_SetPlay(ISD_ADDS3)break//发送地址的 SetRec 指令
case 4: ISD_SetPlay(ISD_ADDS4)break//发送地址的 SetRec 指令
case 5: ISD_SetPlay(ISD_ADDS5)break//发送地址的 SetRec 指令
//case 6:……
}
ISD_Play()//发送放音指令
}
/******************************************************************
名称:REC_now(uchar add_sect)
功能:按指定地址段开始录音
指令:
调用:无
返回:无
/******************************************************************/
void REC_now(uchar add_sect)
{
ISD_PowerUp()//ISD 上电
Delay1Ms(50)//延迟录音
ISD_PowerUp()//ISD 上电
Delay1Ms(100)//延迟录音
switch (add_sect)
{
case 1: ISD_SetRec(ISD_ADDS1)break//发送地址的 SetRec 指令
case 2: ISD_SetRec(ISD_ADDS2)break//发送地址的 SetRec 指令
case 3: ISD_SetRec(ISD_ADDS3)break//发送地址的 SetRec 指令
case 4: ISD_SetRec(ISD_ADDS4)break//发送地址的 SetRec 指令
case 5: ISD_SetRec(ISD_ADDS5)break//发送地址的 SetRec 指令
//case 6:……
}
ISD_Rec()//发送 rec 指令
}
/******************************************************************
名称:ISD_SPI_Send8(uchar isdx)
功能:spi 串行发送子程序,8 位数据
指令:
调用:无
返回:无
/******************************************************************/
void ISD_SPI_Send8( uchar isdx8 )
{
uchar i
ISD_SS = 0 //选中ISD4004
ISD_SCLK = 0
for(i=0i<8i++)//先发低位再发高位,依次发送。
{
if ((isdx8 &0x01) == 1) //发送最低位
ISD_MOSI = 1
else
ISD_MOSI = 0
isdx8 >>= 1 //右移一位
ISD_SCLK = 1 //时钟下降沿发送
ISD_SCLK = 0
}
}
/******************************************************************
名称:ISD_SPI_Send16(uint isdx16)
功能:spi 串行发送子程序,16位数据
指令:
调用:无
返回:无
/******************************************************************/
void ISD_SPI_Send16( uint isdx16 )
{
uchar i
ISD_SS = 0 //选中ISD4004
ISD_SCLK = 0
for(i=0i<16i++) //先发低位再发高位,依次发送。
{
if ((isdx16&0x0001)==1) //发送最低位
ISD_MOSI = 1
else
ISD_MOSI = 0
isdx16 = isdx16 >>1 //右移一位
ISD_SCLK=1 //时钟下降沿发送
ISD_SCLK=0
}
}
/******************************************************************
名称:ISD_SPI_Radd(void)
功能:读取16位行地址
指令:
调用:无
返回:无
/******************************************************************/
uint ISD_SPI_Radd(void)
{
uchar i
uint addsig
ISD_SS = 0 //选中ISD4004
ISD_SCLK = 0
//==============读16位地址================
for(i=0i<16i++) //读行地址
{
ISD_SCLK = 1 //时钟下降沿数据移出ISD
ISD_SCLK = 0
if (ISD_MISO == 1)
addsig |= 0x8000
if (i<15) addsig >>= 1//最先读出的是地址的低位,所以要左移,最后一次地址不用左移,否则地址溢出
}
ISD_Stop()//发送 stop 指令
ISD_SS = 1//关闭 spi 通信端
return addsig//返回地址值
}
/******************************************************************
名称:ISD_Stop(void)
功能:发送 stop 指令
指令:ISD_SPI_Send8(uchar isdx8)
调用:无
返回:无
/******************************************************************/
void ISD_Stop(void)
{
//ISD_SS = 0
ISD_SPI_Send8(STOP)
ISD_SS = 1//关闭片选
}
/******************************************************************
名称:ISD_PowerUp(void)
功能:发送上电指令,并延迟 50ms
指令:ISD_SPI_Send8(uchar isdx8)
调用:无
返回:无
/******************************************************************/
void ISD_PowerUp(void)
{
ISD_SS = 0//选中ISD4004
ISD_SPI_Send8(POWER_UP)
ISD_SS = 1
}
/******************************************************************
名称:ISD_PowerDown(void)
功能:发送掉电指令,并延迟 50ms
指令:ISD_SPI_Send8(uchar isdx8)
调用:无
返回:无
/******************************************************************/
void ISD_PowerDown(void)
{
ISD_SS = 0
ISD_SPI_Send8(STOP_WRDN)
ISD_SS = 1
}
/******************************************************************
名称:ISD_Play(void)
功能:发送play指令,并延迟 50ms
指令:ISD_SPI_Send8(uchar isdx8)
调用:无
返回:无
/******************************************************************/
void ISD_Play(void)
{
ISD_SS = 0
ISD_SPI_Send8(PLAY)
ISD_SS = 1
}
/******************************************************************
名称:ISD_Rec(void)
功能:发送rec录音指令,并延迟 50ms
指令:ISD_SPI_Send8(uchar isdx8)
调用:无
返回:无
/******************************************************************/
void ISD_Rec(void)
{
ISD_SS = 0
ISD_SPI_Send8(REC)
ISD_SS = 1
}
/******************************************************************
名称:ISD_SetPlay(uint add)
功能:发送setplay指令,并延迟 50ms
指令:ISD_SPI_Send8(uchar isdx8)
ISD_SPI_Send16(uint isdx16)
调用:无
返回:无
/******************************************************************/
void ISD_SetPlay(uint add)
{
Delay1Ms(1)
ISD_SPI_Send16(add) //发送放音起始地址
ISD_SPI_Send8(SET_PLAY)//发送 setplay 指令字节
ISD_SS = 1
}
/******************************************************************
名称:ISD_SetRec(uint add)
功能:发送setrec指令,并延迟 50ms
指令:ISD_SPI_Send8(uchar isdx8)
ISD_SPI_Send16(uint isdx16)
调用:无
返回:无
/******************************************************************/
void ISD_SetRec(uint add)
{
Delay1Ms(1)
ISD_SPI_Send16(add)//发送录音起始地址
ISD_SPI_Send8(SET_REC)//发送 setrec 指令字节
ISD_SS = 1
}
//************************************
//检查芯片是否溢出(读 OVF,并返回 OVF 值)
//************************************
/*uchar ISD_Chk_Isdovf(void)
{
ISD_SS=0
ISD_SCLK=0
ISD_SCLK=1
ISD_SCLK=0
if (ISD_MISO==1)
{
ISD_SCLK=0
ISD_SS =1//关闭 spi 通信端
ISD_Stop()//发送 stop 指令
return 1//OVF 为 1,返回 1
}
else
{
ISD_SCLK=0
ISD_SS =1//关闭 spi 通信端
ISD_Stop()//发送 stop 指令
return 0//OVF 为 0,返回 0
}
}*/
/*=========================================================================
名称: void Delay1Ms(uchar t)
功能:延时0.1ms
参数:t,最大255
调用: 无
返回:无
=========================================================================*/
void Delay1Ms(uchar t)
{
uchar i
for (t>0t--)
{
for (i=0i<150i++)
{
_nop_()_nop_()_nop_()_nop_()_nop_()
_nop_()_nop_()_nop_()_nop_()_nop_()
}
}
}
//========================================
void Delay()
{
uchar i
uint d=5000
while (d--)
{
i=255
while (i--)
}
}
一个是人工,就是司机自己按,报站名或者是自动的,如下
1 嵌入式公交自动报站系统的原理及特点
1.1 基于GPS公交自动报站系统的原理概述
本文提出的新型公交车自动报站系统的基本原理如图1所示。通过GPS接收机接收GPS工作卫星的导航信息,从而解算出车辆目前的经、纬度等信息;根据GPS定位数据计算出公交车的实时坐标,将其与站点坐标相比较,当公交车驶入站点一定距离范围内时,不用人工干预,系统自动报站。将位置信息与数据库中电子矢量地图进行匹配,根据公交车位置的不同,LCD显示屏上显示不同的公益信息、广告信息和景点信息等。在离站、到站和拐弯点阈值范围内语音提示的同时,在显示屏上显示同类信息,给乘客一种全方位的提示与服务。
1.2 GPS的定位原理
本装置的定位系统使用GPS接收机进行自主定位,GPS接收模块接收GPS卫星发送的定位数据,将GPS信号的数据流提取出来,经过简单的字符串 *** 作就可以分别找出GPS信号中的经度、纬度以及相应的格林威治时间(该时间加上8小时即为我国标准时)等定位信息。在实际开发中,GPS接收机根据从三颗以上卫星发来的数据计算出自身所处的位置,完成定位。
GPS定位的基本原理是根据高速运动的卫星瞬间位置作为已知的起算数据,采用空间距离后方交汇的方法,确定待测点的位置。如图2所示,假设t时刻在地面待测点上安置GPS接收机,可以测定GPS信号到达接收机的时间△t,再加上接收机所接收到的卫星星历等其他数据可以确定以下四个方程式:
由以上四个方程即可解算出待测点的坐标x、y、z及钟差;GPS模块再由此得到经纬度、时间等信息;最后将这些信息通过串口以GPS信息的形式发送出去。
1.3 GPS信息格式
通常GPS模块支持两种格式:二进制消息格式和NMEA-0183 ASCII消息格式。前者的通信协议为 9600b/s、无校验、8位数据位、1位停止位;后者的通信协议为4800b/s、无校验、8位数据位、1位停止位。由于NMEA-0183 ASCII格式直观、易于识别及应用,因此本设备采用ASCII格式。
系统接收到的GPS数据主要由帧头、帧尾和帧内数据组成。根据数据帧的不同,帧头也不相同,主要有$GPGGA、$GPGSA、$GPGSV以及$GPRMC等。这里选用推荐的$GPRMC。各类数据帧分别包含了不同的信息,在此列举出$GPRMC的各项含义:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,*hh
<1>当前位置的格林威治时间,格式为hhmmss。
<2>状态,A为有效位置,V为非有效接收警告,即当前天线视野上方的卫星个数少于3颗。
<3>纬度,格式为ddmm.mmmm。
<4>标明南北半球,N为北半球、S为南半球。
<5>径度,格式为dddmm.mmmm。
<6>标明东西半球,E为东半球、W为西半球。
<7>地面上的速度,范围为000.0节~999.9节(1节=1.852km/h)。
<8>方位角,范围为000.0度~359.9度。
<9>日期,格式为ddmmyy。
<10>地磁变化,从000.0度~180.0度。
<11>地磁变化方向,为E或W。
由于帧内各数据段由逗号分割,因此在处理缓存数据时一般通过搜寻ASCII码“$”来判断是否是帧头。在对帧头的类别进行识别后,再通过对所经历逗号个数的计数判断出当前正在处理的是哪一种定位导航参数,并做出相应处理。
2 嵌入式智能公交系统设计
车载设备安装于公交车上,其工作环境比较恶劣,对设备的结构也有一定的要求,本系统采用工作稳定可靠、抗干扰能力强的嵌入式系统。嵌入式系统固化于存储器中,其可靠性高、成本低、体积小、功耗低。嵌入式系统有着广泛的应用领域,在车辆与交通工程中的应用是其中一个重要的方面。将嵌入式设备作为车载终端应用于智能公交系统,使车载终端设备具有更高的智能性、稳定性和扩展性,从而建立起全方位、实时准确、高效的智能交通系统。
本系统采用先进的卫星定位技术与语音合成技术相结合的方式,改变了传统公交车语音报站器必须有司机 *** 控才能工作的落后方式,进站、出站自动播报站名及服务用语,准确、及时、不需要人工介入,实现了公交车报站器的完全智能化。本装置主要特点为:
(1)采用GPS卫星定位技术,自动、准确地播报站名、服务用语、广告等。
(2)站名及有关事项可以在计算机上形成电子文件,通过串口下载到报站器中,方便快捷。
(3)与显示屏直接连接,同步显示报站信息、广告等。
(4)可存储多条线路,方便公交车临时更换运营线路。
GPS公交自动报站系统包含硬件和软件两部分。硬件以ARM9S3c2410x处理器为核心,配置存储器、I/O设备、通信模块等必要的外设;软件以嵌入式Linux *** 作系统为核心,向上提供应用编程接口API,向下屏蔽具体硬件特性的板级支持包BSP。嵌入式系统中,软件和硬件紧密配合,协调工作,共同完成系统预定的功能。
2.1 系统硬件设计
嵌入式GPS公交自动报站系统按功能模块可分为:GPS模块、Flash/RAM、JTAG口/串行接口/USB口、音频设备/扬声器、LCD触摸屏及核心处理器S3c2410x。系统硬件框图如图3所示。
这个其实很容易理解的。最早的报站是司机控制的,也就是像录音机一样,司机按下对应站点按钮,就会播放一段事先录好的语音,于是就实现了语音报站功能。而目前大多数地区使用的是
智能公交报站器,所有的播报都是智能机自动完成,完全不需要司机干预,司机只需要在特定情况下按下响应的按键即可,例如注意安全、请让座,按下去就会播放有相对应的提示语音。而进站出站完全是自动播报的。
自动播报的原理很简单,就是利用了GPS系统。例如我们使用导航的时候,导航可以显示我们的移动轨迹,GPS对车辆实时定位,导航软件告诉我们现在所处何地, 应该怎么走,这些都是GPS的功劳。而车载报站系统也是一个原理,利用GPS信号实时对车辆实时定位,在经纬度方向角与设定值相符时,就会触发播报器播报站点信息。当然,这需要提前采集各个站点的数据,例如一条运行线路有二十个站点,那么就需要程序员在站点采集相关的经纬度方向角信息,整条线路信息采集完毕,导入系统后在实验车上调试一次,调试OK后就可以导入响应的语音提示信息即可,当车辆运行到预设经纬度时自然就会播报进站等信息。
关于公交车的报站,据我自己的观察,是分为两个阶段,其中一开始的时候是比较原始的一种,那就是司机的人工按键报站:每过一个站,司机就按下一个数字,每个不同的数字对应的就是不同的站,一般会提前输入到报站的机器里面,然后司机记下不同的数字代表的站是哪一个,在准备到站的时候按下去就报站了。
现代的公交车和公交站台
到现在的话公交车报站基本上都是自动化的报站了,就是说司机只需要按照相应的驾驶 汽车 即可, 汽车 上面的GPS定位系统会根据 汽车 行驶的位置在到站之前就激活语音播报系统,从而进行准确的报站。并且现在的公交车的定位是实时定位的,可以监控到车辆的位置,并且这些位置还可以反映到车辆的公交站上面。
某款智能公交终端
我见现在还有一些新建的公交站台就有关于经停的所有公交车的位置信息,距离现在的车站还有多少站等的位置信息,还有到站时间的大约预估的时间,通过这些方法可以让等公交车也变得时间更加可控,可以规划自己的行程,如果说等待的时间过长的话就可以选择其他的交通工具。
还记得以前读书的时候等公交车去上学,需要比车程的时间多预留半个小时的等待公交车的时间,因为公交车到达的时间经常不确定,有时候等待的时间超过半个小时的话就会导致上学迟到,而现在的话可以看自己想坐的车次离自己这里有多远了,如果到达的时间过远的话就可以选择乘坐出租车去学校了。
公交站台智能显示器
要说技术难度的话其实这个都很简答的,我们现在的手机导航都的定位都非常的精准,在经过路口和一些特殊地标的时候都会进行语音提示,而公交车只需要设置好路线,并且设置好沿途的途经地,在到达途经地的时候就激活预先设置好的语音文件,就可以非常准确的进行播报了。
随着城市建设的越来越好,公交车也变得十分便利,不再像之前那样没有空调还十分拥挤,就拿小柒所在的城市,一元钱你可以绕着城市随便坐,冬暖夏凉,有的车上还有USB充电口,真是十分便利,如果你不赶时间的话,公交车绝对是一个最好的出行方式。但是公交车上的自动报站系统是怎么运作的,又是怎么判断 汽车 当前所在的位置呢,今天小柒就好好跟大家说一下。
第一种:人工控制
这个系统是在公交车出现的早期,司机拥有一个自动报站装置,里面装有提前录好的到站点,只需要到站的时候,司机摁一下就会自动播放语音功能了,这个情况完全需要司机的 *** 作。
第二种,GPS控制
这种报站系统在很多城市都常见,通过GPS接收机接收GPS工作卫星的导航信息,从而解算出车辆目前的经、纬度等信息;根据GPS定位数据计算出公交车的实时坐标,将其与站点坐标相比较,当公交车驶入站点一定距离范围内时,不用人工干预,系统自动报站。将位置信息与数据库中电子矢量地图进行匹配,根据公交车位置的不同,LCD显示屏上显示不同的公益信息、广告信息和景点信息等。在离站、到站和拐弯点阈值范围内语音提示的同时,在显示屏上显示同类信息,给乘客一种全方位的提示与服务。方便乘客查询 汽车 到站时间,以便于确定是否选择此类交通工具,是 科技 化提高的一种表现方式。
由此可以看出, 科技 化日益发展的今天,智能系统已经存在于我们生活的方方面面,给我们的生活提供了很大便利。
经常坐公交的朋友们可能会注意,以前报站都是司机师傅手动按钮报站的,而现在只要是车辆接近站点,车上的语音系统就会自动的报站,完全不需要人工的 *** 作,那么这种功能是怎样实现的呢?
简单的来说,自动包装是依靠GPS定位的技术,目前公交车上的车载终端,基本上都是手动和自动都可以,如果想要实现自动报站,就要提前的踩点,也就是实地采集一条线路上所有的站点,纬度和方向等数据信息。然后把数据导入车载终端,厂家的软件中进行编辑和调整,同时倒入已经准备好的语言文件,比如站名,广告提示用语等等,这样就做好了一个报站文件。
然而为了提高报站的精确度,做好的报站文件需要导入一个车载终端里面,在实际的线路上跑一趟,验证报站是否准确。如果不准确的话就要调整,一直调整到准确为止,然后再倒入所有的车里面正式使用。
最早是人工的,现在好像是gps定位了,到了会自动报
公交车主要判断人民群众出行方便,浦东2O路锦绣东车站往南车站应该北移到朱家宅那里,乘客下车能找到回家的车站。请有关方实地看看吧!往北车站下来,回去的车站找不到。
北斗定位,就这么简单。
定位系统呗,进入车站范围自动播报了,就像考驾照的考试车一样。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)