锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

声音传感器模块

时间:2022-08-24 00:00:01 传感器电路传感器板电压传感器8f8h传感器内置传感器类型电流传感器常见分类3408556传感器

大家好,我是小哈哥。在最近的网络文章中,我将与大家分享一位知识星球运动员的问答。我希望我感兴趣并继续关注它。

问题由来

星球网友的问题必须回答:

让我们把这个问题分开,回答以下几篇网文:

  • 基于Modbus协议将电压数据上传到上位机
  • Qt程序解析Modbus协议并在曲线中显示分析结果
  • 保存温度数据Excel中

这三个内容是这个问题涉及的三个知识点。今天,让我们分享第一个问题和其他问题,然后一个接一个地分享。

声音传感器模块

声传感器的作用相当于麦克风,用于接收声波。

传感器内置一个对声音敏感的电容式驻极体麦克风。声波振动麦克风中的驻极体膜,导致电容变化,然后产生与变化相对应的小电压。

电压随后通过放大器转化为0~VCC电压和电压值的大小等于声音强度的大小A/D转换可以获得相对声音强度AD值。

原理图

传感器模块上的麦克风可以将音频信号转换为电信号(模拟量)STM32自带ADC该功能将模拟量转换为数字量。

LM386是一种功率放大器,具有功耗低、更新内链增益可调、电源电压范围大、外部元件少、总谐波失真小等优点,广泛应用于录音机和收音机。

麦克风将声音信号转换为电信号,然后将信号发送到LM386的引脚3,并通过外部电路将它们输出到引脚5(模块的引脚OUT)。然后使用STM32中具有ADC读取模拟值。

硬件连接

声音传感器端 STM32端
AO PA1
VCC 5V
GND GND

注意:模块介绍中的要求VCC为5V电源,但我测试使用3.3V供电也可以。

STM32进行AD转换步骤

引用adc功能

要使用ADC必须引用功能stm32f10x_adc.c 文件和 stm32f10x_adc.h 文件。

ADC功能初始化

开启对应GPIO口和ADC功能时钟,设置使用GPIO模拟输入。

我们在这里选择核心板预留的PA1。

查询STM32F103数据手册如下:

我们知道PA1引脚有ADC123_IN1标识,ADC123_IN1代表ADC1的通道1、ADC2的通道1、ADC3的通道1在同一个管脚PA1上。

STM32 的 ADC 通道与 GPIO 对应表

我们在这里选择ADC1(选择ADC2和ADC3亦可)。

void  Adc_Init(void) {    ADC_InitTypeDef ADC_InitStructure;   GPIO_InitTypeDef GPIO_InitStructure;   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE );   //使能ADC1通道时钟    RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不超过144M   //PA1引脚初始化  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  //注意这里,模拟输入引脚  GPIO_Init(GPIOA, &GPIO_InitStructure);   ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 所有寄存器重新设置为缺省值   ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC在独立模式下工作  ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式下,不使用扫描  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ///模数转换工作单次转换模式  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐  ADC_InitStructure.ADC_NbrOfChannel = 1; ///按顺序转换规则ADC通道的数目  ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct初始化外设中指定的参数ADCx的寄存器        ADC_Cmd(ADC1, ENABLE); //使能指定ADC1    ADC_ResetCalibration(ADC1); //使能复位校准       while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束    ADC_StartCalibration(ADC1);  //开启AD校准    while(ADC_GetCalibrationStatus(ADC1));  //等待校准结束 } 

获取声传感器的输出值

声传感器的输出值-电压值,间接等同于声的大小。

以上已完成PA1为了获得引脚的输入电压,我们包装了引脚的初始化ADC值的函数u16 Get_Adc(u8 ch)

