最新日志

发表于:2008-4-30 15:08:49
标签:MSP430  升级  

0

MSP430程序升级方式探讨

  对MSP430系列单片机进行编程的方式有以下三种:利用JTAG接口,利用BSL固件和利用用户自定义的升级固件。由于利用自定义升级固件进行程序升级的方式比较灵活,并且用途广泛,本文将对它作重点介绍。

1. 利用JTAG接口
         MSP430系列的单片机都集成了JTAG接口,该接口实现了遵循IEEESTD1149.1规定的测试访问端口状态机(TAP Controller)。它使用一个四线串行接口(TEST用于引脚较少的芯片)。数据或指令从TDI(测试数据输入)移入;串行数据从 TDO(测试数据输出)移出; TCK(测试时钟)作为时钟信号输入;TMS(测试模式选择)信号控制TAP 控制器的状态。利用该接口可以移入指令和数据,从而控制目标芯片的地址线和数据线,达到读写目标芯片FLASH和仿真调试的目的[1]。另外TI现在推出了新型的调试接口—SPY-BI-WIRE,它采用两线制,其中一根为数据线(双向),一根为时钟线。
利用该接口的优点是不需要设计额外的电路和程序,采用仿真器即可下载程序。缺点是一旦用户为了保证代码的安全,烧断了JTAG的熔丝,那么就永久性的破坏了该接口,也就不能再使用该接口了。

2.利用BSL接口
         BSL是 Bootstrap Loader的缩写,中文名称是程序装载器。它实质是固化在芯片中的一段通信程序(占用0C00h-1000h的地址空间),利用它可实现对FLASH的擦除和读写。由于其是固化在芯片中的,因此不必担心其被更改或丢失。

         该接口使用5根线:GND,TX(P1.1/P1.0),RX(P2.2/P1.1),RST,TCK(TEST),在RST和TCK(TEST)加特定的电平时序信号,即可启动BSL程序,从而实现与目标芯片的通信。通信的字符格式是8个数据位,一个停止位和一个偶校验位。起始波特率为9600bps(BSL 1.6版本可更改波特率到38400bps)。BSL协议要求首先接受一个80h字符用于同步时钟,然后发送应答字符90h。接着接受8个字符,并根据命令跳转到相应的处理例程。BSL程序的C语言描述如下
