stm32基于pwm语音播报设计
利用PWM给单片机应用增加语音功能

利用PWM给单片机应用增加语音功能2008-01-14 15:06: ????推荐:0????收藏:0????评论:0???? 来源:单片机及嵌入式系统应用随着嵌入式领域的拓展,目前许多微控制器芯片一般都不具备数据一模拟的双向通道,但几乎都集成有PWM产生模块。
本文利用飞思卡尔公司HCSl2单片机的PWM模块,还原存储在存储器中的声音采样数据,在几乎不增加成本的情况下,实现嵌入式应用中的扩展语音功能。
HCSl2系列单片机未包含数/模转换的模块。
要给其扩展语音功能,通常的做法是增加一块数/模转换芯片。
虽然这样做可以得到非常好的音质(取决于数/模转换芯片的性能),但由于耍多使用一块数/模转换芯片,在对音质要求不太高的应用中,会给设计增加额外的成本,同时也使电路设计相对复杂。
本文介绍利用PWM还原声音的解决方案,可以很好地解决这个矛盾。
例如安全报警应用中,系统通常已经包含了一块微控制器(用来处理人机交互以及系统的控制等),当发出警报时,可以是“BB”或“当当”的蜂鸣声;当然,更好的做法是发出清晰的语音。
用PWM产生声音的基本原理,是使用存储在Flash中的音频采样数据或通过某种算法产生的声音数据,来控制PWM每个波形的占空比;接下来通过一低通滤波器滤波,就可将声音从PWM的脉冲波里分离出来,驱动扬声器发出声音。
1 从WAV文件中提取声音采样数据一般来说,可以从WAV文件中提取声音数据,标准的WAV格式的声音文件含有声音的采样数据和文件头。
文件头描述了后面声音数据的一些信息,如通道数、采样频率、采样位数以及数据的长度等。
通道数,是指声音的采样路数,如单声道、立体声等。
采样频率,是指每秒钟对声音的采样次数,采样频率越高,还原出来的声音越接近原始声音,如表l所列。
要精确还原出某种频率的波形,其最小采样率应为该波形的2倍。
采样位数,指的是每次采样的采样精度。
采样位数越高,还原出来的声音的量化噪声越小,波形也越接近原波形。
基于pwm和stm32的语音录放设计

