博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
电赛初探(二)——语音采集回放系统
阅读量:5062 次
发布时间:2019-06-12

本文共 7952 字,大约阅读时间需要 26 分钟。

一、系统结构

1.基本要求

  (1)话音/功率放大器增益均可调;
  (2)带通滤波器:通带为300Hz~3.4kHz ;
  (3)ADC:采样频率f s=8kHz,字长不小于8位;
  (4)语音存储时间≥10秒;
  (5)DAC:变换频率f c=8kHz,字长不小于8位;
  (6)回放语音质量良好。

2.发挥部分

在保证语音质量的前提下:

  (1)减少系统噪声电平,增加自动音量控制功能;
  (2)语音存储时间增加至20秒以上;
  (3)提高存储器的利用率(在原有存储容量不变的前提下,提高语音存储时间);
  (4)把采集的语音信号在显示屏上显示。

 

二、咪头放大电路设计

1、电路仿真

2、要点:

(1) 系统的增益主要通过R5这个滑动变阻器来控制,咪头采集的信号的幅值,必须控制好,否则在进入AD转换后会导致失真。

(2) 必要时可不需要第二级运放电路,第二级电路只是起一个转接下一级的作用。

(3) 由于咪头采集的信号不仅仅是音频信号,所以之后必须加入一个带通滤波过滤掉无用信号。

 

三、带通滤波器的设计

1、设计软件

 

2、电路仿真

 

3、设计要点

(1)选取高Q值,且斜率比较陡的电路较好。

(2)一般需要强制阶数,要不电路太庞大

(3)明白调节增益的关键电阻。

 

四、AD0809设计

1、程序如下:

#ifndef _ADC0809_H#define _ADC0809_H#include "stm32f10x.h"#include "init.h"#include "stm32f10x_gpio.h"#include "stm32f10x_tim.h"//ADC0809µÄ¿ØÖƶË-GPIOA#define CLK GPIO_Pin_0//µØÖ·ÊÖ¶¯ÉèÖÃ//#define A     GPIO_Pin_1//#define B        GPIO_Pin_11//#define C   GPIO_Pin_3#define ALE GPIO_Pin_4 //µØÖ·Ëø´æÔÊÐíÐźÅÊäÈë¶Ë£¬ALE=1£¬µØÖ·Ëø´æ#define ST    GPIO_Pin_5 //ת»»Æô¶¯ÐźÅ#define OE    GPIO_Pin_6 //Êä³öÔÊÐí¿ØÖƶˣ¬OE=1,Êä³öת»»Êý¾Ý//ADC0809µÄÊý×ÖÊä³ö-GPIOB#define D0     GPIO_Pin_0#define D1     GPIO_Pin_1#define D2     GPIO_Pin_2#define D3     GPIO_Pin_3#define D4    GPIO_Pin_4#define D5     GPIO_Pin_5#define D6     GPIO_Pin_6#define D7     GPIO_Pin_7#define EOC GPIO_Pin_8 //ת»»½áÊøÐźţ¬EOC=1ʱ£¬×ª»»½áÊøvoid adc0809_init(void);u8 adc0809_input(void); //AD²ÉÑùvoid ADC0809_Clock(void); //ADC0809Clock²¨#endif
#include "adc0809.h"#include "gpio.h"#include "timer.h"#include "pbdata.h"void adc0809_init(void){    //Êä³ö¹Ü½Å    set_out(GPIOA, CLK|ALE|ST|OE);        //ÊäÈë¹Ü½Å    set_FIN(GPIOB, D0|D1|D2|D3|D4|D5|D6|D7|EOC);    timer2_pwm(600*1000, 0.5); //A0¹Ü½Å        set_outL(GPIOA, ALE);//µØÖ·ÊÖ¶¯ÉèÖÃ//    set_outL(GPIOA, A);//    set_outL(GPIOA, B);//    set_outL(GPIOA, C);    delay_us(5);    set_outH(GPIOA, ALE); //µØÖ·Ëø´æ}u8 adc0809_input() //AD²ÉÑù{    u8 val;    //ST²úÉúÉÏÉýÑغÍϽµÑØ£ºÉÏÉýÑØ£¬¼Ä´æÆ÷ÇåÁ㣻ϽµÑØ£º¿ªÊ¼ADת»»    set_outH(GPIOA,ST);    delay_us(5);    set_outL(GPIOA, ST);    delay_us(5);    while(read_in(GPIOB, EOC) == 0); //ת»»¹ý³Ì    //    EXTI_GenerateSWInterrupt(EXTI_Line14);        set_outH(GPIOA,OE); //Êä³öÔÊÐí¿ØÖƶˣ¬OE=1,Êä³öת»»Êý¾Ý    val = read_in(GPIOB, D0)*0x0001 + read_in(GPIOB, D1)*0x0002 +          read_in(GPIOB, D2)*0x0004 + read_in(GPIOB, D3)*0x0008 +          read_in(GPIOB, D4)*0x0010 + read_in(GPIOB, D5)*0x0020 +        read_in(GPIOB, D6)*0x0040 + read_in(GPIOB, D7)*0x0080;        set_outL(GPIOA,OE);        return val;}

