查看: 3183|回复: 5

[原创] 以YL-KL26Z开发板制作会讲故事的书——2

[复制链接]
  • TA的每日心情
    奋斗
    2023-2-15 00:12
  • 签到天数: 969 天

    连续签到: 1 天

    [LV.10]以坛为家III

    175

    主题

    2843

    帖子

    34

    金牌会员

    Rank: 6Rank: 6

    积分
    7123
    最后登录
    2023-4-20
    发表于 2015-11-22 22:43:24 | 显示全部楼层 |阅读模式
    若此时不能听到声音,你也不必着急,试着转动红色的电位器旋钮,直至触摸板下的3个指示灯全部亮起,则说明音量是最大了,此时就应听到播放的声音。若还不能发出声音,就属异常情况了。
    语音播放的工作原理
    实现语音播放功能主要经过的环节有:指定播放文件->读取SD卡->数据缓冲区缓存数据->PIT周期性输出数据->DCA输出模拟信号->运放功率放大->扬声器还原语音输出
    在这个过程中,使用的SD卡为mini型高容量SD卡,其容量介于2GB到32GB之间,采用FAT32文件系统格式,在使用中我需要的是4GB的SD卡。
    那么SD卡有何特点呢?
    SD卡是一种基于Flash存储器的新型存储设备,被广泛应用于便携式装置上,具有读取速度快和存储容量大的特点。一般是采9针的接口与专用驱动器相连,不需要额外的电源来保持信息,由于是一种固体介质,所以不必担心运动性损坏。
    SD卡定义了两种通讯协议来传递信息,一种是SD接口,另一种则是SPI接口。对于YL-KL26Z开发板,其所用的是SPI接口。对于K60 所采用的则是SD接口。
    在使用SD卡时,需用到SD初始化函数SD_Init()及SD卡读取函数。在SD卡的读取操作中是以扇区为单位的,一个扇区包含512个字节。
    由于语音信息是以音频文件方式存储的,因而还需要文件管理函数的配合,所用的函数有TAT初始化函数FAT_Init()、根目录搜索函数FAT_DisDir()、读取扇区函数FAT_LoadPartCluster()和读取下一个扇区函数AT_NextCluster()。
    在数据输出由于方面,由于音频文件的格式为16KHz 采样率的8bit数据,所以在输出时是借助PIT周期中断定时器来等间隔的频率来读取缓冲区中的数据进行输出,其频率会与16KHz 的采样率相匹配。
    在数模转换方面是采用微控器内部的DAC转换器,其转换精度为12bit,较音频的8bit数据要高。
    为了便于动态地调节音量,是采用微控器内部的模数转换器来完成的,其转换精度为16bit。在数据位数统一方面是由下面2条语句来实现:
       Volume=Volume_Num*adcGetUint()>>16;
       dacTrigger(Buffer[FIFO_out]/(Volume_Num-Volume));
       在音量指示方面是以3个LED等来反应,它是将A/D转换器的采用值分为3个等级来处理的,其判别值依次为AD_Sample_Num/3、2*AD_Sample_Num/3和AD_Sample_Num。
    程序改进与完善
    如果你要播放自己的声音文件,可以通过电脑中附件的录音机来录制,当然对语音文件的格式是有要求的,即以16KHz 采样率8bit 格式的音频文件。此外,如果你有其它格式的声音文件,也可通过相应的软件转换为该格式的文件来使用。
    此时,你是否觉得一切技术方面的问题都已解决了呢?回答是否定的,因为故事通常是由多个故事段组成的,要想播放多段语音就必须对程序进行改造。改造的对象选取main.c文件即可,方法是在适当的位置添加一个循环,使播放文件的过程反复进行直到退出为止,期间通过变换相应的文件名即可达到变换播放内容的需要。
    但通过实践你会发现这一想法很难实现,似乎程序从未离开第一段程序的播放,根本就无法脱离出来,问题出在哪里呢?
    仔细研读程序,可以发现有这样一条语句,即while(size<FileInfo.Size)。
    其含义是当size变量的值不小于文件长度FileInfo.Size时,则退出数据的读取过程。然而遍寻整个主函数也没发现一条更改size变量的语句,程序又怎能退出数据读取过程那,程序是一段永无休止的死循环呀!
    那如何来修改size变量呢?通过程序分析可以发现,size是与扇区及簇分不开的。因为在SD卡的读取过程中其基本单位不是字节而是扇区,所以无法直接以字节数来作为判别条件,因采用语句:size=size+SectorsPerClust*512;
    在程序运行中,为了能够控制语音播放的节奏,可用K3 键来限制下一段语音的播放时机。其方法是在退出数据读取后,添加一条等待语句,其内容为:while((FGPIOD_PDIR & 1<<6) == 1<<6);
    随着节奏控制的实现,此时会有一个新的问题出现,就是伴随语音内容的结束,机制而起的是无规则的噪音声。这又是什么原因导致的?原来随着正常语音数据输出的结束,DAC的输出过程并未停止,所以就出现了无规则的噪音声。解决的方法是设置输出字节计数器size2和文件长度存储变量size1,当输出字节等于文件长度时就关断DAC的输出,其语句为:
      if(size2 < size1) dacTrigger(Buffer[FIFO_out]/(Volume_Num-Volume));

    评分

    参与人数 1NXP金币 +10 收起 理由
    小七 + 10 赞一个!

    查看全部评分

    回复

    使用道具 举报

  • TA的每日心情
    开心
    2017-1-24 09:50
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    654

    主题

    3262

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    13136
    最后登录
    2019-1-27
    发表于 2015-11-23 09:16:15 | 显示全部楼层
    支持一下楼主
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2024-1-6 07:38
  • 签到天数: 736 天

    连续签到: 1 天

    [LV.9]以坛为家II

    21

    主题

    3486

    帖子

    6

    金牌会员

    Rank: 6Rank: 6

    积分
    5093
    最后登录
    2024-1-7
    发表于 2015-11-23 09:20:19 | 显示全部楼层
    谢谢分享
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-1-6 07:38
  • 签到天数: 736 天

    连续签到: 1 天

    [LV.9]以坛为家II

    21

    主题

    3486

    帖子

    6

    金牌会员

    Rank: 6Rank: 6

    积分
    5093
    最后登录
    2024-1-7
    发表于 2015-11-23 09:53:55 | 显示全部楼层
    支持一下
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    该用户从未签到

    9

    主题

    642

    帖子

    0

    高级会员

    Rank: 4

    积分
    748
    最后登录
    1970-1-1
    发表于 2015-11-23 10:24:16 | 显示全部楼层
    感谢分享
    104930kli5jsmlssemljli.png
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 21:29
  • 签到天数: 2457 天

    连续签到: 13 天

    [LV.Master]伴坛终老

    17

    主题

    5366

    帖子

    5

    金牌会员

    Rank: 6Rank: 6

    积分
    11311
    最后登录
    2025-7-25
    发表于 2015-11-23 20:20:31 | 显示全部楼层
    谢谢分享
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-26 13:48 , Processed in 0.098444 second(s), 26 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表