基于P WM 和S T M 32的语音录放设计*李力,谢云,赵龙辉,陈奕辉,林诗柔(广东工业大学自动化学院,广州510000)*基金项目:广东省自然科学基金(2016A 030313706)㊂摘要:针对智能产品对语音播放的需求和现有系统存在的问题,提出一种基于P C M 的语音录放设计㊂设计采用S TM 32F 103R C T 6作为主控单元,微控制器直接读取P C M 格式的音频数据,通过P WM 方式实现音频的播放㊂该设计能够实现语音录放的功能,输出内容灵活可调,具有一定的应用价值㊂关键词:P C M ;P WM ;微控制器;音频播放;S TM 32F 103R C T 6中图分类号:T N 92 文献标识码:AD e s i g n o f A u d i o P l a y e r S ys t e m B a s e d o n P WM a n d S T M 32L i L i ,X i e Y u n ,Z h a o L o n gh u i ,C h e n Y i h u i ,L i n S h i r o u (S c h o o l o f A u t o m a t i o n ,G u a n g d o n g U n i v e r s i t y o f T e c h n o l o g y ,G u a n gz h o u 510000,C h i n a )A b s t r a c t :A c c o r d i n g t o t h e d e m a n d s o f i n t e l l e c t u a l p r o d u c t s a n d t h e p r o b l e m s o f e x i s t i n g s y s t e m ,a d e s i g n o f v o i c e p l a y b a c k s ys t e m b a s e d o n P u l s e C o d e M o d u l a t i o n (P C M )i s d e s i g n e d .T h e m a i n c o n t r o l u n i t u s e s t h e S TM 32F 103R C T 6.T h e P C M f i l e c a n b e d i r e c t l yr e a d ,a n d p l a y a u d i o t h r o u g h P WM m o d u l a t i o n .T h e d e s i g n e d s y s t e m c a n r e a l i z e t h e e x p e c t e d f u n c t i o n s o f v o i c e p l a y i n g,a n d t h e c o n t e n t o f v o i c e c a n c h a n g e b y y o u r s e l f ,a n d h a s v a l u e f o r a p pl i c a t i o n .K e y wo r d s :P C M ;P WM ;m i c r o c o n t r o l l e r ;v o i c e p l a y ;S TM 32F 103R C T 6引 言随着技术的日益发展,人们对智能设备的要求越来越高,具有音频播放能力的设备逐渐成为主流,出现了多种具有语音输出功能的产品㊂根据播放时输出数据的变换方式,可分为数字模拟播放输出和数字信号直推输出㊂前者是将音频信号解码后通过D A C 的方式输出并推动扬声器进行播放[1-4],音效不理想;使用数字信号直推或放大后进行音频播放[5-8]正逐渐成为主流㊂按照播放载体可分为O T P 语音芯片㊁T T S 语音芯片和使用专用解码器解码播放㊂使用O T P 语音芯片可分为一次性可编程语音芯片和E E P R OM 语音芯片[9],前者只能烧写一次且播放段不可控,后者虽然可以重复擦写且录放一体,但是音频质量往往难以保证,且都需要M C U 对它们进行控制,较为复杂;T T S (T e x t T o S pe e c h ,从文本到语音)语音芯片虽然可将文本合成语音流,并可实现任意段播放,但成本较高;使用专用的音频解码器对音频文件进行解码播放,如基于S TM 32的多功能M P 3设计[10]㊁面向嵌入式系统的音视频解码与同步播放实现[11],实现了语音的解码播放,同样增加了成本㊂因此,本设计提出一种基于P WM 的语音录放设计,系统结构图如图1所示,微控制器与计算机通过串口进行通信,使用X m o d e m 协议来保证在传输时数据的准确性,将P C M 格式的音频数据按照一定的编码格式存放在F L A S H 芯片中㊂利用微控制器的定时/计数器和P WM输出能力实现语音播放㊂与使用解码芯片方案相比,该设计仍使用数据存储芯片与功放输出芯片,但无需使用解码芯片,且输出级不需要高分辨率的数/模转换器[12]㊂图1 语音录放系统结构图该设计要求微控制器可以输出占空比可变的P WM ,并且需要有精确计时到1/16000s 的定时器,即可使M C U 支持语音播放㊂利用P WM 将音频数据还原成语音信号,简化电路的同时占用微控制器资源少,硬件结构简单,降低了工艺成本,可应用于电话应答机㊁各类可编程的需要语音播放仪器仪表或智能家居产品中(如一种基于125k H z 的R F I D 智能锁设计[13]㊁可移动智能无障碍门禁系统设计[14]等),引入音频播放之后可以带来更好的体验和交互㊂本设计以智能锁所需的部分音频进行分析㊂1 系统及基本结构系统主要由控制模块㊁功率放大模块及数据存储模块组成㊂控制模块的核心是S TM 32F 103R C T 6微控制器,进行音频数据的读取和P WM 波生成㊂功率放大模块主要由H T 82V 742音频驱动器I C 构成,它将来自微控制器的P WM 信号输出,直接驱动扬声器㊂数据存储模块存放音频数据,并在微控制器需要时提供数据㊂此外,当需要写入音频数据时,上位机与微控制器间使用串口通信,采用X m o d e m 协议进行数据传输,存储在F L A S H 中㊂2 系统硬件设计本设计采用S TM 32F 103R C T 6微控制器作为主控单片机,硬件设计主要包括3个部分:主控单元㊁功率放大部分及数据存储模块㊂该系列微控制器时钟工作频率可达72MH z ,拥有U A R T ㊁S P I ㊁I 2C 等多个通信接口,主频最高可达72MH z ,其内部搭载的16位高级控制定时器T I M 1和T I M 8可设置为产生输出波形模式(即P WM 输出模式),并支持两路互补输出㊂S T 公司提供丰富的技术文档和库函数封装,以及K e i l 5专门针对该类微控制器推出的编程软件M D K 5也降低了该单片机二次开发的难度㊂2.1 H T 82V 742音频驱动芯片功率放大模块可为主控单元输出的P WM 脉冲进行放大,只需要M C U 支持P WM 输出模式,搭载H T 82V 742音频驱动I C 后便可具有语音播放功能㊂在工作电压为5V ㊁负载为8Ω的工况下,输出功率可达1.5W ,采用B r i d ge T i e d L o a d 输出㊂该音频P WM 放大器具有两个输入引脚和两个输出引脚,输出引脚可直推扬声器㊂其典型应用方框图如图2所示㊂图2 H T 82V 742典型应用电路图中,I N 1㊁I N 2和O U T 1㊁O U T 2之间是同相逻辑关系㊂若I N 1㊁I N 2同时输入为高,则O U T 1和O U T 输出为高;若I N 1㊁I N 2同时输入为低,则O U T 1㊁O U T 2则输出为低㊂如图2所示,M C U 在P WM 1/P WM 2引脚上产生音频P WM 调制信号,配合S u b b a n d C o d i n g 压缩/解压,就可以使得M C U 具有语音功能㊂2.2 数据存储模块数据存储模块的主要功能为存放以P C M 格式编码的语音文件,并且按照一定的索引规则存放㊂设计选用W 25Q 16存储芯片,存储模块电路图如图3所示,该芯片将2M B 存储空间划分为32个块(B l o c k),每个块的大小为64K B ㊂每个块可分为16个扇区(S e c t o r),每个扇区固定大小为4K B ,即每次进行擦除操作时,必须擦除4K B ㊂若以16位的采样精度和16k H z 的采样率来计算,该芯片可存储约65.5s 的音频数据㊂图3 数据存储模块电路图在进行操作时,每次需要给W 25Q 16开辟1个至少4K B 的数据缓存区㊂该器件通过S P I 总线接口进行操作,微控制器通过搭载的S P I 1接口与其进行通信㊂3 系统软件设计3.1 音频数据预处理P C M 是数字通信的编码方式之一,基本原理是将语音㊁图像等模拟信号每隔一定时间进行取样,使其离散化,同时将抽样值按分层单位四舍五入取整量化,同时将抽样值按一组二进制码来表示抽样脉冲的幅值㊂设计中采用微控制器直接读取P C M 文件的方式实现音频播放,因此利用上位机将所需或合成的WA V 格式的音频文件统一进行格式转换并编码㊂在智能锁的交互过程中使用到约22个音频段,然后执行m k f i l e ㊂在b a t 批处理文件中,程序将自动调用 w a v 2p c m.e x e ㊁ c o m b i n e .e x e 和 e n c o d e .e x e 三个应用程序,完成 格式转换 文件组合 文件编码 步骤,并生成b i n 文件㊂编码后的音频存储索引如图4所示㊂图4 数据索引格式设计共使用22段音频,经过处理后生成的b i n 文件中,前16个字节包含该部分语音数据的采样率㊁声道数和采样位数等信息㊂接下来以4个字节为一组,代表22段音频在b i n 文件中的编码地址㊂3.2 音频数据传输微控制器与上位机间采用串口通信,采用X m o d e m协议进行数据的传输,以保证数据的完整性,防止丢包㊂数据包格式如下所示:该协议下传输数据单位为信息包,以128字节块的形式传输数据,并且每个块都使用一个校验过程来进行错误检测㊂在校验过程中,如果接收方关于一个块的检验和与它在发送方的检验相同,接收方就向发送方发送一个确认字节<A C K>;如果有错则发送一个字节<N A K>要求重发㊂其中包括固定数据头帧S OH (0x 01),第2个字节为当前数据包序号,下一个字节是数据包序号的补码,用来检验是否正确发送㊂中间128个字节是本次发送的数据,如果余下不足128字节,则使用C T R L Z (0x 1A )来填充数据包,最后是一个双字节的C R C 16校验㊂3.3 P WM 播放原理及实现脉宽调制(P WM )在多个领域具有多种应用,例如通信系统㊁光学系统㊁功率转换器和音频系统[14]㊂在采样控制原理中有一个重要结论[15]:冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同㊂冲量即指窄脉冲的面积,效果相同是指惯性环节的输出响应波形基本相同[16]㊂波形如图5所示,将正弦半波进行等分,可以看到等分幅值是不相同的㊂用图5(b)中等幅但不等宽的脉冲(即P WM 波)来代替这个正弦半波,每一个等幅不等宽的脉冲与图5(a )的等宽脉冲的冲量(即面积)相同,也就是说可以用P WM 波来近似等效正弦半波,但其中P WM 波输出频率必须与P C M 中的采样频率保持一致㊂利用第3.1节中的P C M 数据流,由模拟信号到数字信号的逆过程可知,使用P WM 波可以近似等效输出原音频波形㊂图5 P WM 波等效正弦半波采用P WM 控制方式来输出音频数据,将存储的P C M 数据转化成一系列等幅不等宽的P WM 信号,其占空比由P C M 数据决定,且采样频率与P WM 的变换频率必须相等㊂设计中微控制器的P WM 输出采用互补输出的方式,通过两个定时/计数器来控制播放㊂因此,设计需要将一个定时/计数器设置为定时器模式,该定时器作为P WM 占空比变化的时钟信号,而另一定时/计数器设置为P WM 输出模式㊂这样,在每一个P WM 波变换的时间节点,将新的P WM 占空比数据写入就可以实现播放功能㊂图6 语音播放程序流程图本设计中原语音数据的采样率是16k H z,因此定时/计数器定时时间为0.0000625s (即1/16000),作为P WM 波变换的时间节点,在中断服务函数中更新P WM 占空比值㊂程序根据字段索引读取语音数据起始地址并确定数据长度,存储在W a v e P l a y L e n g t h 变量中,单次读取的数据量为512字节,当W a v e P l a y L e n g t h 小于等于512时不再读取F L A S H 存储器,完成该次播放,流程图如图6所示㊂4 系统试验与分析为了验证使用P WM 方式播放P C M 语音数据的可行性与实际效果,按流程将P C M 数据使用X M o d e m 文件传输协议通过串口方式发送至微控制器,以保证数据无损和正确地写入F L A S H 存储器中㊂然后运行播放程序,对上述流程进行验证,得到如图7所示的P WM 波形图并通过扬声器判别语音内容,可清晰听到需要播放的语音内容㊂可以看出,输出波形的频率为16k H z,上升时间与下降时间也控制得较为理想,音质得到了保证㊂实际上,常用语音的频率范围约为300~3000H z,音乐的频率范围在20H z ~20k H z 之间㊂而数字式音频播放器的性能主要与采样位数和采样频率有关㊂图7 按键音对应P WM 输出波形图本设计提出的语音录放方案使用16k H z 采样和16位的采样位数,可将日常中使用的语音源文件近似于无损方式输出,在输出采样频率不太高的音乐上也能有很好的效果㊂相比于利用微控制器I /O 定时翻转电平产生驱动信号实现音频播放的方案[18],使用P WM 输出的方案占用微控制器资源少,且驱动信号也更加精确,音频质量得到了提升㊂结 语本文提出了一种基于P WM 的语音播放设计,以S TM 32F 103R C T 6作为主控制器,采用H T 82V 742P WM音频驱动芯片驱动扬声器,实现播放指定音频的任务㊂微控制器直接读取P C M 数据,通过改变P WM 波输出占空比的方式实现语音播放,即任何微控制器只需拥有两个定时精度达到1/16000s 的定时器和P WM 脉冲输出能力,即可通过采用 存储芯片M C U P WM三级架构方式实现语音播放功能,使得语音播放更加便捷㊂同时,可以精确控制语音播放内容,与O T P 语音芯片相比,增强了灵活性,降低了开发成本㊂利用P WM 功率放大器件直接推动扬声器,简化了传统音频输出中的转换及放大电路,实现了一种高效和低成本的语音播放系统㊂该设计架构可广泛应用于各种语音内容相对确定或高音质语音播放场合或产品中,如家电产品㊁智能产品和仪器仪表等,且输出音频的音质可由选用的微控制器P WM 输出频率及定时器位数决定,调节灵活,具有一定的实际应用价值㊂参考文献[1]方永佳.基于M a t l a b 和S TM 32的音频播放设计[J ].工业控制计算机,2016,29(7):151.[2]张仲明,郭东伟,吕巍,等.音频录制与播放系统的设计[J ].实验室科学,2018,21(6):7477.[3]程媛媛,杨文荣.音频数模转换器芯片内部低功耗的设计[J ].计算机测量与控制,2007(11):15841586.[4]杨帅,薛岚,高安邦,等.基于S P C E 061A 智能小车机器人语音播放系统的研究[J ].装备制造技术,2009(7):3839.[5]林桓.A V S 2音频与M P 3的对比及其录制与播放的实现[D ].成都:西南交通大学,2017.[6]杨博,张亚平,丁瑞.多任务音频播放与实时频谱变换的实现[J ].实验技术与管理,2017,34(9):137141.[7]刘伍洋.基于T h r e a d X 系统的I ~2S 音频总线驱动设计方案[J ].单片机与嵌入式系统应用,2018(1).[8]李慧,胡永兵,姚梦茹.基于U C O S I I I 系统的音频信号分析设计与实现[J ].计算机技术与发展,2018,28(7):136139.[9]王南阳.智慧型音乐/语音电路原理及开发应用系列(三)可程式化智能型O T P 系列语音集成电路[J ].电子世界,2005(10):5053.[10]颜锐,谭周文.基于S TM 32的多功能M P 3设计[J ].湖南人文科技学院学报,2013(4):107110.[11]张森永,高树立,陈为刚.面向嵌入式系统的音视频解码与同步播放实现[J ].应用科学学报,2018,36(3):98108.[12]C h a n g C M ,W u J T.A c o m p u t a t i o n a l l y ef f i c i e n t P WM t e c h n i q u e f o r d ig i t a l c l a s s D a m pl i f i e r s [C ]//2016I E E E I n t e r n a t i o n a l S y m p o s i u m o n C i r c u i t s a n d S y s t e m s (I S C A S ).I E E E ,2016.[13]李力,吴卓葵,陈立升.一种基于125k H z 的R F I D 智能锁设计[J ].仲恺农业工程学院学报,2018,31(3):3944.[14]贺升平,李爱国,张鑫.可移动智能无障碍门禁系统设计[J ].测控技术,2017(9):7780.[15]D o m i n gu e s T ,S a n t o s M ,T a v a r e s G.A C l i c k M o d u l a t i o n a u -d i o p l a y e r [C ]//D e s i g n o f C i r c u i t s &I n t e g r a t e d S y s t e m s .I E E E ,2016.[16]李旭,谢运祥.P WM 技术实现方法综述[J ].电源技术应用,2005(2):5155.[17]谢可,姚鸿强.基于P WM 的数字音频播放器设计[J ].计算机应用与软件,2014(5):328329.[18]远飞.基于单片机的音乐播放器的仿真与制作[J ].电子元器件应用,2010(12):4749.李力(硕士研究生),主要从事智能技术与装备方面的研究工作㊂(责任编辑:薛士然 收稿日期:2019-12-11)。
STM32编程输出可调的硬件PWM,频率范围1Hz