华丽的分割!!!!!!!!!!!!!!!

这里是程序中的调用:

adc0809_init();val = adc0809_input();DtoB(valB,val);set_outL(GPIOC,ILE);delay_us(5);

2、要点

(1) AD需要单片机提供500KHz的方波作为时钟信号,当你提供500KHz的时钟信号时,AD0809便会以8KHz的频率进行采样。

(2) 程序中需要巧妙使用EOC提供的转换停止信号,进行采集,以及接下来的储存和DA转化所应该采取的频率基础来源。

(3) AD0809的参考电压只能是正,且不能大于10V。

 

五、DA0832使用

1、程序如下

#include "stm32f10x.h"//DAC0832µÄÊý×ÖÊäÈë-GPIOC#define DI0 GPIO_Pin_0#define DI1 GPIO_Pin_1#define DI2 GPIO_Pin_2#define DI3 GPIO_Pin_3#define DI4 GPIO_Pin_4#define DI5 GPIO_Pin_5#define DI6 GPIO_Pin_6#define DI7 GPIO_Pin_7#define ILE GPIO_Pin_8void da0832_init(void);void DtoB(int valB[],int val);
#include "adc0809.h"#include "gpio.h"#include "timer.h"#include "pbdata.h"void adc0809_init(void){    //Êä³ö¹Ü½Å    set_out(GPIOA, CLK|ALE|ST|OE);        //ÊäÈë¹Ü½Å    set_FIN(GPIOB, D0|D1|D2|D3|D4|D5|D6|D7|EOC);    timer2_pwm(600*1000, 0.5); //A0¹Ü½Å        set_outL(GPIOA, ALE);//µØÖ·ÊÖ¶¯ÉèÖÃ//    set_outL(GPIOA, A);//    set_outL(GPIOA, B);//    set_outL(GPIOA, C);    delay_us(5);    set_outH(GPIOA, ALE); //µØÖ·Ëø´æ}u8 adc0809_input() //AD²ÉÑù{    u8 val;    //ST²úÉúÉÏÉýÑغÍϽµÑØ£ºÉÏÉýÑØ£¬¼Ä´æÆ÷ÇåÁ㣻ϽµÑØ£º¿ªÊ¼ADת»»    set_outH(GPIOA,ST);    delay_us(5);    set_outL(GPIOA, ST);    delay_us(5);    while(read_in(GPIOB, EOC) == 0); //ת»»¹ý³Ì    //    EXTI_GenerateSWInterrupt(EXTI_Line14);        set_outH(GPIOA,OE); //Êä³öÔÊÐí¿ØÖƶˣ¬OE=1,Êä³öת»»Êý¾Ý    val = read_in(GPIOB, D0)*0x0001 + read_in(GPIOB, D1)*0x0002 +          read_in(GPIOB, D2)*0x0004 + read_in(GPIOB, D3)*0x0008 +          read_in(GPIOB, D4)*0x0010 + read_in(GPIOB, D5)*0x0020 +        read_in(GPIOB, D6)*0x0040 + read_in(GPIOB, D7)*0x0080;        set_outL(GPIOA,OE);        return val;}

 

2、要点

(1) DA0832芯片输出的是电流信号,也就是说DA出来的是电流量,我们需要外接一个运放来转换成电压信号。

(2) DA0832芯片输出时候的频率应该由EOC来控制。

(3) DA0832芯片输出会产生反相的作用

(4) DA0832与AD0809在直通时,会产生低频干扰,但由于是采集回放系统,所以很好的避免这个问题。否则需要采取软件去抖动的方法。

 

六、SD储存

1、程序如下