Void main()
{
Byte B,bArray[8];
LOCKSTATE = LOCK;
InitPorts();
While(1)
{
      B="ReceiveSyncByte"();
      SyncTimer(B);
SendAck();
For( I = 0 ; I < 8 ;i++) bArray = ReceiveByte();
Switch(bArray)
{
0x12: //写FLASH
For(I = 0 ; i<bArray[7] ; i++)
{
      B="ReceiveByte"();
If(LOCKSTATE ==UNLOCK) WriteByte(B);
}
Break;
0x10://接收口令
Receive32Byte();
If(PassWordCorrect) LOCKSTATE = UNLOCK;
      Break;
      0x18..0xn:
If(PassWordCorrect) DoTask();
      }
      If(NoError) SendNak();
else
      If(TxData) SendData();
else
      SendAck();
}
其实现细节可能因版本不同而变化。若用户想利用它来实现程序升级,可参考文[2][3]。 利用BSL程序进行升级的优点是节省代码空间,用户不需要实现自己的升级固件,而且现在已经有很多现成的BSL升级工具;缺点是需预留BSL接口,并且需要现场接线。

3.利用自定义升级固件
         MSP430系列单片机的FLASH存储器模块是一个可独立操作的物理存储单元。全部模块安排在同一个线性地址空间中,存储器被分为多个512字节的段(信息段大小为128/64字节)。各段可单独擦除,并且在正常工作电压下程序可对FLASH进行擦写操作,因此特别适合在线程序升级(in-system program)。

         自定义升级固件就是在程序中内置一段用于升级应用程序的代码,即可利用现有通信接口进行远程代码的升级。其实现原理是在目标芯片中放置2段代码:一段为应用程序,一段为升级程序。两者的地址段不重叠,这样就可以利用升级程序擦除应用程序并写入新的代码。

3.1引导程序
         复位后先进入引导程序,由它来决定进入升级程序或应用程序。引导程序的意义在于当应用程序不存在或错误时能直接进入升级程序,从而保证升级不成功可进行再次升级。
引导程序的描述如下
Void main()
{
While(1)
{
      If(ResetVectorValid()) Application();
      Updata();
}
}
其中的ResetVectorValid()函数用于检测应用程序是否存在或是否有效。实现可以是检测EnterApplication的入口地址是否合法,一种简单的实现是
#define ResetVectorValid() (ResetVector !=FFFF)
其中ResetVector为应用程序的入口地址,该地址通常放在一个固定的地址中,升级程序后修改该入口地址。Application() 为应用程序,它若正常执行不会返回 , 只有在接受到升级指令后才返回。可在Application()中使用Return语句进入升级程序。

         Updata()为升级程序,其入口处必须加检测指令,以确认是正常进入升级程序。进入升级程序后,通信端应先发送擦除指令,擦除原有代码,然后发送升级代码更新FLASH。若是具有外部扩展存储器或用户程序较小,可先接收整个程序段,若校验正确再写入,这样可靠性会更高。
这里有个策略就是最先擦除包含ResetVector的块,最后写入ResetVector的值,这样可以尽量保证不会进入不完整的应用程序。

3.2应用程序的编写
         应用程序的编写没有什么大的变化,需要在通信协议中加入自定义的一个升级命令,用于进入升级程序。另外需更改链接文件(*.XCL),指定应用程序的地址范围,如下以应用程序地址范围为2500-F7DC为例(用//注释掉的为默认的设置)
// Code
//-Z(CODE)CSTART=2500-FFDF
//-Z(CODE)CODE=2500-FFDF
-Z(CODE)CSTART=2500-F7DF
-Z(CODE)CODE =2500-F7DF
// Constant data
//-Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=2500-FFDF
-Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=2500-F7DF
// Interrupt vectors
//-Z(CONST)INTVEC=FFE0-FFFF
-Z(CONST)INTVEC=F7E0-F7FF
修改完毕后将该文件添加到工程。编译后的代码即可作为升级代码。

3.3升级程序的编写
         新建一个工程,按如上的方法将升级代码定位到与应用程序不重叠的区域,如F800-FFFF,此时不修改
-Z(CONST)INTVEC=FFE0-FFFF
在升级程序中将除复位中断外的所有中断映射到应用程序中,一种办法是嵌入汇编,采用汇编的定位指令ORG;或者写15个中断影射函数,如下
//重新映射中断向量地址
#pragma vector="0x0"
      __interrupt void intvec_0(void)
{
      asm("br & 0F7E0h"); //假设F7E0中存放中断15的地址
}

另外也可以采用动态确定中断入口地址的方法,即将中断向量地址放入约定好的RAM中,如下
__no_init void (*intvec1[16])() @ 0x200; //定义指向函数指针的数组,用于映射新的中断向量
//重新映射中断向量地址
#pragma vector="0x0" //
__interrupt void intvec_0(void)
{
      asm("push R15");
      asm("mov #0x200,R15");
      asm("call @R15");
      asm("pop R15");
}
然后在应用程序中进行中断向量的映射,如
intvec1[TIMERA0_VECTOR/2]=Timer_A_0;
即在TIMERA0中断时执行Timer_A_0()函数。这样做的优点是可以在运行时动态决定中断函数的入口,即如高级语言中的虚函数(Virtual Function)。
当这两个函数块编写完毕后就可以进行工程测试了。

3.4应用程序与升级程序同时完成
         也许您还希望两个函数在一个工程里完成。这时除了需要修改链接文件外,还需要注意以下几点:
(1)将升级程序的所有函数定位到升级程序空间,即在函数前面加定位指令
#pragma location="UPDATECODE" // UPDATECODE为升级程序所在段的名称

(2)修改函数返回调用的例程。当函数返回时会调用弹出寄存器的默认例程,而这些例程可能并不在升级程序的地址空间内。一种解决方法是利用编译环境生成的LST文件(汇编代码),逐个修改函数返回时调用的弹出寄存器例程,这样就可以保证两者代码独立。这样做的缺点是每次更改C语言代码后,就要重新修改汇编代码,比较繁琐。另一种方法是考虑到升级程序所做的就是接受和发送数据,一般不需要使用中断。这样就可以在升级函数前面加入__monitor 编译指令,指明该函数为原子操作。这类函数入口处先压入SR并禁止中断,返回时使用RETI返回,此时编译器并不调用例程弹出保存的寄存器,而是根据进栈情况逐个弹出寄存器。

(3)更改SWITCH语句。使用SWITCH语句时编译器也会产生默认例程调用,很难屏蔽掉,故只有将SWITCH修改为多个判断语句。

点击此处查看原文 >>

系统分类: 单片机   |    用户分类:    |    来源: 转贴

评论(0) | 阅读(46)
发表于:2008-4-15 11:43:07
标签:msp430  ds1302  

0

MSP430读写DS1302程序(已测试)

/**********************************************************/
//MSP430高级实验开发组件 - DS1302时钟芯片
//硬件连接:
////       MSP430 MCU                   DS1302
////   ------------------         ------------------
////   |      P15       | ------> |     SCLK       |
////   |      P17       | ------> |      RST       |
////   |      P16       | ------> |      SDI       |
////   ------------------         ------------------
////       MSP430 MCU                   KEYS
////   ------------------         ------------------
////   ------------------         ------------------ 
//当前演示程序功能描述:
////
/*********************************************************/

#include <msp430x41x.h>

#define DS1302_DIR  P1DIR
#define DS1302_IN    P1IN
#define DS1302_OUT  P1OUT

#define DS1302_RST  BIT7
#define DS1302_SCLK  BIT5
#define DS1302_SDI  BIT6  //定义MSP320的端口

#define DS1302_RST_LO  DS1302_OUT &= ~DS1302_RST
#define DS1302_RST_HI  DS1302_OUT |= DS1302_RST
#define DS1302_SCLK_LO  DS1302_OUT &= ~DS1302_SCLK
#define DS1302_SCLK_HI  DS1302_OUT |= DS1302_SCLK
#define DS1302_SDI_LO  DS1302_OUT &= ~DS1302_SDI
#define DS1302_SDI_HI  DS1302_OUT |= DS1302_SDI

void DS1302_Delay(unsigned int dtime);
void DS1302_Reset(void);
void DS1302_WriteOneByte(unsigned char w_dat);
void DS1302_WriteData(unsigned char addr,unsigned char w_dat);
void DS1302_SettingData(void);
void DS1302_GetData(unsigned char *str);
unsigned char DS1302_ReadOneByte(void);
unsigned char DS1302_ReadData(unsigned char addr);

unsigned char Setting_Time[7]={ //bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
 0x08,    //--------十位-------|-------个位--------|年份(当前07年)
 0x01,    //                        |-----个位-----|星期(当前周日)
 0x04,    //              |十位|-------个位--------|月份(当前07月)
 0x15,    //         |--十位---|-------个位--------|日期(当前01号)
 0x11,    //-12H|    |--十位---|-------个位--------|小时(当前18点)
 0x09,    //    |-----十位-----|-------个位--------|分钟(当前20分)
 0x21    //    |-----十位-----|-------个位--------|秒钟(当前30秒)
};
unsigned char ReadingData[7];  //读出来的数据,同SettingData定义与格式

/****************************
void main(void) {
 WDTCTL = WDTPW + WDTHOLD;
 DS1302_Reset();
 //DS1302_SettingData();
 while(1){
  DS1302_GetData(ReadingData);
  _NOP();
 };
}
****************************/

//延时函数
void DS1302_Delay(unsigned int dtime) {
 unsigned int temp;
 for(temp=0;temp<dtime;temp++);
}

//DS1302复位
void DS1302_Reset(void) {
 DS1302_DIR |= (DS1302_RST + DS1302_SCLK);
 DS1302_SCLK_LO;
 DS1302_RST_LO;
 DS1302_Delay(10);
 DS1302_SCLK_HI;
}

//向DS1302写入一个字节
void DS1302_WriteOneByte(unsigned char w_dat) {
 unsigned char temp;
 
 DS1302_RST_HI;
 DS1302_DIR |= DS1302_SDI;
 
 for(temp=8;temp>0;temp--) {
  DS1302_SDI_LO;
  if(w_dat&BIT0) DS1302_SDI_HI;
  DS1302_SCLK_LO;
  DS1302_Delay(10);
  DS1302_SCLK_HI;
  DS1302_Delay(10);
  w_dat >>=1;
 }
}

//从DS1302中读取一个字节
unsigned char DS1302_ReadOneByte(void) {
 unsigned char temp,rdata;
 rdata = 0x00;
 
 DS1302_RST_HI;
 DS1302_DIR &= ~DS1302_SDI;
 
 for(temp=0;temp<7;temp++){
  DS1302_SCLK_HI;
  DS1302_Delay(10);
  DS1302_SCLK_LO;
  DS1302_Delay(10);
  if((DS1302_IN&DS1302_SDI)==DS1302_SDI)
   rdata |= BIT7;
  rdata >>= 1;
 }
 
 return(rdata);
}

//向DS1302中写入地址后写入数据
void DS1302_WriteData(unsigned char addr,unsigned char w_dat) {
 DS1302_RST_LO;
 DS1302_SCLK_LO;
 DS1302_RST_HI;
 
 DS1302_WriteOneByte(addr);  //写入地址
 DS1302_WriteOneByte(w_dat);  //写入数据
 
 DS1302_SCLK_HI;
 DS1302_RST_LO;
}

//向DS1302写入地址后,从DS1302中读取数据
unsigned char DS1302_ReadData(unsigned char addr) {
 unsigned char r_dat;
 DS1302_RST_LO;
 DS1302_SCLK_LO;
 DS1302_RST_HI;
 
 DS1302_WriteOneByte(addr);  //写入地址
 r_dat = DS1302_ReadOneByte();  //读出数据
 
 DS1302_SCLK_LO;
 DS1302_RST_LO;
 
 return(r_dat);
}

//按照SettingData的设置设置DS1302的时间
void DS1302_SettingData(void) {
 unsigned char temp;
 unsigned char addr = 0x8C;
 
 DS1302_WriteData(0x8E,0x00);  //写入控制命令,禁用写保护

 for(temp=0;temp<7;temp++) {
  DS1302_WriteData(addr,Setting_Time[temp]);
  addr -= 2;
 }
 
 DS1302_WriteData(0x8E,0x80);  //写入控制命令,启用写保护
}

//读取DS1302时间到ReadingData中
void DS1302_GetData(unsigned char *str) {
 unsigned char temp;
 unsigned char addr = 0x8D;

 for(temp=0;temp<7;temp++) {
  str[temp] = DS1302_ReadData(addr);//年
  addr -= 2;
 }
}

void main(void)
{
  unsigned char time1[7];
  WDTCTL = WDTPW + WDTHOLD;             // Stop WDT

  BTCTL = BTFRFQ1+BT_ADLY_500;  ;           // ACLK/(256*16)
  
  DS1302_Reset();
  while(1)
  {
    DS1302_GetData(time1);
    DS1302_SettingData();
    DS1302_GetData(time1);
  }
}
点击看大图

点击此处查看原文 >>

系统分类: 软件开发   |    用户分类:    |    来源: 整理

评论(0) | 阅读(128)
发表于:2008-3-26 9:24:51
标签:外汇  

0

不断增长的外汇储备,是中国政府的心病

很多人想得很简单,他们认为,如果中国政府放宽外汇管制,让商人通过自由兑换,把美金换成人民币不就可以了。这种想法的确很好,如果人民币与外币能够自由兑换,中国政府不但可以白赚好几百亿元,并且每年通过发钞还可以再赚一笔。因为,一旦人民币成为硬通货,很多外国人的口袋中必然会沉淀一定数量的人民币,这些人民币就像每年都要留种子一样,这些种子是永远不会消失的,它与一张废纸没有多大区别。但是,放宽外汇管制将会引起很多企业或个人大量走私,以及很多贪官和私人将会进行资产转移。

企业走私一直存在,不过企业走私比较隐蔽,比如倒卖批文实际上就是走私,就是官商勾结在一起走私。90年前、后,是中国倒卖批文最严重的时期,什么设备以及生产线的批文都可以倒卖,大家比较熟识的有汽车、电视机显像管等。现在看起来好了一些,好像倒卖批文的现象少了,但政府审批的腐败事件却增多了。根据国家信息中心经济预测部相关报道,在新双轨制下政府官员每年的灰色收入高达46,000亿。

未来几年,只要国家外汇管理的政策一松动,就会象九十年代初一样,国外大量的生产设备以及产品,就会通过倒卖批文和走私进来。你看这几年的汽车生产企业,不也是要经过国家相关部门审批才能引进吗?但在短短的几年内,中国就诞生了118家整车生产企业,进口汽车生产线370多条,数量几乎等于美、日、欧所有汽车厂商数之和,但是全国汽车的年产量还不及一家国外大汽车公司的产量,年产量达万辆以上的只有21家。

今年3月18日上午,国务院总理温家宝会见中外记者时指出:“今年恐怕是中国经济最困难的一年。”温家宝在记者会上坦言:“由于政治体制的缺陷和财政体制的漏洞,中国的财政透明度至今都让人扑朔迷离。大面积的官场腐败现象与此都有直接关系,社会的公平正义遭到破坏也与此因果相连。从公开的数据看,07年的财政收入为5.1万亿元,而从其它渠道暴露的数据则是9万亿元,其中的巨大差额却不见踪影,不见说法,的确让人感到惊心动魄!”

试想,如果从现在起,中国政府完全放宽外汇管制,那么上述被贪官黑掉的3.9亿元人民币是不是更容易转移出国。还有,前些年中国海关经常收到一批又批无人领取的进口货物,他们都是以进口设备的形式进来的,待海关同意把外汇汇出之后,货物就再也没有人来领取,打开货柜箱一看,里面全部是电子垃圾。可见这些外汇走私商,何等猖狂。

根据《人民邮电报社》网站(2004-04-23 09:11:39)的报道:“作为电子口岸建设的亲历者,曾燕珲对当时的背景记忆犹新。她说,1998年,我国走私骗汇现象非常严重,1天的外汇流失金额可高达2亿美元。1998年全年的外贸顺差是435亿美元,而外汇顺收仅有47.8亿美元,近400亿美元的外汇从非正常渠道流失。”

实际上,中国的外汇走私远远要比上述报道的严重很多,这里仅举几例说明。

2007年11月17日,深圳警方破获一起特大地下钱庄非法买卖外汇案,捣毁了组织分工严密的“杜氏”地下钱庄,这个钱庄从2006年至2007年5月非法交易金额达43亿多元。

2002年4月5日电(记者张毅)深圳皇岗海关昨天上午从一出境旅客所携带的手提袋中及其身上查获巨额走私外币,折合人民币约400多万元。

2003年12月16日,大连海关驻机场办事处旅检现场的关员在对CA105(大连-香港)航班进行监管时,发现一名旅客在查验行李的过程中神色异常,经开箱查验,海关关员们发现包中4个黄色牛皮纸包内装有大量美元。经清点,每包为20万美元,总计80万美元。

深圳罗湖海关几乎每天都会发生好几起外汇走私出境案,还有,很多货物走私,实际上也是外汇走私,每年通过走私船把外汇偷渡出境的也不少。

有关专家认为,中国每年资本外逃在150-200亿美元之间,通过海关直接携带货币外逃的相对比例虽然不大,但外逃货币资本的绝对数字应该不少。比如香港破获的一桩跨境洗黑钱大案表明,一家专门从内地走私货币到香港的犯罪集团,用蚂蚁搬家的形式,每天走私人民币、美元、日元、港币等29种货币,再到香港兑换成港币,5年内涉案金额达500亿元。

由此可知,政府何尝不想早日开放外汇市场,但是中国的外汇市场开放之日,可能就是中国经济全面崩溃之时。前段时间,中国政府也曾对外汇管理稍微放松过,允许中国的企业到国外投资。结果怎么样,有些企业把钱带出去后根本就不是办什么企业,而是做资本运营买卖,说穿了,这种资本运营买卖,有资产转移的嫌疑。因为,钱一转出去,中国政府基本上就管不到他了,一旦有风吹草动,这些资产就会变相转移到外国人手中,你看连德国的飞机场也有人敢买,很多国外的大公司他们也敢买。最后政府只好发个75号文,赶紧收摊。

现在,虽然政府还没有放松对外汇管制,但仔细观察一下,那些有几亿身家的私人老板或其家属,是不是大部分已经拿到外国绿卡;还有那些贪官,是不是大部分已经拿到绿卡。实际上,现在什么样的绿卡到处都可以买得到,只要你有钱,就像买城市户口一样,你不找他,他也会来找你。如果一旦放松外汇管制,或者国内一有风吹动,那些贪官以及私人老板,就会快速进行资产转移。

当一个政府失信于民的时候,或者当政府不能永远保护私人财产安全的时候,谁不想把自己的资产转移到一个更安全的地方。1991年,苏联经济改革失败,在很大程度上就是因为老百姓不愿意配合政府,而把有限的资产转移到国外。我想,现在很多中国的有钱人,当他什么时候读起《共产党宣言》中要打倒自己那部份内容的时候,他一定也会感到不寒而栗,他怎能不时刻想着要把自己的资产进行转移呢?这就是中国政府迟迟不敢放宽外汇管制的原因之一。

如果中国政府不放宽外汇管制,那么中国的市场经济就不可能是真正意义上的市场经济,而是被捆绑起来的市场经济,这样,中国的外汇储备还得继续上升,中国的通货膨胀还得继续上涨,更严重的是,中国政府内部产生腐败的土壤不可能得到根除;而一旦政府对外汇管制突然松绑,中国经济将会产生激烈振荡,这就是中国政府一个难以治愈的心病。

不过,现在想把财产转移到安全地方的并不是普通中国公民,而是贪官、或者与贪官互相勾结的不法商人。目前,中国的经济很大部份已经被这些人进行控制,难道中国真的还要进行一次土地革命吗?

点击此处查看原文 >>

系统分类: 自由话题   |    用户分类:    |    来源: 转贴

评论(0) | 阅读(259)
发表于:2008-3-21 9:40:41
标签:sql  dml  

0

Using SQL 之Data Manipulation Language (DML)

Using SQL


Data Manipulation Language (DML)


SQL pronounced “sequel”.


1. Types of MDL statements


SELECT Retrieves rows from one or more tables. 从一个或多个表中取得若干列


INSERT Adds one or more new rows to a table. 向表中添加若干列


UPDATE Modifies one or more rows in a table. 更新表中的若干列


DELETE Removes one or more rows from a table. 从表中删除若干列


 


2. SELECT


SELECT 列名, 列名, …, 列名 FROM 表名;


SELECT *(所有列) FROM 表名;


 


如果表名或列名中有空格,要用方括号[]括起来。


 


1 使用SMO有条件地SELECT


SELECT加上限制条件,使用WHERE


SELECT something FROM somewhere WHERE 列名 SMO某个值;


Here, SMO means SQL Mathematical Operators


























操作符



意义



=



等于



<> !=



不等于





小于





大于



<=



小于等于



>=



大于等于



 


(2) LIKE - 按样式SELECT


SELECT something FROM somewhere WHERE 列名 LIKE某个值(带通配符);


LIKE 中可以使用的通配符


























通配符



意义



_ (下划线)



表示作一个任意字符



%



表示任意任意字符



[  ]



表示与括号中任意一个字符相匹配的字符



[^  ]



表示与任意一个不在括号中的字符匹配的字符



[ - ]



与括号中从左到右的范围中字符匹配



#



表示一个任意数字



 


例:


‘Cha_’ 可以是 ‘Chaa’’Chay’’Cha4’’Cha.’’Cha@’……


‘Cha%’ 可以是’‘Chaaasf’’Chay’’Chaqq4a4’’Cha.ert’’Cha@qawe’……


‘[AIO]%’ 表示以’A’’I’’O’开头,以任意字符结尾的字符串


‘[AIO]%’ 表示以’A’’I’’O’之外的字符开头,以任意字符结尾的字符串


‘[A-O]%’ 表示以从’A’O’之间的字符开头,以任意字符结尾的字符串


 


(2) IN - 指定选择范围


SELECT something FROM somewhere WHERE 列名 IN(列出范围);


列出的范围可以是显式地指定出来,也可以用其它方法限制,如用另一个SELECT语句选择得到的结果。


1 SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice FROM Products WHERE ProductID IN (1, 2, 5, 15, 20, 45, 50);


2SELECT OrderID FROM Orders WHERE CustomerID IN


( SELECT CustomerID FROM Customers WHERE CompanyName LIKE 'Fu%');


 


(3) BETWEEN - 指定选择范围


SELECT something FROM somewhere WHERE 列名 BETWEEN 起始 AND 终止;


 


(4) NOT - 取操作符相反的意义


 


(5) 选择列值为空的行


SELECT something FROM somewhere WHERE 列名 IS NULL;


 


(6) 使用逻辑运算符限定多个选择条件


使用 AND, OR, NOT


 


(7) ORDER BY - 对取得的行进行排序


SELECT something FROM somewhere ORDER BY 列名 (ASC / DESC);


可以用ASCDESC指定是按升序或降序排列。


可以同时使用两个排序条件:


ORDER BY 1 (ASC / DESC), 2 (ASC / DESC);


意为先按列1排列,在此基础上再按列2排列。


 


(8) TOP - 取得最前面的N


SELECT TOP N something…


 


(9) DISTINCT 忽略某列值重复的行


SELECT DISTINCT something FROM somewhere…


只取得something指定列中唯一的项。


 


(10) UNION 合并SELECT得到的结果


SELECT something FROM somewhere…


UNION


SELECT something_else FROM somewhere_else…


 


(11) GROUP BY – 把得到的结果分组


SELECT something FROM somewhere…GROUP BY something2;


SELECT something COUNT(*) FROM somewhere…GROUP BY something2;


按照something2把得到的结果中相同的项合并为一项,即按something2进行分组。可以用COUNT(*)计算每组中的个数。


 


(12) 限制得到的分组


SELECT something FROM somewhere…GROUP BY something2 HAVING COUNT(*) > N;


HAVING限制只得到包括个体数目大于N的组。


 


(13) AS - 更改显示的列名,自定义表名


SELECT something AS something_else, something2 AS something_else2…;


显示自定义的列名。


SELECT Cust.CustomerID, CompanyName, Address, OrderID, ShipAddress FROM Customers AS Cust, Orders AS Ord WHERE Cust.CustomerID = Ord.CustomerID…;


为方便、简略,把表名用别名代替。


 


(14) 对列中的值进行计算


SELECT something (+, -, *, /, … something) FROM somewhere…;


对选择的列按其类型(数值、字符、字符串)进行相应的计算,以及在列之间进行计算,得到计算结果。


 


(15) 从多个表中进行选择


SELECT something, something2, … FROM (table1, table2…);


table1table2必须JOIN起来。


如果有选择的列名同时在两个表中出现,必须明确表示出来,如:table1.something


表的JOIN可以用标准的SQL形式:table1.something=table2.something;也可以用更加“显式”的形式,直接用JOIN关键字:


SELECT something, something2, … FROM table1


JOIN table2 ON table1.something=table2.something AND (other conditions)…


上两种JOIN方法存在明显的不足:如果某行中列的值为NULL则不能得到结果,即不能针对存在NULL值的列进行JOIN。外部JOIN可以解决这一问题。


LEFT OUTER JOIN 可以得到左边含NULL的值


RIGHT OUTER JOIN 可以得到右边含NULL的值


FULL OUTER JOIN 两边含NULL的值都可以取得


 


(16) 从视图中选择行


SELECT something FROM table1 INNER JOIN table2… ON (Condition)…;


取得的View称为Alphabetical list of something


 


3. INSERT - 向表中插入一行


INSERT INTO table (column1, column2, …, column…) VALUES (value1, value2, …, value…);


如果为插入的行的每一列都提供值,则可以忽略列名,只提供值:


INSERT INTO table VALUES (value1, value2, …, value…);


 


4. UPDATE – 修改表中某一行


UPDATE table


SET column = (something) WHERE (condition);


可以同时修改行中多列的值:SET column = (something), column2 = (something2), …


 


5. DELETE – 删除一行


DELETE FROM table WHERE (condition);


 


6. 保持数库的完整一致性


1.主键的独一无二性


2.子表中的Foreign Key指向父表中的有效值


如:不能修改或删除一个作为Foreign Key被引用的值


 


7. TRANSACTION


通过把多条语句集合为一个“Transaction”(业务、记录?),以及业务的执行与回滚实现。


BEGIN TRANSACTION;


Do something;


COMMIT; / ROLLBACK;


在决定是COMMIT还是ROLLBACK之前,应该检查业务中有没有错误发生。如果没有则执行,否则就回滚。用@@ERROR的值判断是否发生错误,0代表没有。


BEGIN TRANSACTION MyTransaction;


Do something;


IF @@ERROR = 0


  COMMIT TRANSACTION MyTransaction;


ELSE


  ROLLBACK TRANSACTION MyTransaction;

点击此处查看原文 >>

系统分类: 软件开发   |    用户分类:    |    来源: 转贴

评论(0) | 阅读(254)
发表于:2008-1-17 17:07:20
标签:HEX  格式  

0

HEX格式说明

什么是Intel HEX格式?
Intel HEX文件是记录文本行的ASCII文本文件,在Intel HEX文件中,每一行是一个HEX记录
由十六进制数组成的机器码或者数据常量,Intel HEX文件经常被用于将程序或数据传输
存储到ROM.EPROM,大多数编程器和模拟器使用Intel HEX文件.

记录格式

一个Intel HEX文件可以包含任意多的十六进制记录,每条记录有五个域,下面是一个记录的格式.

:llaaaatt[dd...]cc

每一组字母是独立的一域,每一个字母是一个十六进制数字,每一域至少由两个十六进制数字组成,下面是字节的描述.

:冒号 是每一条Intel HEX记录的开始

ll 是这条记录的长度域,他表示数据(dd)的字节数目.

aaaa 是地址域,他表示数据的起始地址
<如果是数据记录,这表示将要烧录的这条记录中的数据在EPROM中的偏移地址,
对于不支持扩展段地址和扩展线性地址的,如89C51,这就是此条记录的起始地址>

tt 这个域表示这条HEX记录的类型,他有可能是下面这几种类型
00 ----数据记录
01 ----文件结束记录
02 ----扩展段地址记录
04 ----扩展线性地址记录

dd 是数据域,表示一个字节的数据,一个记录可能有多个数据字节,字节数目可以
查看ll域的说明

cc 是效验和域,表示记录的效验和,计算方法是将本条记录冒号开始的所有字母对

<不包括本效验字和冒号> 所表示的十六进制数字
<一对字母表示一个十六进制数,这样的一个十六进制数为一个字节>

都加起来然后模除256得到的余数最后求出余数的补码即是本效验字节cc.
<例如:
:0300000002005E9D
cc=0x01+NOT((0x03+0x00+0x00+0x00+0x02+0x00+0x5E)%0x100)=0x01+0x9C=0x9D

C语言描述:
UCHAR cc;
cc=(UCHAR)~(0x03+0x00+0x00+0x00+0x02+0x00+0x5E);
cc++;
>
数据记录

Intel HEX文件由若干个数据记录组成,一个数据记录以一个回车和一个换行结束
<回车为0x0d换行为0x0a>

比如下面的一条数据记录
:10246200464C5549442050524F46494C4500464C33

10 是此行记录数据的字节数目
2462 是数据在内存<将要烧写的eprom地址>中的起始地址
00 是记录类型00(是一个数据记录)
464C 到 464C 是数据
33 是此行记录的效验和

扩展线性地址记录(HEX386)
扩展线性地址记录也可称为 32位地址记录 和 HEX386记录,这个纪录包含高16(16-31位)位数据地址,这种扩展的线性记录总是有两个字节数据,像下面这样:

:02000004FFFFFC
02 是记录的数据字节数目
0000 是地址域这在扩展地址记录中总是0000
04 是记录类型04(扩展地址记录)
FFFF 是高16位地址
FC 是记录效验和,计算方法如下:
01h + NOT(02h + 00h + 00h + 04h + FFh + FFh)

当一个扩展线性地址记录被读到后,扩展线性地址记录的数据区域将被保存
并应用到后面从Intel HEX文件中读出的记录,这个扩展线性记录一直有效,
直到读到下一个扩展线性记录.


绝对内存地址 = 数据记录中的地址 + 移位后的扩展线性地址


下面举例说明这个过程

从数据记录的地址域得到地址 2462
从扩展线性地址记录的地址域得到地址 FFFF
绝对内存地址 FFFF2462

扩展段地址记录 (HEX86)

扩展段地址记录也被称为 HEX86记录, 包含 4-19位的数据地址段,
这个扩展段地址记录总是有两字节数据,如下:

:020000021200EA
02 是 记录中的数据字节数目
0000 是地址域,在扩展段地址记录中,这个域总是0000
02 是记录类型02(扩展段地址的标示)
1200 是该段的地址
EA 是效验和
计算如下:
01h + NOT(02h + 00h + 00h + 02h + 12h + 00h).

当扩展段地址记录被读后,扩展段地址将被存储并应用到以后从Intel HEX文件读出的记录,这个段地址一直有效直到读到下一个扩展段地址记录

绝对内存地址 = 数据记录中的地址 + 移位后的扩展段地址


数据记录中的地址域 移位后扩展段地址记录中的地址域

下面举例说明这个过程

从数据记录的地址域得到地址 2 4 6 2
从扩展段地址记录的地址域得到地址 1 2 0 0
绝对内存地址 0 0 0 1 4 4 6 2

文件结束记录(EOF)
一个Intel HEX文件必须有一个文件结束记录,这个记录的类型域必须是01,
一个EOF记录总是这样:
:00000001FF
00是记录中数据字节的数目
0000这个地址对于EOF记录来说无任何意义
01记录类型是01(文件结束记录标示)
FF是效验和计算如下
01h + NOT(00h + 00h + 00h + 01h).
========================

总结


形如
:BBAAAATTHHHH...HHHHCC

BB: Byte
AAAA:数据记录的开始地址,高位在前,地位在后
因为这个格式只支持8bits,地址被倍乘
所以,为了得到实际的PIC的地址,需要将 地址除以2
TT: Type
00 数据记录
01 记录结束
04 扩展地址记录(表示32位地址的前缀,当然这种只能在 INHX32)
HHHH:一个字(Word)的数据记录,高Byte在前,低Byte在后
TT之后,总共有 BB/2 个字 的数据
CC: 一个Byte的CheckSum


因为PIC16F873A只有4K的程序空间

所以,不会有 TT="04的" Linear Address Record

点击此处查看原文 >>

系统分类: 软件开发   |    用户分类:    |    来源: 整理

评论(0) | 阅读(409)
发表于:2008-1-9 10:49:57
标签:无标签

0

[转载]音频文件格式全介绍

自从PC支持多媒体以来,陆陆续续地出现了许多音频格式。这些格式既有流行的也有不那么流行的,关于它们的来龙去脉,本文向你一一道来。

主流

  目前的主流音频格式其实不少。不同的格式有自己的用途,比如大家都应该很熟悉的MP3格式就是用于聆听用途的。下面我们逐一介绍:

存在便是永恒 - WAV

  WAV是Microsoft Windows本身提供的音频格式,由于Windows本身的影响力,这个格式已经成为了事实上的通用音频格式。不客气地说,它实际上是Apple电脑的 AIFF格式的克隆。通常我们使用WAV格式都是用来保存一些没有压缩的音频,但实际上WAV格式的设计是非常灵活(非常复杂)的,该格式本身与任何媒体数据都不冲突,换句话说,只要有软件支持,你甚至可以在WAV格式里面存放图像。之所以能这样,是因为WAV文件里面存放的每一块数据都有自己独立的标识,通过这些标识可以告诉用户究竟这是什么数据。在WINDOWS平台上通过ACM(Audio Compression Manager)结构及相应的驱动程序(在这里通常称为CODEC,编码/解码器),可以在WAV文件中存放超过20种的压缩格式,比如ADPCM、 GSM、CCITT G.711、G.723等等,当然也包括MP3格式。

图表 - 使用音频编辑软件WaveCN(http://www.wavecn.com)列出Windows安装了的ACM驱动信息

  虽然WAV文件可以存放压缩音频甚至mp3,但由于它本身的结构注定了它的用途是存放音频数据并用作进一步的处理,而不是像mp3那样用于聆听。目前所有的音频播放软件和编辑软件都支持这一格式,并将该格式作为默认文件保存格式之一。这些软件包括:Sound Forge, Cool Edit Pro, WaveLab等等。由于WAV的支持实在是太广泛了,可以说,即使Windows退出历史舞台,WAV格式也不会消亡。

老当益壮 – mp3

  第二个要提到的就是改变了世界的mp3了。这个比喻相信大家都会同意。mp3是Fraunhofer-IIS 研究所(http://www.iis.fhg.de/)的研究成果。mp3是第一个实用的有损音频压缩编码。在mp3出现之前,一般的音频编码即使以有损方式进行压缩能达到4:1的压缩比例已经非常不错了。但是,mp3可以实现12:1的压缩比例,这使得mp3迅速地流行起来。mp3之所以能够达到如此高的压缩比例同时又能保持相当不错的音质是因为利用了知觉音频编码技术,也就是利用了人耳的特性,削减音乐中人耳听不到的成分,同时尝试尽可能地维持原来的声音质量。

图表 - 人耳等响度曲线图,mp3的技术基础。

  衡量mp3文件的压缩比例通常使用比特率来表示。这个术语的英文是bps: bit per second,表示每1秒钟的音频可以用多少个二进制比特来表示。通常比特率越高,压缩文件就越大,但音乐中获得保留的成分就越多,音质就越好。由于比特率与文件大小音质的关系,所以后来又出现了vbr(Variant Bitrate 可变比特率)方式编码的mp3,这种编码方式的特点是可以根据编码的内容动态地选择合适的比特率,因此编码的结果是在保证了音质的同时又照顾了文件的大小,结果大受欢迎。其实mp3的编码标准本来就支持这种压缩方式,但是第一个将此功能实现的反而是一个第三方工具:曾经非常有名的Xing Technology公司(http://www.xingtech.com,当年很多电脑上看VCD听mp3就靠这个公司的Xing Player)推出的Xing Encoder。

  由于mp3是世界上第一个有损压缩的编码方案,所以可以说所有的播放软件都支持它,否则就根本没有生命力。在制作方面,也曾经产生了许多第三方的编码工具。不过随着后来Fraunhofer-IIS宣布对编码器征收版税之后很多都消失了。目前属于开放源代码并且免费的编码器是LAME (Lame Ain't Mp3 Encoder,http://lame.sourceforge.net)。这个工具是公认的压缩音质最好的mp3压缩工具。另外,几乎所有的音频编辑工具都支持打开和保存mp3文件。最近,Fraunhofer-IIS对之前不收取版权费的mp3解码器也征收了版权费。此举大有Fraunhofer-IIS意识到mp3已经在没落,趁还能收到钱最后捞一把的意思。应该说,到了现在,MP3确实显现出疲态了。许多新一代的编码技术都已经能在相同的比特率下提供比MP3优越得多的音质。特别是音乐发烧友对mp3的音质更是嗤之以鼻。不过由于mp3的影响力实在是太大了,支持mp3的软件多如牛毛,更别提众多支持mp3的硬件播放器,如MPMAN,DiscMan, CD/VCD/DVD机等等。一句话,它依然是世界上最流行的音频压缩技术,所以要它真正退出舞台相信还有好一段时间。

图表 - Lame的其中一个前端:RazorLame(http://www.dors.de/razorlame

老树发新花 - mp3PRO

  为了使mp3能在未来仍然保持生命力,Fraunhofer-IIS研究所连同Coding Technologies 公司(http://www.codingtechnologies.com)还有法国的Thomson multimedia公司(http://www.thomson.net)共同推出了mp3PRO。这种格式与之前的mp3相比最大的特点是能在低达64kbps的比特率下仍然能提供近似CD的音质(mp3是128K)。该技术称为SBR(Spectral Band Replication),它在原来mp3技术的基础上专门针对原来mp3技术中损失了的音频细节进行独立编码处理并捆绑在原来的mp3数据上,在播放的时候通过再合成而达到良好的音质效果。

图表 - SBR技术在音频编码/解码过程中的应用

  mp3PRO格式与mp3是兼容的,所以它的文件类型也是mp3。mp3PRO播放器可以支持播放 mp3PRO或者mp3编码的文件;普通的mp3播放器也可以支持播放mp3PRO编码的文件,但只能播放出mp3的音质。但是,虽然mp3PRO是一种优秀的技术,由于技术专利费用的问题以及其他技术提供商比如Microsoft的竞争,mp3PRO并没有得到很大的流行。大家可以从Coding Technologies的网站下载Demo播放/压缩工具和Winamp的播放插件。目前也有许多专业音频编辑软件比如Cool Edit Pro 2.0支持mp3PRO格式,但播放器除了刚才说的和Music Match Juke Box就基本没有了。最关键的是由于Microsoft的媒体播放机不支持,使得mp3PRO失去了流行的机会。前段时间Coding Technologies推出了最新的MPEG-4 aacPlus,通过将SBR技术应用在AAC(Advanced Audio Codec)技术中而获得更卓越的音质。Coding Technologies并表示SBR将会成为MPEG-4的核心技术。但缺乏支持的技术到底能走多远,谁也不清楚。

图表 - THOMSON mp3PRO 播放器

网络流媒体鼻祖 - Real Media

  互联网大行其道之后,Real Media 出现了。这种文件格式几乎成了网络流媒体的代名词。RA、RMA这两个文件类型就是Real Media里面向音频方面的。它是由Real Networks公司(http://www.realnetworks.com)发明的,特点是可以在非常低的带宽下(低达28.8kbps)提供足够好的音质让用户能在线聆听。这一特点在互联网的早期简直是广大网虫的福音。也就是因为出现了Real Media之后,相关的应用比如网络广播,网上教学,网上点播等等才浮出水面,形成了一个新的行业。

  网络流媒体的道理其实非常简单,简单说就是将原来连续不断的音频分割成一个一个带有顺序标记的小数据包,将这些小数据包通过网络进行传递,在接收的时候再将这些数据包重新按顺序组织起来播放。如果网络质量太差,有些数据包收不到或者延缓了到达,它就跳过这些数据包不播放,以保证用户在聆听的内容是基本连续的。就是这么简单的道理,促成了网络上的又一个传奇。

  由于Real Media是从极差的网络环境下发展过来的,所以Real Media的音质并不怎样,包括在高比特率的时候,甚至差于mp3。特别是有相当长的一段时间Real Networks公司只顾着往Real Media里面加入各种各样的新特性比如广告插播什么的,而忽略了随着网络速度的提升和宽带网的普及,用户对质量的要求也不断提高。后来Real Networks通过与SONY公司合作,利用SONY的ATRAC技术(http://www.minidisc.org/,也就是MD的压缩技术)实现高比特率的高保真压缩,但这些举措始终都带给用户一个姗姗来迟的感觉。由于Real Media的用途是在线聆听,并不适于编辑,所以相应的处理软件并不多。一些主流软件可以支持Real Media的读/写,可以实现直接剪辑的软件是Real Networks自己提供的捆绑在Real Media Encoder编码器中的Real Media Editor。但功能非常有限。这一点与现在的Windows Media相比是两个世界。

图表 - Real One Player, 最新的Real Media播放器

霸气十足 - Windows Media

  任何事情都少不了Microsoft的份。在意识到网络流媒体之于互联网的重要性之后,Microsoft立马就推出了Windows Media与Real Media相抗衡,同时开始对其他音频压缩技术说不:一律不提供直接支持。到了Windows XP版本还把原来提供的mp3压缩功能都拿掉了。

  Windows Media (http://www.microsoft.com/windows/windowsmedia)也是一种网络流媒体技术,本质上跟Real Media是相同的。但Real Media是有限开放的技术,比如rtsp(Real Time Stream Protocol实时流协议)这样的网络传输协议是提交到网络工作组RFC网络协议集的其中一个(编号RFC2326),而Windows Media则没有公开任何技术细节,据称是为了更好地进行版权保护,因此要完全封闭,还创造出一种名为mms(Multi-Media Stream多媒体流)的传输协议。所有这些事情综合起来可以看出Microsoft意图一统江湖的野心。

  最初版本的Windows Media并没有得到什么好评,特别在音质方面更被网络上那些“金耳朵”的网友所不齿。不过在更新了几个版本之后,目前最新的Windows Media 9技术携带着大量的新特性并在Windows Media Player的配合下表现已经不可同日而语。特别在音频方面,Microsoft是唯一一个能提供全部种类音频压缩技术(无失真、有失真、语音)的解决方案,大有囊括一切的势头。这也是微软的一贯特色:虽然我的东西质量不是最好的,但肯定是最方便,集成度最高的。目前Windows Media还是处于推广期,播放器和编码器可以免费下载,服务器端捆绑在Windows服务器版中,不另外收费。这些手段正在不断提升其市场占有率。而且由于Microsoft的影响力,支持Windows Media的软件非常多。虽然它也是用于聆听用途,不能编辑,但几乎所有的Windows平台的音频编辑工具都对它提供了读/写支持,至于第三方播放器更是无一例外了,连Real Player都支持其播放。通过Microsoft 自己推出的Windows Media File Editor可以实现简单的直接剪辑。最近,Microsoft还推出了Windows XP Media Center版本,通过在Windows XP中捆绑Windows Media 9技术以及相关娱乐媒体软件来加强Windows作为家庭娱乐中心的作用。如果Microsoft继续保持其在操作系统特别是桌面操作系统的垄断地位的话,Windows Media的未来肯定是一片光辉。

图表 - 最新的Windows Media Player 9,带有大量的网络特性

电脑与电子乐器的桥梁 – MIDI

  MIDI技术本来不是为了电脑发明的。该技术最初应用在电子乐器上用来记录乐手的弹奏,以便以后重播。不过随着在电脑里面引入了支持MIDI合成的声音卡之后MIDI才正式地成为了一种音频格式。有很多人都误以为MIDI是用来记谱的,这是错的。MIDI的内容除了乐谱之外还记录了每个音符的弹奏方法,所以有些MIDI文件播放起来不好听,而某些则有良好的效果。MIDI本身也有两个版本,General MIDI和General MIDI 2。在MIDI上还衍生了许多第三方的非标准技术,比如非常著名的:X-MIDI(或者叫XG),这是由日本YAMAHA公司(http://www.yamaha.com)发明的,在原有的MIDI具有128种乐器的基础上扩充到了512种,并增加了更多的演奏控制,配合YAMAHA自己的波表播放软件或支持X-MIDI的硬件可以还原出非常动听和接近真实乐器效果的音乐。另外就是为了弥补MIDI中通过声音合成得到的乐器声音始终比不上真实乐器声音这一缺点而由 General MIDI Association(MIDI规范的国际组织,http://www.midi.org)推出的DLS(Downloadable Sound)技术,该技术通过给MIDI文件附带上真实乐器的录音(采样)而使MIDI文件能营造出接近真实乐器效果的声音,不过该技术的主要问题是带上乐器采样之后的MIDI文件实在是太大了,通常情况下都有4兆字节以上(这样的大小用户当然是去找mp3了),影响了该技术的普及。

  由于MIDI具有的优点和特殊性,因此可以相信这是一种在相当长的时间里都会继续存在的技术。普通的MIDI 文件许多播放器都支持,但要达到好的效果就必须安装软波表,比如曾经很出名的WinGroove、Roland Virtual Sound Canvas和YAMAHA S-YXG Player。随着Microsoft与Roland(http://www.roland.com)合作在DirectX里面增加了 DirectMusic之后软波表就变成了Windows系统的标准配置了。需要注意的是对于X-MIDI格式来说必须使用YAMAHA自己推出的播放器才能得到良好的播放效果。比如当年曾经卖得很火的使用YAMAHA YMF724/740做芯片的声音卡便带有X-MIDI的播放器S-YXG100。

图表 - Roland Virtual SoundCanvas软音源界面

图表 - YAMAHA S-YXG50软音源播放器界面,怎么看都觉得比Roland的好看。

图表 - YAMAHA S-YXG50 XGPlayer软音源播放器界面,这个版本支持的播放控制更多。

  如果要对MIDI文件进行编辑,可以使用的比较出名的软件是Cake Walk Pro和Sonar(http://www.cakewalk.com); X-MIDI则要使用YAMAHA XGWorks。另外还有一些曲谱软件,比如Sibelius(http://www.sibelius.com)。不过这些软件都是非常昂贵的。国产的相关软件都有一些,而且支持简谱,比如TT作曲家(http://www.centrmus.com)。

开放、免费 - Ogg Vorbis

  开放源代码的Ogg Vorbis(http://www.xiph.orghttp://www.vorbis.com),作为开放源码向专利技术下的第一封战书出现在世人的面前。在经历了一些变故之后,Ogg Vorbis终于在2002年7月释出了1.0版本。由于开放源码的东西向来都缺少枪手为其摇旗呐喊,所以国内并不是有很多的人了解Ogg Vorbis。Ogg Vorbis 是一种音频压缩格式,类似于MP3等现有的通过有损压缩算法进行音频压缩的音乐格式。但有一点不同的是,Ogg Vorbis格式是完全免费、开放源码且没有专利限制的。Vorbis 是这种音频压缩机制的名字,而Ogg则是一个计划的名字,该计划意图设计一个完全开放源码的多媒体系统。开放源代码能为用户在经济上带来收益,这一点很多人都知道了,但不能忘记的是Ogg Vorbis的技术也不是盖的。Ogg Vorbis文件的扩展名是.OGG。这种文件的设计格式是非常灵活的。它的最大特点是在文件格式已经固定下来后还能对音质进行明显的调节和新算法。现在创建的OGG文件可以在未来的任何播放器上播放,因此,这种文件格式可以不断地进行大小和音质的改良,而不影响旧有的编码器或播放器。在压缩技术上, Ogg Vorbis的最主要特点是使用了VBR(可变比特率)和ABR(平均比特率)方式进行编码。与MP3的CBR(固定比特率)相比可以达到更好的音质。 Ogg Vorbis其他技术特性还包括:支持类似于MP3的ID3信息,但比MP3要灵活而又完整得多,实际上可以填写随意多的信息。Vorbis还具有比特率缩放功能,可以不用重新编码便可调节文件的比特率。Vorbis文件可以被分成小块并以样本粒度(granularity,专业术语,指数据可以被分割的最小尺寸)进行编辑;Vorbis支持多通道(大于2)音频流并使用了独创性的处理技术;Vorbis文件可以以逻辑方式相连接等。

  在经济利益的推动下,Ogg Vorbis从一诞生就获得了各方的关注,许多著名音频软件,包括象出品Sound Forge的Sonic Foundry(http://www.sonicfoundry.com)这样的工业巨头也在软件中增加了对Ogg Vorbis的支持,而对于本来就是免费的或者开放源码的音频相关软件比如WinAMP(http://www.winamp.com)、CDEX(http://cdex.sourceforge.net)等等更是第一时间在软件中加入了Ogg Vorbis的支持。可以这样说,Ogg Vorbis在业界的支持是非常广泛的。简单的举个例子,著名的游戏闪点行动(Operation Flash Point)就是使用Ogg Vorbis作为游戏所有声音和音乐的保存格式的。

  当然,软件上的支持对于一种音乐格式来说还是一厢情愿的事情。Ogg Vorbis是否能够真正流行起来,关键还是要靠广大用户和音乐制作人。可喜的是,目前在网络上Ogg Vorbis格式的应用已经日渐增多,而且已经开始向其他方面发展,比如游戏、多媒体应用的配乐等。目前Ogg Vorbis取得的最大成就是获得著名的BBC广播公司的认可,使用Ogg Vorbis音频流在线播放节目。另外,在硬件方面也出现了支持播放OGG格式的播放器。

  Ogg Vorbis几乎得到所有的音频编辑器的支持。另外,作为一般的编码使用,可以在http://www.vorbis.com/download_win.psp网址可以下载到OggDrop/OggDrop XPd。播放可以使用WinAMP播放。现在Ogg Vorbis已经是WinAMP标准配置之一。

图表 - OggDrop XPd, Ogg Vorbis的编码器

生不逢时 – VQF

  VQF实际指的是TwinVQ(Transform-domain Weighted INterleave Vector Quantization)技术,是日本Nippon Telegraph and Telephone集团属下的NTT Human Interface Laboratories(http://sound.splab.ecl.ntt.co.jp)开发的一种音频压缩技术。该技术受到著名的YAMAHA公司的支持。VQF或TVQ是其文件的文件类型名。VQF其实是一种比较先进的技术,通常认为 96kbps VQF 与 128kbps MP3 质量相同。下图是MP3与VQF的一个质量对比示意图:

MP3 128Kbps

 

Original 1411Kpbs

 

VQF 96Kbps