STM32编程输出可调的硬件PWM,频率范围1Hz【原创】编程输出可调的硬件PWM,频率范围1Hz-1MHz,占空比0-100%uint32_t TIM4_PWM_FQ = 50; /* TIM4_CH1_PWM输出频率设置值,1-1000000 */uint32_t TIM4_PWM_FQ_Old = 0;uint16_t TIM4_PWM_Pulse = 50; /* TIM4_CH1_PWM输出占空比设置值,0-100 */uint16_t TIM4_PWM_Pulse_Old = 0;uint32_t SystemCoreClock = 168000000;/** 函数功能: 定时器4配置为硬件PWM模式(不开启TIM4的定时及DMA传输中断)* TIM4_PWM_FQ: TIM4_CH1_PWM 频率1Hz至1000000Hz* TIM4_PWM_Pulse: TIM4_CH1_PWM 占空比 0-100%*/void StdPeriph_TIM4_PWM_Config(void){GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;uint32_t temp32;uint32_t uhTimerfrequency;uint16_t uhTimerPeriod;uint16_t uhTimerPulse;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);#ifdef USE_PB6_PWM// TIM4_CH1_PWM: PB6RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);// GPIOB ConfigurationGPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4);#else// TIM4_CH1_PWM: PD12RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);// GPIOD ConfigurationGPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_Init(GPIOD, &GPIO_InitStructure);GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);#endifuhTimerfrequency = 200000; /* 初始化 200KHz */temp32 = ((SystemCoreClock /2) / uhTimerfrequency);if(temp32 > 65535) temp32 = 65535;uhTimerPeriod = (uint16_t) temp32;uhTimerPulse = uhTimerPeriod * 50 / 100; /* 占空比50% */// Time base configurationTIM_TimeBaseStructure.TIM_Period = uhTimerPeriod - 1; /* 0x0000 and 0xFFFF */TIM_TimeBaseStructure.TIM_Prescaler = 0; /* 0x0000 and 0xFFFF */TIM_TimeBaseStructure.TIM_ClockDivision = 0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);// PWM1 Mode configuration: Channel1TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = uhTimerPulse;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC1Init(TIM4, &TIM_OCInitStructure);TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);TIM_ARRPreloadConfig(TIM4, ENABLE);TIM_GenerateEvent(TIM4, TIM_EventSource_Update);TIM_Cmd(TIM4, ENABLE);}/** 函数功能: 刷新TIM4_CH1_PWM输出的频率和占空比* 修改TIM4_PWM_FQ的值,调节PWM频率(1Hz至1MHz)* 修改TIM4_PWM_Pulse的值,调节PWM的占空比(0-100)*/void StdPeriph_TIM4_PWM_Update(void){uint32_t temp32;uint32_t uhTimerfrequency;uint16_t uhTimerPeriod;uint16_t uhTimerPrescaler;uint16_t uhTimerPulse;if ((TIM4_PWM_FQ_Old != TIM4_PWM_FQ) || (TIM4_PWM_Pulse_Old != TIM4_PWM_Pulse)){TIM4_PWM_FQ_Old = TIM4_PWM_FQ;TIM4_PWM_Pulse_Old = TIM4_PWM_Pulse;if(TIM4_PWM_FQ >= 4000){uhTimerfrequency = TIM4_PWM_FQ; /* 定时器计时频率和PWM频率相等 */uhTimerPrescaler = 1; /* 实际频率TIM4_PWM_FQ较大时,TIM4设置分频为1(不分频) */}else{uhTimerfrequency = 4000; /* 实际频率TIM4_PWM_FQ较小时,和4000Hz的频率比较,看相差几倍 */uhTimerPrescaler = 4000 / TIM4_PWM_FQ; /* 实际频率和4000相差的倍数作为TIM4的分频设置值 */uhTimerfrequency = uhTimerPrescaler * TIM4_PWM_FQ; /* TIM4分频后,计时周期变长,需要将uhTimerfrequency倍频 */ }/* TIM4的周期要通过倍频uhTimerfrequency来计算,uhTimerPeriod = 84MHz / uhTimerfrequency */temp32 = ((SystemCoreClock /2) / uhTimerfrequency);if(temp32 > 65535) temp32 = 65535;uhTimerPeriod = (uint16_t) temp32;if(TIM4_PWM_Pulse > 100) TIM4_PWM_Pulse = 100;uhTimerPulse = uhTimerPeriod * TIM4_PWM_Pulse/ 100;TIM4->ARR = uhTimerPeriod - 1;TIM4->PSC = uhTimerPrescaler - 1;TIM4->CCR1 = uhTimerPulse;TIM4->EGR = TIM_PSCReloadMode_Update;}}。
stm32语音播报模块工作原理