u16 Get_Adc(u8 ch)    {    //设置指定ADC规则组通道,一个序列,采样时间  ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期          ADC_SoftwareStartConvCmd(ADC1, ENABLE);  //使能指定ADC1软件转换启动功能      while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束   return ADC_GetConversionValue(ADC1); //回到最后一次ADC1规则组的转换结果 } 

要想求得PA1引脚的ADC值,只需这样调用:Get_Adc(1) ; ,函数返回值是获得的电压值。

有时候,为了减少随机误差,我们可以找到它ADC多次测量取平均值。

ADC结果验证

可以将PA1引脚通过杜邦线接触核心板3.3V和GND,看看结果是否接近4095和0。

或者直接连接声传感器模块,改变周围环境的声音大小,看输出值是否随声音大小而变化。如果变化规则一致,则表示ADC求得值应该不是问题。

通讯协议

通过以上步骤,我们得到了声传感器的值,那么如何将这个值上传到上位机呢?

要传输数据,首先要选择与上位机的通信方式。常见的通信方式有RS232、RS485、USB、网络等。

在这里,我们选择串口来实现下位机和上位机之间的通信通信最简单,资源消耗最少。

有了通信方式,为了保证通信双方能够正常交互,接下来要规定通信协议。

一般来说,主机端获得传感器值通常是一个问答。工业控制领域最常用的通信协议是Modbus协议。

因为我们想读的电压值只读,所以我们在这里选择功能码0x04即可。

04:INPUT REGISTER:输入寄存器,读取WORD类型、字操作、输入参数、控制器运行时从外部设备获得的参数,可读但不能写,常用于模拟输入。

按照Modbus对于寄存器的分类,电流和电压值属于模拟量,只能读不能写,属于输入寄存器的类别。严格来说,只能用0x04功能码。

Modbus协议的格式

主机发送的指令:

地址 功能码 寄存器起始地址 寄存器数量 CRC校验位
01H 04H 0x0000 0x0001 前面所有字节的CRC16校验和,2个字节,低字节在前

从机返回:

地址 功能码 寄存器字节总数 寄存器数据 CRC校验位
01H 04H 0x02 电压值 前面所有字节的CRC16校验和,2个字节,低字节在前

我们使用STM32F103自带的ADC功能,因为他的AD是12位的,所以我们用一个16位整数表示该电压值即可,所以我们从机返回的寄存器数据占用2个字节。

上位机发送的指令:

读取当前电压:nAddr, 0x04, 0x00, 0x00, 0x00, 0x01, checkBitHig, checkBitLow

即: 01 04 00 00 00 01 31 CA

串口接收及发送

为了方便调试,我们使用最小系统核心板的串口1接收和发送传感器数据。

从机接收指令

Modbus协议一般用于一主多从结构,主机主动发送指令,从机被动接收指令。

从机接收到指令后,对接收到的指令进行解析,然后根据指令向主机返回对应的内容。

当串口接收超时时,我们将获得一帧数据,这个数据保存至USART_RX_BUF数组中,接下来我们就对这个数组中的内容进行解析:

//解析接收到的串口数据
//串口1收到的信息
if(USART_RX_STA&0x8000)
{ 
    uart1Len=USART_RX_STA&0x3f;            			//得到此次接收到的数据长度   

    if(uart1Len==8)
    {
        crc16 = chkcrc(USART_RX_BUF, 6);
        checkBitLow = (u8)(crc16 & 0xff);				//校验位低8位
        checkBitHig = (u8)((crc16 >> 8) & 0xff);		//校验位高8位

        //低字节在前
        if(checkBitLow==USART_RX_BUF[6] && checkBitHig==USART_RX_BUF[7])
        {
            if(USART_RX_BUF[0] == 0x01)             //我们可以规定地址0x01即为获取声音传感器的值
            {
                //... ...
            }
        }
    }


    USART_RX_STA=0;   
    memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));                          //清空数组  
} 

从机发送数据

根据主机的指令,从机返回对应的数据给主机。

从机发送的数据要满足Modbus协议返回数据的帧格式。

具体发送数据的代码如下:

u16 crc16; 
u8 checkBitLow, checkBitHig;
u8 sendBuf[20];
u16 nADCValue = 0;
//获取AD的值
nADCValue = Get_Adc_Average(1,10); 

//格式化待发送数据
sendBuf[0] = 0x01;
sendBuf[1] = 0x04;
sendBuf[2] = 0x02;
sendBuf[3] = ((nADCValue >> 8) & 0xff); //0x18;//
sendBuf[4] = (nADCValue & 0xff);        //0xD5;//
crc16 = chkcrc(sendBuf, 5);
checkBitLow = (u8)(crc16 & 0xff);				//校验位低8位
checkBitHig = (u8)((crc16 >> 8) & 0xff);		//校验位高8位
sendBuf[5] = checkBitLow;
sendBuf[6] = checkBitHig;

//串口发送,发送结果数据至主机
USART_OUT(sendBuf, 7);

上位机打开串口助手,以十六进制的方式发送数据帧:01 04 00 00 00 01 31 CA

STM32端收到串口指令之后,解析此数据帧,将当前的声音传感器的值封装数据帧之后,发送给上位机。

调试验证

使用ModScan32软件对我们实现的下位机程序进行验证。

ModScan32是一个运行在Windows下,作为在RTU或者ASCII传输模式下的Modbus协议主设备的应用程序。

总结

这样我们就把声音传感器的数值通过串口上传到了上位机中,实现了Modbus协议的主机、从机的交互,对于不同传感器、不同节点,我们只需要设定不同的地址即可。

参考阅读

土壤湿度传感器,出远门再也不怕花没人浇水了

STM32F103 串口的使用方法

[网友问答2]上位机如何与STM32进行串口通信

干货 | Modbus协议调试分享

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章