#ifndef _SD_H#define _SD_H#include "stm32f10x.h"#include "pbdata.h"#include "stm32f10x.h"#include "usart1.h"#include "stm32f10x_gpio.h"#include "SD_driver.h"#define LED_D1_ON()  (GPIOA->ODR &= ~GPIO_Pin_8)#define LED_D1_OFF() (GPIOA->ODR |= GPIO_Pin_8)void ConfigurationLED(void);void InitSys(void);void InitBSP(void);#endif
#include "SD.h"void ConfigurationLED(void){  GPIO_InitTypeDef GPIO_InitStructure;    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE);   RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA , ENABLE);                         /** *    LED -> PB1 */                       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   GPIO_Init(GPIOA, &GPIO_InitStructure);}void InitSys(void){     SystemInit();}/***************************************************************************************/void InitBSP(void){  ConfigurationUsart1();    ConfigurationLED();    printf("\r\n this is a SD Test demo \r\n");    USART1_printf(USART1, "\r\n this is a SD Test demo \r\n");    USART1_printf(USART1, "\r\n ("__DATE__ " - " __TIME__ ") \r\n");     ConfigurationSDCard(); while(1)     {        if(TestSD_ReadWriteFunction())            {                printf ( "SD ReadWriteFunction success !\n");             break;            }    LED_D1_ON();  //D1     printf ( "SD ReadWriteFunction error !\n");     }}

华丽的分割!!!!!!!!!!!!!!!!!!!!!!!!!!!

完整版的AD DA SD程序(仅仅main函数)

u16 sound_p = 0;  InitSys();  InitBSP();    set_out(GPIOA,Pin8);    extern_interrupt_init();    adc0809_init();    da0832_init();    set_outL(GPIOA, ST);    set_out(GPIOA,Pin11);        //timer3_init(10000); //¶¨Ê±Æ÷ÖжÏÅäÖà    //RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, DISABLE);    while(1)    {        if(function == Function_In)        {         val = adc0809_input();             music[i++]=val;            // printf("\r %d \n",val);          if(i>=512)          {               i=0;               if(SD_WriteSingleBlock(++Sector_pointer_In, music))               {                 //    printf("Write Error!");               }          }            }                if(function==Function_Out)        {                    set_outL(GPIOA, ST);      delay_us(5);        set_outH(GPIOA,ST);            delay_us(5);            set_outL(GPIOA, ST);            delay_us(5);            while(read_in(GPIOB, EOC) == 0); //ת»»¹ý³Ì            if((Sector_pointer_Out<=Sector_pointer_In)&&(Sector_pointer_In!=0))            {                    if(i==0)              {                 if(SD_ReadSingleBlock(++Sector_pointer_Out, music))               {                 //    printf("Read Error!");               }              }                DtoB(valB,music[i++]);                //  printf("\r %d \n",music[i-1]);                      GPIO_SetBits(GPIOC, DI0*valB[0] + DI1*valB[1] + DI2*valB[2] + DI3*valB[3] +                                         DI4*valB[4] + DI5*valB[5] + DI6*valB[6] + DI7*valB[7]);              GPIO_ResetBits(GPIOC, DI0*(1-valB[0]) + DI1*(1-valB[1]) + DI2*(1-valB[2]) + DI3*(1-valB[3]) +                                         DI4*(1-valB[4]) + DI5*(1-valB[5]) + DI6*(1-valB[6]) + DI7*(1-valB[7]));                if(i>=512)            {               i=0;            }            }            else            {                function=Function_Stop;            }
}

 

七、功率放大电路

1、采用TDA2030A作为功放芯片,电路如下:

 

2、要点:

(1)需要调节C7的电容,去掉直流分量。。。虽然不知道为什么会有,在测试的时候220nF会产生10V的直流分量。

(2)需要改变R1来控制增益。

 

八、总PCB设计

要点:

(1)各级电路之间要用短接帽的方式隔开

(2)电源排针需要多接几个,弄成一排。

(3)电源要用大电容小电容进行滤波

(4)半手工PCB版由于工艺。。最好是把铜线布宽点。

 

九、成品图

转载于:https://www.cnblogs.com/BlueMountain-HaggenDazs/p/4627624.html

你可能感兴趣的文章
c# 获取 bios 序列号
查看>>
[转] Chrome 控制台不完全指南
查看>>
给现下流行的打车软件的一点小建议
查看>>
Git 文件比较
查看>>
leetcode 102. Binary Tree Level Order Traversal
查看>>
def权限,频率,分页
查看>>
Javascript switch语句
查看>>
替换localhost:8080(假域名,本地使用)
查看>>
jQuery学习笔记
查看>>
PHP设计模式:结构型之门面(facade)
查看>>
ios中UITableViewCell选中后的颜色设置
查看>>
[搜片神器]迅雷云播视频地址获取代码分享[自己动手丰衣足食]
查看>>
两种不同的多路选择器?
查看>>
关于是用dotnet获取本机IP地址+计算机名的方法
查看>>
ajax请求步骤
查看>>
数据存储网址
查看>>
阅读程序并回答问题
查看>>
flash_header.S ( freescale imx6 board)
查看>>
C# 操作Excel文件的方法
查看>>
Converter -> public static int ToInt32(double value) 你用对了么?
查看>>