stm32语音播报模块工作原理
STM32语音播报模块是一种集成了语音识别、语音合成、音频播放等功能的电子模块。
该模块采用STM32单片机作为核心处理器,通过外接语音识别芯片和音频芯片实现语音的输入和输出。
在工作过程中,STM32语音播报模块首先会接收用户的语音输入,通过语音识别芯片将语音转换为数字信号,并将其传输给STM32单片机。
接下来,STM32单片机通过算法处理和判断,确定用户输入的语音内容,然后根据预设程序进行相应的操作。
比如,用户说“播放音乐”,STM32单片机就会发送相应的指令给音频芯片,触发音频播放。
另外,STM32语音播报模块还配备了语音合成功能,可以将STM32单片机处理的信息转换为语音输出。
在输出语音时,STM32单片机将数字信号发送到音频芯片,音频芯片再将信号转换为模拟信号,从扬声器中发出语音。
总之,STM32语音播报模块是一种功能强大的电子模块,不仅可以实现语音输入和输出,还可以实现音频播放等多种功能。
在智能家居、智能机器人、智能安防等领域,都有广泛的应用前景。
- 1 -。
基于STM32的无线语音交互系统设计

电子技术• Electronic Technology82 •电子技术与软件工程 Electronic Technology & Software Engineering【关键词】STM32 Wi-Fi 网络 TCP/IP 协议 短距通信为了实现工业生产过程全部数据的统一化管理,工业生产中经常需要人机配合完成诸如设备检修、原材料统计等功能。
现场操作人员在现场采集数据,例如设备检修时拍摄设备图片传输到计算机存储,或者原材料统计时拍摄原材料编码传输到计算机存档等,现场操作人员现场采集的数据是否满足要求,需要上位机操作人员将判断结果告知现场操作人员,通过对讲机在一般场合能够实现此功能,但是对讲机无法将通信过程的数据进行存储和归档。
因此需要一套能够满足实施通信,又能将数据归档的系统。
本次设计的无线语音交互系统可以很好地满足生产中短距通信的需要。
无线语音交互系统主要包含三部分:计算机服务器端、无线网络、四台终端。
一台计算机机作为服务器端通过Wi-Fi 网络以TCP/IP 协议可连接四台终端,服务器通过一系列不同的指令,指定的终端的指示灯和语音模块给出提示,终端按键可返回消息;服务器端可将发送和接收的信息存储到MySQL 数据库中,方便以后的检索和追溯。
1 硬件设计终端整体结构主要分为STM32主控芯片及最小系统、供电模块、ESP8266无线通信模块、WT588D 语音模块、按键指示灯等部分,如图1所示。
基于STM32的无线语音交互系统设计文/段宇1 戴舜华2 付鹏飞2 史程程31.1 ARM主控芯片主控芯片采用STM32F103系列单片机,内核是Cortex-M3。
最高达到72MHZ 的运行频率。
支持USART ,I2C ,SPI ,CAN 等众多接口模式,可满足不同条件下的通信需求。
同时该款单片机功耗低,作为无线终端拥有待机时间长的优势。
芯片采用3.3V 供电,采用多重电容滤波的方式使电压达到稳定,外部接有8MHZ 晶振及复位电路,整体构成了主控芯片的最小系统。
基于STM32CubeMX配置PWM输出和输入捕获

