掌上游戏机开发指南GBA探索日记(9)(转)

掌上游戏机开发指南GBA探索日记(9)(转)[@more@]

  这一节我们讨论如何正常结束声音播放的问题。不要觉得这是个小问题,当初这个小问题难倒了我们所有研究GBA的爱好者。我总觉得这一点似乎是GBA设计上的缺陷,但是最后我们可以通过使用VBlank中断还解决这个问题。本篇结束的时候,我还会给出完整声音播放的代码。这样,你甚至不必了解声音播放的细节就可以实现声音的播放功能了。

  

  由于声音播放使用的DMA不能根据WORD COUNT来控制传输的数据量,同时又不能在传输完毕的时候产生DMA中断,所以我们无法知道什么时候DMA把我们的音频数据传输完毕。这样,我们必须自己另外加一计时器,来计算什么时候声音播放结束。当然,你可以使用Timer来做,但是另外再设置个Timer似乎就麻烦了点,而且Timer的精度过高,也不好计算长时间的声音播放。依照官方开发包中的做法,我们就拿VBlank中断作为声音播放的计时器。

  

  VBlank中断是在硬件扫描屏幕V方向扫描线的时候产生的硬件中断。它是严格的每秒59.78次(接近60次/s)

  

  下面我们来看看这段修改后的播放声音的代码。需要注意拿他和前一节的播放代码来比较一下,看看他们之间有什么不同。

  

  这个PlayDirectSoundA的播发函数多了一个参数u32 time.它就是用来控制声音结束的时间参数。它的单位是秒(对于一般的声音播放来说,秒单位应该是足够精确了)。

  

  soundATime = time * 59.727;

  

  这条代码是将实际播放时间的秒数转换成一共要产生VBlank的中断数。前面说过,我们将使用VBlank来判断我们的声音是否播放结束。而VBlank中断的频率是59.727Hz,也就是说一秒中要产生59.727次。比如说如果我们的这段声音要播放5秒钟,那么播放过程中一共要产生5*59.727次VBlank中断。这样,我们只要使用一个计数器,每次VBlank中断产生的时候计数器自加1,当它等于5*59.727的时候,那么声音也就应该结束了。

  

  其它的代码就差不多和前一节的PlayDirectSoundA差不多了。

  

  PlayDirectSoundA/

  

  // time是播发时间,单位是秒数

  

  void PlayDirectSoundA(u8 *sound, u16 sampleRate, u32 length,u32 time)

  

  {

  

  //Stop any previous sample

  

  soundAPlaying = 0;

  

  *(vu16 *)REG_TM0CNT_H = 0;

  

  *(vu16 *)REG_TM0CNT_L = 0;

  

  *(vu32 *)REG_DMA1SAD = 0;

  

  *(vu16 *)REG_DMA1CNT_H = 0;

  

  *(vu32 *)REG_DMA1DAD = 0;

  

  //Output DirectSound A to right channel

  

  *(vu16 *)REG_SOUNDCNT_H |= DSOUND_A_RIGHT_CHANNEL| DSOUND_A_TIMER_0 | DSOUND_A_LEFT_CHANNEL | DSOUND_A_FIFO_RESET | DSOUND_A_OUTPUT_FULL;

  

  //Enable all sound

  

  *(vu16 *)REG_SOUNDCNT_X |= SOUND_MASTER_ENABLE;

  

  //DMA1 Source Addresss

  

  *(vu32 *)REG_DMA1SAD = (u32)sound;

  

  //Set sound A's current sound

  

  soundA = sound;

  

  //Set the length, looping, etc

  

  soundALength = length;

  

  // 讲time秒转换成V-Blank中断次数,V-Blank中断是59.727Hz

  

  soundATime = time * 59.727;

  

  soundACurrent = 0;

  

  soundASampleRate = sampleRate;

  

  //DMA1 Destination Address (REG_SGFIFOA)

  

  *(vu32 *)REG_DMA1DAD = 0x40000A0;

  

  //Write 32 bits into 0x040000A0 (REG_SGFIF0A) every VSync

  

  *(vu32 *)REG_DMA1CNT = DMA_DEST_FIXED | DMA_REPEATE | DMA_32 | DMA_TIMEING_SYNC_TO_DISPLAY | DMA_ENABLE;

  

  //Sample Rate

  

  *(vu16 *)REG_TM0CNT_L = 65536 - (16777216/sampleRate);

  

  //Enable the timer

  

  *(vu16 *)REG_TM0CNT_H = TIMER_ENABLE | TIMER_IRQ;

  

  //The sound is playing

  

  soundAPlaying = 1;

  

  }

  

  在这里我们增加了一个函数UpdateDirectSoundA.它的作用是判断Direct Sound A是否播放完毕的函数.它的代码很简单.每调用它一次,当前计数器soundACurrent自加1,同时判断是否播放完毕.

  

  /UpdateDirectSoundA

  

  void UpdateDirectSoundA(void)

  

  {

  

  // if now is not playing sound A,return

  

  if(!soundAPlaying)

  

  return;

  

  // Increase the Current timer

  

  soundACurrent +=1;

  

  // If sound A play time is up,close the sound A

  

  if(soundACurrent >= soundATime)

  

  CloseDirectSoundA();

  

  }

  

  需要注意的是,这个函数的调用必须是放在VBlank中断的响应函数里.比如像下面一样,把它的调用放在Interrupt中处理VBlank的部分里.这样我们才能保证它是每1/59.727秒被调用一次.

  

  关于中断的部分,请看看前面的<>有关中断的部分.

  

  void Interrupts(void)

  

  {

  

  u16 Int_Flag;

  

  REG_IME = 0x00;      // Disable interrupts

  

  Int_Flag = REG_IF;     // Read the interrupt flags

  

  if((REG_IF & 1) == 1)

  

  {

  

  UpdateDirectSoundA();

  

  }

  

  REG_IF = Int_Flag;     // Write back the interrupt flags

  

  REG_IME = 1;    // Re-Enable interrups

  

  }

  

  好了.这个如何控制声音播放结束的问题总算解决了.其实我们也可以使用Timer用同样的原理来控制声音播放的结束,不过至少我觉得Timer的中断产生频率太快,完全没有必要.下面我将把我播放声音的全部代码公布出来,你可以将它拷贝到libsound.c和libsound.h,然后就可以使用了.

  

  随便在结束本节之前再说几句,我们关于GBA的基础部分也就结束.但是我们对于GBA开发的探索还没有结束.后面的GBA探索日记将介绍一些实际游戏开发过程中需要的技术,比如汉字显示,Tile模式下写点等问题.不过这些问题就和我们一直走的官方开发包没有关系(无论是日本人还是老美根本不会去考虑汉字显示的问题),但是这些技术在实际开发过程中是很有用的.特别是汉字显示和Tile下写点这两个问题,是很多朋友都在做的,现在应该说是比较成熟的,所以在后面的两篇日记里,我也将它们公布出来,希望对大家有所帮助.

  

  //*************************************

  

  //  文件名: libsound.h

  

  //  GBA中Direct Sound处理函数或宏

  

  //  tangl_99 创建于2003.2.7

  

  //*************************************

  

  #ifndef _SOUND_H

  

  #define _SOUND_H

  

  //Necessary Includes/

  

  //Definitions/

  

  #define BIT00 1

  

  #define BIT01 2

  

  #define BIT02 4

  

  #define BIT03 8

  

  #define BIT04 16

  

  #define BIT05 32

  

  #define BIT06 64

  

  #define BIT07 128

  

  #define BIT08 256

  

  #define BIT09 512

  

  #define BIT10 1024

  

  #define BIT11 2048

  

  #define BIT12 4096

  

  #define BIT13 8192

  

  #define BIT14 16384

  

  #define BIT15 32768

  

  #define TIMER_CASCADE  BIT02

  

  #define TIMER_IRQ    BIT06

  

  #define TIMER_ENABLE  BIT07

  

  #define DMA_ENABLE               0x80000000

  

  #define DMA_INTERUPT_ENABLE           0x40000000

  

  #define DMA_TIMEING_IMMEDIATE          0x00000000

  

  #define DMA_TIMEING_VBLANK           0x10000000

  

  #define DMA_TIMEING_HBLANK           0x20000000

  

  #define DMA_TIMEING_SYNC_TO_DISPLAY       0x30000000

  

  #define DMA_16                 0x00000000

  

  #define DMA_32                 0x04000000

  

  #define DMA_REPEATE               0x02000000

  

  #define DMA_SOURCE_INCREMENT          0x00000000

  

  #define DMA_SOURCE_DECREMENT          0x00800000

  

  #define DMA_SOURCE_FIXED            0x01000000

  

  #define DMA_DEST_INCREMENT           0x00000000

  

  #define DMA_DEST_DECREMENT           0x00200000

  

  #define DMA_DEST_FIXED             0x00400000

  

  #define DMA_DEST_RELOAD             0x00600000

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8225414/viewspace-951688/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/8225414/viewspace-951688/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
近年来由于油价节节攀升,电动车作为一种绿色、环保、便捷的交通工具,其发展势头异常迅猛,产销量一直以惊人的速度翻番递增,但是许多消费者在使用电动车半年后铅酸蓄电池就连续出现问题,因为铅酸蓄电池厂家都承诺电池质保一年,于是用户们纷纷找销售商更换铅酸蓄电池,铅酸蓄电池的返修给厂家与经销商及用户带来了一种无形压力,经销商花费了大量的精力检测、维护、保养,还是不能避免被投诉。可电池厂家承诺质保一年的铅酸蓄电池产品,为什么半年后很多都出现了问题呢?它的退返率为什么会急剧增加呢?笔者分析主要成在以下四个方面的重要因素: 1. 先天性不足的重要因素 我们使用的电动车蓄电池往往是由2只(24V)、3只(36V)、4只(48V)电池串联而成铅酸蓄电池组,甚至于有的超标准电动车还用5只(60V)电池串联而成铅酸蓄电池组,而每只电池内部又是由6个2V的单体组成一只电池,(用通俗易懂的说法就是每只电池内部由6个2V的小电池串联而成12V的一只电池),而要串联成这样一只好的铅酸蓄电池,就要对每只小单体铅酸蓄电池进行严格筛选,使组成单只12V蓄电池的特性一致,这只电池才能达到最佳的组合效果,才能提高这只蓄电池的循环使用寿命,否则这只蓄电池的质量就有问题,假如:组成这只电池的某一个单体电池容量小、电压偏低,那么在充电时这个单体电池就先充满电并进入过充电状态,周而复始造成整只电池过充电,而过充电的这只铅酸蓄电池就会失水从而影响它的循环使用寿命;在放电时这个单体电池就最先放完电进入过放电状态,大家都知道,铅酸蓄电池过放电它还会直接影响组成这只电池的其它电池循环使用寿命;(就相当于人们在日常生活中用新、旧电池混合使用的状态,等于是在电池组间串联了一个使用的电阻一样)这样这只电池容量会很快降低从而加速了该只电池的老化,使这只电池就进入了一种恶性循环的状态。【美卡得】充电器则采用微芯片处理技术,在充饱电后关断充电器只输出瞬间脉冲电流,这样周而复始提高容量和电压来解决这一问题。 结语:有些电池厂家在制造电池时其浓差极化与电阻极化电压没有彻底做好,再加上相应检测设备和手段不够完善,其使用的铅酸蓄电池组本身特性就不一样,这就造成了这只电池在制造时就存在先天性的不足,再加上有些电动车整车的系统配置不佳,生产的电动成品车就到了市场,它的蓄电池循环使用寿命当然就短了。这就是为什么电动车生产厂家生产36V电动车要比48V电动车更可靠的原因了。故建议生产厂家尽量生产36V电动车。 2.充电器的重要因素 蓄电池充电与放电的工作循环过程、充电电流与电压大小和充电控制方式等等,都是直接影响铅酸蓄电池组循环使用寿命的重要因素,而铅酸蓄电池组的容量与电压决定了充电需要的参数,所以充电器的参数要与蓄电池参数密切配合,才能减少充电不当对蓄电池组的容量损害。 现在很多厂家觉得充电器结构简单容易制造,生产投入也不大,市场需求却很大,于是纷纷上马生产充电器,现在一个普通的充电器销售价从二三十元到一百多元不等,他们的充电控制模式也各不相同,电流小则充电时间长,电流大则电池容易发热,导致电池失水,缩短了电池使用寿命,这种小电流充电器在冬季充电又出现另外一个问题:在冬季低温情况下电池内硫酸黏度变高,电池内阻就成倍增大,这就使得电化学反应慢,在充电电流小的条件下,电池无法充饱,就产生了欠充,而时常欠充的电池就会产生硫酸盐化,加速电池的老化。 就目前普遍使用比较好一点的恒流、恒压、涓流三段式充电模式,充电在恒压阶段的后期析气相当严重,它严重影响了铅酸电池的循环使用寿命,这一阶段的电流偏小,极板化合反应不充分,充电在进入涓流阶段充电方式则为电流取样,电池在后期失水量相当严重,充电后期温度会高于正常值40,自放电增加,使电池已充满也无法换充电指示灯和关断充电输出,电池组中的单体电池之间不可避免地出现电压和容量高低差别,电池就会被充鼓变形,这就是将电池充坏了,于是就有了“电池不是用坏的而是充坏的”说法。 结语:目前大部分充电器成在以下问题需要克服。 ①.对铅酸蓄电池进行充电时,电流小则充电时间长,电流大则电池容易发热,从而导致电池失水,缩短了电池使用寿命。 ②.对铅酸蓄电池进行充电时,由于冬季低温情况下电池内硫酸黏度高,电池内阻成倍增大,使得电化学反应漫,在充电电流小的条件下,电池无法充饱,自然会产生硫酸盐化缩短电池使用寿命。 ③.电池组各块电池在放电时不可避免的会产生电压高低差别,电压高低差别越大,越会造成电压低的单体电池容量衰减加快,如此恶性循环电池组整体寿命缩短加剧。目前大部分充电器不但没有办法在充电时对这种电压差进行平衡修补,反而会加大。 ④.对铅酸蓄电池进行充电时,使电池长期处于一种过充电或欠充电状态,电池内部不断失水和硫酸盐化,大大缩短了使用寿命。 以上问题希望充电器厂家想办法解决,为我们电动车行业健康有续发展做一份自己能做的贡献。 3.控制器的重要因素 蓄电池的放电过程是电动车主要的工作循环之一,也就是电动车的行驶过程,而在行驶过程中控制器则控制着蓄电池的放电参数,因而它也是影响蓄电池循环使用寿命的重要因素。而人们往往忽略这一因素,将影响电动车蓄电池循环使用寿命的责任全部归咎于蓄电池和充电器生产厂家,使蓄电池和充电器生产厂家蒙受许多的不白之冤。 例如:①、大电流放电。一般36V/10AH铅酸蓄电池最大放电电流为1C,即10A放电,而目前电动车厂家为了迎合消费者的市场需求,提高加速动力、提高行驶速度、提高爬坡能力及载荷水平,往往将36V/10AH铅酸蓄电池电动车控制器的限流电流放宽至大于14A(甚至大于20A),这样它各方面的性能指标是提高了,但缩短了蓄电池的循环使用寿命,当然这些问题在用户使用前期是察觉不到的,在使用半年后感觉电动车比以前劲小、充电时充电器不换充饱指示灯等等, ②、过放电。过放电也是直接影响蓄电池循环使用寿命的重要因素,控制器一般均设有欠压保护电路,但要防止使用蓄电池的回升电压(也就是蓄电池停止放电后,每只蓄电池的电压就会回升2V左右)。 4.电机的重要因素 电机是电动自行车中将电池的电能换为动能的装置,电机在这个换过程中有一部分能量是要被电机的换效率消耗掉,电机在不同的电流段中运是有不同的换效率,一般各个电动车厂都会根据不同电动车设置一个最大工作电流,当外来负载较大时,电动自行车的工作电流达到最大值,输入功率也就达到最大值,例如:某电动车最大工作电流设置为12A,工作电压为36V,那最大输入功率就是:12×36=432W。如果电机在432W输入功率的情况下效率可达85%,那输出就是:432×0.85=367.2W。新车使用一段时间后电机的功率与效率会随时间的推移逐渐降低,有可能是75%、65%、55%,因电机的质量水平而定,这时电机的最大输出功率就只有432×0.75=324W、432×0.65=280.8W、432×0.55=237.6W,整车的各项性能指标就会明显下降,电机电驱动系统恶化会引起电池工作电流的增大,在超载能力或效率特性差的情况下,如果一旦出现2次以上恶性使用,电机的永磁体就会出现严重退磁现象,效率特性会全面恶化,导致电池工作电流急剧增加,放电时间急剧减少而使续行里程不足,顾客误认为蓄电池容量已经衰退。有些用户更换了新电池后整车的续行里程还是不足,这就说明并不一定是电池的问题了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值