基于STM32CubeMX配置PWM输出和输⼊捕获PWM输出和输⼊捕获1、试验⽬标 1.输出2路PWM脉冲信号 2.捕获1路PWM脉冲信号 本次试验会使⽤到2个定时器,⼀个⾼级定时器⽤于脉冲捕获,⼀个普通定时器⽤于PWM脉冲输出。
2、准备材料 1. STM32F103C8 2. STM32CubeMX2、STM32CubeMX配置 2.1时钟树 系统时钟为72M,APB1 和APB2 的定时器时钟都为72MHZ。
2.2 PWM输出配置 PWM的输出配置⽐较简单,这⾥我们使⽤到了TIM2普通定时器控制输出,具体参数如下图。
在 Parameter Settings 页配置预分频系数为 72-1,计数周期(⾃动加载值)为 10000-1,定时器溢出频率,即PWM的周期,就是72MHz/(71+1)/(9999+1) = 100Hz 2.3 PWM输⼊捕获配置 PWM捕获,本次试验使⽤到了STM32F103C8的⾼级定时器TIM1。
配置如下图。
中断配置勾线这⾥,因为我们需要使⽤中断回调函数来计算频率占空⽐。
2.4 配置中断分组和中断使能2.5串⼝输出2.6⽣成⼯程 这⾥选择分离C.h⽂件,IDE 根据⾃⼰的环境选择,这⾥我使⽤的GUN编译⽅式的IDE所以选择了SW4SEM32。
以上CubeMX的PWM配置就完成了。
配置完毕后,⽣成⼯程打开。
下⾯我们来分析代码和如何使⽤。
3、代码实现 3.1 tim.c 该代码主要配置了Tim1 和Tim2 的相关配置,为什么要这么配置,在接下来的第4⼤点会详细说明。
这⾥主要了解HAL_TIM_IC_CaptureCallback 捕获中断回调函数这⾥函数主要处理计算占空⽐和频率。
/********************************************************************************* @file tim.c* @brief This file provides code for the configuration* of the TIM instances.******************************************************************************* @attention** <h2><center>© Copyright (c) 2021 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under BSD 3-Clause license,* the "License"; You may not use this file except in compliance with the* License. You may obtain a copy of the License at:* /licenses/BSD-3-Clause********************************************************************************//* Includes ------------------------------------------------------------------*/#include "tim.h"/* USER CODE BEGIN 0 *//// 计算占空⽐时使⽤__IO uint16_t IC2Value = 0;__IO uint16_t IC1Value = 0;__IO float DutyCycle = 0;__IO float Frequency = 0;/* USER CODE END 0 */TIM_HandleTypeDef htim1; // ⾼级定时器捕获PWMTIM_HandleTypeDef htim2; // 普通定时器输出PWM/* TIM1 init function */void MX_TIM1_Init(void){TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_SlaveConfigTypeDef sSlaveConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_IC_InitTypeDef sConfigIC = {0};htim1.Instance = TIM1;htim1.Init.Prescaler = 72-1;htim1.Init.CounterMode = TIM_COUNTERMODE_UP; /* 计数⽅式上计数 */htim1.Init.Period = 65535; /* 计数器更新上限值 */htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /* 采样时钟分频 */htim1.Init.RepetitionCounter = 0; /* 重装值=0 */htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; /* ⾃动装载值软件使能 */ if (HAL_TIM_Base_Init(&htim1) != HAL_OK) /* 初始定时器 */{Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; /* 内部时钟源 */if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK){Error_Handler();}if (HAL_TIM_IC_Init(&htim1) != HAL_OK){Error_Handler();}///选择从模式: 复位模式sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;sSlaveConfig.InputTrigger = TIM_TS_TI1FP1; /* 选择定时器输⼊触发: TI1FP1 */ sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;sSlaveConfig.TriggerFilter = 0;if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK){Error_Handler();}///IC1捕获上升沿触发 TI1FP1sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;sConfigIC.ICFilter = 0;if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1) != HAL_OK){Error_Handler();}///IC2捕获下降沿捕获 TI1FP2sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2) != HAL_OK){Error_Handler();}}/* TIM2 init function */void MX_TIM2_Init(void){TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_OC_InitTypeDef sConfigOC = {0};htim2.Instance = TIM2;/** htim2.Init.Prescaler 分频计算* 定时器时钟源TIMxCLK = 2 * PCLK1* PCLK1 = HCLK / 2* => TIMxCLK = HCLK/2 = SystemCoreClock / 2 *2=72MHz (APB1)* 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10KHz* */htim2.Init.Prescaler = 72-1;htim2.Init.CounterMode = TIM_COUNTERMODE_UP; /* 计数⽅式上升沿有效 */htim2.Init.Period = 10000-1; /* 累计 TIM_Period个后产⽣⼀个更新或者中断当定时器从0计数到10000,即为10000次,为⼀个定时周期*/ htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;if (HAL_TIM_Base_Init(&htim2) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; /* 内部时钟源 */if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK){Error_Handler();}if (HAL_TIM_PWM_Init(&htim2) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK){Error_Handler();}///PWM模式配置sConfigOC.OCMode = TIM_OCMODE_PWM1; /* 配置为PWM模式1*/sConfigOC.Pulse = 5000; /* 默认占空⽐为50%*/sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; /* 当定时器计数值⼩于CCR1_Val时为⾼电平*/sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) /* 配置PWM通道*/{Error_Handler();}if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK){Error_Handler();}HAL_TIM_MspPostInit(&htim2); /* 外置GPIO初始化 */}void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle){GPIO_InitTypeDef GPIO_InitStruct = {0};if(tim_baseHandle->Instance==TIM1){/* USER CODE BEGIN TIM1_MspInit 0 *//* USER CODE END TIM1_MspInit 0 *//* TIM1 clock enable */__HAL_RCC_TIM1_CLK_ENABLE(); /*定时器时钟使能*/__HAL_RCC_GPIOA_CLK_ENABLE(); /*GPIO时钟使能*//**TIM1 GPIO ConfigurationPA8 ------> TIM1_CH1*/GPIO_InitStruct.Pin = GPIO_PIN_8; /* 36脚的F103 不能改变引脚编号*/GPIO_InitStruct.Mode = GPIO_MODE_INPUT; /* 输⼊模式*/GPIO_InitStruct.Pull = GPIO_NOPULL; /* ⽆上下拉*/HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* TIM1 interrupt Init */HAL_NVIC_SetPriority(TIM1_CC_IRQn, 0, 0); /* 配置中断分组*/HAL_NVIC_EnableIRQ(TIM1_CC_IRQn); /* 使能中断*//* USER CODE BEGIN TIM1_MspInit 1 *//* USER CODE END TIM1_MspInit 1 */}else if(tim_baseHandle->Instance==TIM2){/* USER CODE BEGIN TIM2_MspInit 0 *//* USER CODE END TIM2_MspInit 0 *//* TIM2 clock enable */__HAL_RCC_TIM2_CLK_ENABLE();/* USER CODE BEGIN TIM2_MspInit 1 *//* USER CODE END TIM2_MspInit 1 */}}void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle){GPIO_InitTypeDef GPIO_InitStruct = {0};if(timHandle->Instance==TIM2){/* USER CODE BEGIN TIM2_MspPostInit 0 *//* USER CODE END TIM2_MspPostInit 0 */__HAL_RCC_GPIOA_CLK_ENABLE();/**TIM2 GPIO ConfigurationPA0-WKUP ------> TIM2_CH1PA1 ------> TIM2_CH2*/GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; /* 这⾥定义了2路PMW输出⽤PA0 和PA1*/ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USER CODE BEGIN TIM2_MspPostInit 1 *//* USER CODE END TIM2_MspPostInit 1 */}}void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle){if(tim_baseHandle->Instance==TIM1){/* USER CODE BEGIN TIM1_MspDeInit 0 *//* USER CODE END TIM1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM1_CLK_DISABLE();/**TIM1 GPIO ConfigurationPA8 ------> TIM1_CH1*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8);/* TIM1 interrupt Deinit */HAL_NVIC_DisableIRQ(TIM1_CC_IRQn);/* USER CODE BEGIN TIM1_MspDeInit 1 *//* USER CODE END TIM1_MspDeInit 1 */}else if(tim_baseHandle->Instance==TIM2){/* USER CODE BEGIN TIM2_MspDeInit 0 *//* USER CODE END TIM2_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM2_CLK_DISABLE();/* USER CODE BEGIN TIM2_MspDeInit 1 *//* USER CODE END TIM2_MspDeInit 1 */}}/* USER CODE BEGIN 1 *//*** @brief Conversion complete callback in non blocking mode 捕获回调函数* @param htim : hadc handle* @retval None*/void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){/* 获取输⼊捕获值 */IC1Value = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1);IC2Value = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_2);if (IC1Value != 0){/* 占空⽐计算 */DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1);/* 频率计算 */Frequency = 72000000/72/(float)(IC1Value+1);}else{DutyCycle = 0;Frequency = 0;}}}/* USER CODE END 1 *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/3.2 main.c ⽤于计算的变量//计算占空⽐时的全局表变量extern __IO uint16_t IC2Value;extern __IO uint16_t IC1Value;extern __IO float DutyCycle;extern __IO float Frequency; 使能和输出PWM/// 使能捕获/⽐较2中断请求HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_1);HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_2);/// 开始输出PWMHAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); 打印调试输出while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */printSwo("IC1Value =",IC1Value,LINE_FEED_EN);printSwo("IC2Value =",IC2Value,LINE_FEED_EN);printSwo("占空⽐:",DutyCycle,LINE_FEED_EN);printSwo("频率:",Frequency,LINE_FEED_EN);HAL_Delay(500);}3.3 输出结果短接任意⼀路输出 PA0与PA8 PWM输出与捕获,或 PA1与PA8 PWM输出与捕获。
pwm语音播报

基于PWM的语音播报设计班级:专业:姓名:学号:东华理工大学利用PWM进行数字语音的播报设计摘要随着嵌入式领域的拓展,目前许多微控制器芯片一般都不具备数据一模拟的双向通道,但几乎都集成有PWM产生模块。
本文利用飞思卡尔公司HCSl2单片机的PWM模块,还原存储在存储器中的声音采样数据,在几乎不增加成本的情况下,实现嵌入式应用中的扩展语音功能。
关键词单片机PWM 语音低通滤波HCSl2系列单片机未包含数/模转换的模块。
要给其扩展语音功能,通常的做法是增加一块数/模转换芯片。
虽然这样做可以得到非常好的音质(取决于数/模转换芯片的性能),但由于耍多使用一块数/模转换芯片,在对音质要求不太高的应用中,会给设计增加额外的成本,同时也使电路设计相对复杂。
本文介绍利用PWM还原声音的解决方案,可以很好地解决这个矛盾。
例如安全报警应用中,系统通常已经包含了一块微控制器(用来处理人机交互以及系统的控制等),当发出警报时,可以是“BB”或“当当”的蜂鸣声;当然,更好的做法是发出清晰的语音。
用PWM产生声音的基本原理,是使用存储在Flash中的音频采样数据或通过某种算法产生的声音数据,来控制PWM每个波形的占空比;接下来通过一低通滤波器滤波,就可将声音从PW M的脉冲波里分离出来,驱动扬声器发出声音。
1 从WAV文件中提取声音采样数据一般来说,可以从WAV文件中提取声音数据,标准的WAV 格式的声音文件含有声音的采样数据和文件头。
文件头描述了后面声音数据的一些信息,如通道数、采样频率、采样位数以及数据的长度等。
通道数,是指声音的采样路数,如单声道、立体声等。
采样频率,是指每秒钟对声音的采样次数,采样频率越高,还原出来的声音越接近原始声音,如表l所列。
要精确还原出某种频率的波形,其最小采样率应为该波形的2倍。
采样位数,指的是每次采样的采样精度。
采样位数越高,还原出来的声音的量化噪声越小,波形也越接近原波形。
WAV文件的文件头定义:提取声音数据时,请注意采样频率、采样位数、存储容量与存储时间的关系,如表2所列。
KeilMDKSTM32系列(八)STM32F4基于HAL的PWM和定时器输出音频

KeilMDKSTM32系列(⼋)STM32F4基于HAL的PWM和定时器输出⾳频Keil MDK STM32系列⽅式1: 通过PWM和TIM输出⾳频机制⾳频使⽤⼀个预⽣成的的8bit⽆符号数组, 采样率为8KHz输出包含两部分, ⼀部分是TIM2产⽣连续的PWM, PWM分辨率设置为256, 正好对应8bit PCM采样输出的第⼆部分是TIM3产⽣的定时中断, 中断的频率正好是8KHz, 每次中断都修改⼀次PWM的占空⽐通过调节PWM频率可以调节输出⾳质, PWM频率越⾼⾳质越好(谐振频率越远离⾳频)通过调节PWM分辨率可以调节⾳量, PWM分辨率越⾼, ⾳量越低配置STM32CubeMX选择芯⽚STM32F401CCU6, 创建新项⽬系统时钟System Core -> SYS-> Debug: Serial WireSystem Core -> RCC-> High Speed Clock (HSE): Crystal/Ceramic Resonator 启⽤外接⾼速晶振Clock Configuration: (配置为最⾼84MHz)选择外部晶振, 连接HSE和PLLCLK, 在HCLK上输⼊84回车, 软件会⾃动调节各节点倍数PWM(使⽤TIM2)Timers -> TIM2Clock Source: Internel Clock, 使⽤系统的时钟源Channel1: PWM Generation CH1Counter Settings PWM频率 = 84MHz / (Perscaler + 1) / (Counter Period + 1)Perscaler: 0Counter Mode: UpCounter Period: 255Internal Clock Division(CKD): No Divisionauto-reload preload: EnableTrigger OutputMaster/Slave Mode (MSM bit): DisableTrigger Event Selection: Reset (UG bit from TIMx_EGR)PWM Generation Channel 1Mode: PWM mode 1Pulse: 0Output compare perload: EnableFast Mode: DisableCH Polarity: High8KHz定时中断(使⽤TM3)Timers -> TIM3勾选 Internal ClockCounter SettingsPrescaler: 0Counter Mode: UpCounter Period: 10499 # 10500 = 84MHz / 8KHzInternal Clock Division (CKD): No divisionauto-reload preload: DisableTrigger Output (TRGO) ParametersMaster/Slave Mode (MSM bit): DisableTrigger Envent Selection: ResetNVIC SettingsTIM3 global interrupt: Enable代码修改通过STM32CubeMX⽣成代码后, 需要对main.c添加代码/* USER CODE BEGIN PV */uint8_t pwm_buf[] = {125, 125, ..., 126, 125}; // 这⾥是⼀个长数组, 可以⾃⼰通过⼯具⽣成uint8_t *start = pwm_buf, *end = pwm_buf, *lb = pwm_buf, *rb = (pwm_buf + 27451); // 27451是数组长度/* USER CODE END PV */main函数int main(void){HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM2_Init();MX_TIM3_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);HAL_TIM_Base_Start_IT(&htim3);/* USER CODE END 2 */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}}添加定时器中断处理函数/* USER CODE BEGIN 4 */void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){if(htim->Instance==TIM3){__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, *start++);if (start == rb) {start = lb;}}}/* USER CODE END 4 */输出效果演⽰⽅式2: 通过PWM+DMA通过配置成DMA的⽅式, 可以省掉⼀个定时器, 并且不需要主进程介⼊⽽直接将数组赋值给PWM.这⾥有个需要注意的地⽅, STM32F401的各个TIMx计数器位宽不同, TIM2,TIM5是32bit, 其它的都是16bit, ⽽STM32F103的TIMx全是16bit位宽的. 之前在这个问题上困惑了很长时间, 后来费了不少⼯夫测试, 加上对⽐其它项⽬代码的配置才找到原因.在设置DMA时, DMA_HandleTypeDef.Init.PeriphDataAlignment要与TIMx的计数器位宽⼀致, 如果没设置成⼀致会导致PWM输出错误.⽽MemDataAlignment要与数组的数据类型⼀致, 实际上也要设置成对应的位宽.根据ST的⼿册如果勾选了FIFO, 可以设置为其它位宽, 系统会⾃动补位, 但是实际测试并不能, ⽆论如何调整FIFOThreshold, MemBurst, ⾳频的前半部分都是错误的, 只能播放后半部分. 原因待查.配置STM32CubeMX选择芯⽚STM32F401CCU6, 创建新项⽬系统时钟System Core -> SYS-> Debug: Serial WireSystem Core -> RCC-> High Speed Clock (HSE): Crystal/Ceramic Resonator 启⽤外接⾼速晶振Clock Configuration: (配置为最⾼84MHz)选择外部晶振, 连接HSE和PLLCLK, 在HCLK上输⼊84回车, 软件会⾃动调节各节点倍数PWM(使⽤TIM3)Timers -> TIM3Internel Clock: 勾选, 使⽤系统的时钟源Channel1: PWM Generation CH1Counter Settings PWM频率 = 84MHz / (Perscaler + 1) / (Counter Period + 1)Perscaler: 40Counter Mode: UpCounter Period: 255Internal Clock Division(CKD): No Divisionauto-reload preload: EnableTrigger OutputMaster/Slave Mode (MSM bit): DisableTrigger Event Selection: Reset (UG bit from TIMx_EGR)PWM Generation Channel 1Mode: PWM mode 1Pulse: 0Output compare perload: EnableFast Mode: DisableCH Polarity: HighDMA Settings: AddDMA Request: TIM3_CH1/TrigStream: DMA1 Stream4Direction: Memory To PeripheralPriority: HighMode: CircularIncrement Address: Peripheral[不勾选], Memory[勾选]Use Fifo: 不勾选Data Width: Peripheral[Half Word], Memory[Half Word]代码修改只需要在main.c中添加变量和启动⽅法/* USER CODE BEGIN PV */uint16_t pwm_buffer[] = {125, 125, 128, ...};/* USER CODE END PV *///...MX_TIM3_Init();/* USER CODE BEGIN 2 */HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, (uint32_t *)pwm_buffer, 27452);/* USER CODE END 2 */在PA6上就能观察到PWM, 接上喇叭能听到输出. 这种⽅式因为基频8KHz就在⼈⽿的听觉范围内, 会有持续的明显的⾼频声, 通过增加RC低通滤波能改善但是⽆法消除, 最好的⽅式还是将基频提升到20KHz以上, 这样基本上就不会被⼈⽿感知了.参考详细说明了STM32的DMA⼯作⽅式DMA+PWM的位宽讨论另⼀个位宽相关的讨论。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
嵌入式设计论文
…基于PWM的语音0~9数字播报班级: 1221201
专业:测控技术与仪器
姓名:朱宇杰
学号: 201220120118
指导老师:钟老师
东华理工大学
利用PWM进行数字语音的播报设计
摘要随着嵌入式领域的拓展,目前许多微控制器芯片一般都不具备数据一模拟的双向通道,但几乎都集成有PWM产生模块。
本文利用stm32单片机的PWM模块,还原存储在存储器中的声音采样数据,在几乎不增加成本的情况下,实现嵌入式应用中的扩展语音功能。
关键词stm32 PWM 语音低通滤波
STM32的PWM精讲
通过对TIM1定时器进行控制,使之各通道输出插入死区的互补PWM输出,各通道输出频率均为17.57KHz。
其中,通道1输出的占空比为50%,通道2输出的占空比为25%,通道3输出的占空比为12.5%。
各通道互补输出为反相输出。
TIM1定时器的通道1到4的输出分别对应PA.08、PA.09、PA.10和PA.11引脚,而通道1到3的互补输出分别对应PB.13、PB.14和PB.15引脚,中止输入引脚为PB.12。
将这些引脚分别接入示波器,在示波器上观查相应通道占空比的方波配置好各通道后, 编译运行工程;点击MDK 的Debug菜单,点击
Start/Stop Debug Session;通过示波器察看PA.08、PA.09、PA.10、PB.13、PB.14、PB.15的输出波形,其中PA.08和PB.13为第一通道和互补通道,PB.09和PB.14为第二通道和其互补通道,PB.10和PB.15为第三通道和其互补通道;第一通道显示占空比为50%,第二通道占空比为25%,第三通道占空比为12.5%。
STM32处理器概述
STM32F103xx增强型系列产品中内置了多达3个同步的标准定时器。
每个定时器都有一个16位的自动加载递加/递减计数器、一个16位的预分频器和4个独立的通道,每个通道都可用于输入捕获、输出比较、PWM和单脉冲模式输出,在最大的封装配置中可提供最多12个输入捕获、输出比较或PWM通道。
它们还能通过定时器链接功能与高级控制定时器共同工作,提供同步或事件链接功能。
在调试模式下,计数器可以被冻结。
任一个标准定时器都能用于产生PWM输出。
每个定时器都有独立的DMA请求机制。
PWM概述
PWM是Pulse Width Modulation的缩写,中文意思就是脉冲宽度调制,简称脉宽调制。
它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,其控制简单、灵活和动态响应好等优点而成为电力电子技术最广泛应用的控制方式,其应用领域包括测量,通信,功率控制与变换,电动机控制、伺服控制、调光、开关电源,甚至某些音频放大器,因此研究基于PWM技术的正负脉宽数控调制信号发生器具有十分重要的现实意义。
PWM是一种对模拟信号电平进行数字编码的方法。
通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。
PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。
电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。
通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。
只要带宽足够,任何模拟值都可以使用PWM进行编码。
多数负载(无论是电感性负载还是电容性负载)需要的调制频率高10Hz,通常调制频率为1kHz到200kHz之间。
占空比是接通时间与周期之比;调制频率为周期的倒数。
目前,运动控制系统或电动机控制系统中实现PWM的方法主要有传统的数字电路方式、专用的PWM集成电路、单片机实现方
式和可编程逻辑器件实现方式。
用传统的数字电路实现PWM,电路设计较复杂,体积大,抗干扰能力差,系统的控制周期较长。
专用的PWM集成电路或带有PWM的单片机价格较高。
对于单片机中无PWM输出功能的情况,实现PWM将消耗大量的时间,大大降低了CPU的效率,而且得到的PWM信号精度不太高
数字播报设计思路
如安全报警应用中,系统通常已经包含了一块微控制器(用来处理人机交互以及系统的控制等),当发出警报时,可以是“B B”或“当当”的蜂鸣声;当然,更好的做法是发出清晰的语音。
用PWM产生声音的基本原理,是使用存储在Flash中的音频采样数据或通过某种算法产生的声音数据,来控制PWM每个波形的占空比;接下来通过一低通滤波器滤波,就可将声音从P WM的脉冲波里分离出来,驱动扬声器发出声音。
1 从WAV文件中提取声音采样数据
一般来说,可以从WAV文件中提取声音数据,标准的WA V格式的声音文件含有声音的采样数据和文件头。
文件头描述了后面声音数据的一些信息,如通道数、采样频率、采样位数以及数据的长度等。
我们先对0~9这几个数字进行发音,通过器件进行采集,转化为WAV格式。
通道数,是指声音的采样路数,如单声道、立体声等。
采样频率,是指每秒钟对声音的采样次数,采样频率越高,还原出
来的声音越接近原始声音,如表l所列。
要精确还原出某种频率的波形,其最小采样率应为该波形的2倍。
采样位数,指的是每次采样的采样精度。
采样位数越高,还原出来的声音的量化噪声越小,波形也越接近原波形。
WAV
文件的文件头定义:
提取声音数据时,请注意采样频率、采样位数、存储容量与存储时间的关系,如表2所列。
通常,11.025 kHz的采样频率和8位的采样位数可获得清晰的语音以及较好的音乐声,并且占有较少的存储空间。
通过了解和分析WAV文件的格式,可以将文件中的声音采样数据读取出来,并转换为C语言格式的数组结构,以便和其他程序一并编译和下载到芯片中去。
例如:
2 产生PWM波形
要还原声音,最低要求是HCSl2系列微控制器具备一个PWM 模块,芯片选择的另一个细节是要有足够的Flash存储容量,来存储声音的采样数据。
MC9S12DP256具有一个16位的PWM模
块.可产生16位解析精度的PWM波形,这意味着nr以使用1 6位的采样数据来产生PWM。
MC9S12DP256还具备256 KB的Flash,能够存储23 78 s八位11.025 kHz的采样数据。
产生PWM波形的步骤:①设置定时器.产生定时中断:如采样率为ll.025 kHz.则设置定时器的定时中断频率为11.025 kHz。
②初始化PWM模块,产生11.025kHz的PWM波形。
③等待定时器中断,在中断处理程序中取采样数据,并设置PWM占空比寄存器,判断声音是否播放完成。
若完成,则关定时器巾断,并停止PWM输出。
3 低通滤波
PWM输出后须通过低通滤波器滤波,才能还原成人耳能识别的声音。
低通滤波器的类型和参数取决于声音的采样频率和价格预算。
最简单的要数RC滤波器。
这种滤波器的优点是仪需要两个元件,另一种是有源滤波器,滤波效果好,但相对复杂。
滤波器截止频率的选择,对于音频输出是非常重要的,推荐设置在采样频率的一半。
若要获得更佳的滤波器截止频率,就要进一步对采样数据进行分析,找出最大具有有效声音数据的频
率。
当然,在一般应用中并没有要求这么严格,甚至在某些场合
中,即使用参数不非常明确的元件也能获得很好的声音输出,这时RC滤波器将是最好的选择。
推荐使用图1所示的滤波器,其截止频率为5.5 kHz(11.0 25 kHz/2)。
这个设计中,使用了2个运算放大器,足够驱动一小型扬声器。
图2也给出一种简单直接的接法:仅使用一22μF的电容用于低通滤波,驱动一5 kHz、8Ω的小扬声器。
结语
利用stm32微控制器的PWM功能可为单片机的应用增加语音功能。
对声音采样数据的存储方式是用直接的、原始的采样数据。
在具体的实际应用中,为存储更长时间的声音数据,还可对声音数据进行压缩。