老兵精讲:基于MM32实现音频播放系统的应用实例

嵌入式ARM 2022-08-16 12:01
一、基本介绍

I2S总线又称为Inter-IC Sound总线,它是集成在芯片内的音频总线,是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准,该总线专门应用于音频设备之间的数据传输,广泛应用于各种多媒体系统。它采用了沿独立的导线传输时钟和数据信号的设计,通过将数据和时钟信号分离,避免了因时差诱发的失真问题。

MM32F3270系列MCU最多支持3个I2S接口,同一时刻只能工作在发送或者接收接收状态,支持16位、24位和32位三种数据格式、数据传输始终是MSB优先、每个I2S接口都支持DMA传输方式。

此外,MM32F3270系列MCU的I2S还支持4种I2S协议标准,分别是飞利浦标准、MSB对齐标准、LSB对齐标准、以及PCM标准,我们可以根据MM32F3270系列MCU连接的I2S外设所支持的协议标准进行灵活配置和选择。

二、实现功能

基于MM32-EVBoard(MB-039)开发板,实现音频播放系统。通过DMA的方式,将存储在TF卡中的音频文件(WAV格式/MP3格式)通过I2S总线,将音频数据发送给CS4344音频数模转换芯片,通过与其连接的音响设备播放出音乐;通过板载的4个按键来实现对音频文件的开始播放、停止播放、音频文件选择等操作,并在TFT液晶显示屏上显示系统运行信息、音频文件目录,以及当前的播放状态等内容。

根据如上功能要求,需要实现的技术点如下:

1、GPIO口控制LED闪烁和KEY按键检测;LED控制引脚与I2S引脚复用,所以在播放音乐的时候,LED是表象上不闪烁的;KEY在识**需要结合音频的当前状态做处理。

2、TFT LCD用于运行显示,通过FSMC接口与MCU进行连接,通过8080总线方式进行显示控制和内容显示;显示的字符包含ASCII码和汉字,其中ASCII码字库存放在MCU的FLASH程序空间,中文GBK编码字库存放在SPI FLASH中。

3、SPI FLASH用于存放中文GBK编码字库,通过板载的UART8接口,结合Xmodem串行文件传输协议,从电脑端把GBK_FONG.BIN文件传输并写入到板载的SPI FLASH芯片中;再通过回读取的方式,将SPI FLASH存储的字库数据通过Xmodem上传到电脑端,比较下载文件与读取到的文件是否相一致,确认字库的正确性。

4、通过MCU的SDIO接口来操作TF卡,移植FatFs文件系统对音频文件进行识别,对音频文件数据进行读取操作。

5、通过MCU的I2C接口来与CS4344音频数模转换芯片进行数据传输,实现播放音频文件,采用DMA传输方式,开启DMA传输完成中断和半传输完成中断,通过乒乓操作实现音频文件播放的流畅效果。

6、另外最重要的就是音频文件的识别和解码;对于WAV文件来说,它是未经编码/压缩的音频数据文件,在固定的文件头信息后面是音频数据,只需要在音频文件解析后将获取到的音频数据直接发送到I2S总线即可实现播放;而对于MP3文件来说,它是经过编码/压缩的音频数据文件,在没有外部解码芯片支持的时候,需要用软件解码的方式来实现音频数据的提取操作,本文中将会介绍Helix和libmad这两种开源的,且非常常用的软件解码方式。

三、软件环境

Windows操作系统下开发,使用的IDE和相应的软件如下:

1、Keil MDK开发软件;

2、MobaXterm终端软件,用于监控程序运行及代码中SHELL功能的操作;

3、SecureCRT终端软件,通过Xmodem传输协议结合MCU功能代码实现,用于将GBK汉字字库编码数据下载到板载的SPI FLASH芯片中;

4、Beyond Compare比较软件,用于比较GBK汉字字编码下载和上传数据的一致性;

5、酷狗音乐,下载音频文件。

四、硬件环境

1、MM32-EVBoard(MB-039)开发板;

2、8GB容量的TF卡及读卡器,通过读卡器连接电脑,将音频文件存放在TF卡中;

3、音箱设备;

4、Micro USB数据线、音频接口连接线;

5、USB转TTL调试工具。

五、WAV音频文件

WAV文件Waveform的简写,也称为波形文件,是一种可以存储声音波形的数字音频格式。WAV支持多种音频数字、采样频率和声道,标准格式化的WAV文件和CD的格式一样,也是44.1kHz的采样频率、16位量化数据,具有真实记录声音波形的特点,基本无数据压缩,所以数据体量也变得相对大些。

WAV文件的编码包括两方面的内容,一个是按一定格式存储数据,另外一个就是采用一定的算法压缩数据。WAV格式对音频流的编码没有硬性规定,支持非压缩算法的PCM(Plus Code Modulation)脉冲编码调制格式,也支持其它一些压缩算法。

典型的WAV文件格式,如下图所示:

1、WAV文件结构

在Windows环境下,大部分多媒体文件都是按照资源互换文件格式(Resources Interchange File Format)存放信息的,简称RIFF格式。构成RIFF文件的基本单位称之为块(Chunk),每个RIFF文件都是由若干个块组成的,而每个块都是由块标识、块长度以及数据这三部分组成的。块标识是由4个ASCII码字符组成的,如果不满4个字符则在右边以空格来补齐;块长度也占4个字节存储空间,保存的是当前块数据的长度,但不包含块标识和块长度字段;所以一个块的实际长度就是块长度字段的数值再加上8字节。

RIFF格式规定,只有RIFF块和LIST块可以包含子块,其它的块都不允许包含子块;而一个RIFF格式文档本身就是一个块。分析一个RIFF文档的组成部分,第一部分的4个字节为文档的标识符“RIFF”,同时也是RIFF的块标识,指示该文档是一个有效的RIFF格式文档;第二部分的4个字节为块长度,指示文件的数据长度,其数据为文件总长度减8字节;第三部分为块数据,其中,前4个字节为文件格式类型标识,如WAVE、AVI等;面后面其它部分就是RIFF块的子块了。

WAV文件采用的是RIFF格式结构,其至少由RIFF块、fmt块和data块组成,若是基于压缩编码的WAV文件还必须包含fact块;其中fmt块、data块和fact块都是RIFF块的子块。WAV文件的文件格式类型标识符为“WAVE”,其基本结构如下所示:


2、WAV文件头格式


3、WAV文件格式实例解析


4、扩展子块格式


5、fact块格式


6、WAV文件格式实例解析


  • 5249 4646这个是ASCII字符”RIFF”,这部分是固定格式,表明了这是一个有效的RIFF格式文件;
  • AC96 5E03这个是WAV文件的数据大小,对应0x035E96AC,十进制值为56530604;这个值再加上8个字节就是WAV文件总长度了,如下图所示:


  • 5741 5645这个是ASCII字符”WAVE”
  • 666D 7420这个是ASCII字符”fmt ”,即fmt块的块标识
  • 1000 0000这个是fmt格式块长度,16字节
  • 0100这个是编码格式,0x0001对应PCM/非压缩格式
  • 0200这个是声道个数,0x0002表示两声道或者立体声道
  • 44AC 0000这个是采样频率,对应16进制数为0x0000AC44,对应十进制为44100

其它的字段数据可以对照上述表格一一列举出来,但需要注意的是数据的大小端不同的存储方式哈!!!

7、WAV文件格式在代码中的结构体定义

WAV.h /* 由于字数限制,请参考源代码 */
8、WAV文件格式在MM32中的结构解析
static uint8_t WAV_DecodeFile(WAV_TypeDef *pWav, char *Path, char *Name) /* 由于字数限制,请参考源代码 */
9、WAV文件格式在MM32中的播放实现
void WAV_PlaySong(char *Path, char *Name){
    WAV_TypeDef WaveFile;
    char FilePath[100];


    /* 获取WAV文件的信息 */
    if(WAV_DecodeFile(&WaveFile, Path, Name) == 0)
    {
        if((WaveFile.BitsPerSample == 16) && (WaveFile.nChannels == 2) &&
           (WaveFile.SampleRate  > 44000) && (WaveFile.SampleRate < 48100))
        {
            I2S_InitGPIO();


            I2S_PowerON(1);


            I2S_Configure(I2S_Standard_Phillips, I2S_DataFormat_16b,
                          I2S_AudioFreq_44k,     I2S_Mode_MasterTx);
        }
        else
        {
            printf("\r\nWAV File Error!\r\n");  return;
        }
    }
    else
    {
        printf("\r\nNot WAV File!\r\n");    return;
    }


    memset( FilePath, 0x00, sizeof(FilePath));
    sprintf(FilePath, "%s%s",   Path,   Name);


    WAV_RES = f_open(&WAV_File, FilePath, FA_READ);


    if(WAV_RES == FR_OK)
    {
        WAV_NextIndex = 0;
        WAV_PlayEnded = 0;


        WAV_PlaybackProgress = 0;


        WAV_PrepareData();
        WAV_PlayHandler();
    }
    else
    {
        printf("\r\nWAV File Open Error : %d", WAV_RES);
    }
}

六、MP3音频文件

MP3格式音乐文件普遍存在我们生活中,实际上MP3本身是一种音频编码方式,全称为 Moving Picture Experts Group Audio Layer III(MPEG Audio Layer 3)。MPEG音频文件是MPEG标准中的声音部分,根据压缩质量和编码复杂程度划分为三层,即 Layer-1、Layer2、Layer3,且分别对应MP1、MP2、MP3 这三种声音文件。其中,MP3压缩率可达到10:1至12:1,可以大大减少文件占用存储空间大小。

MPEG 音频编码的层次越高,编码器越复杂,压缩率也越高。MP3是利用人耳对高频声音信号不敏感的特性,将时域波形信号转换成频域信号,并划分成多个频段,对不同的频段使用不同的压缩率,对高频加大压缩比(甚至忽略信号)对低频信号使用小压缩比,保证信号不失真。这样一来,就相当于抛弃人耳基本听不到的高频声音,只保留能听到的低频部分,这样可得到很高的压缩率。

1、MP3文件结构

MP3文件大致分为3个部分:TAG_V2(ID3V2)、音频数据、TAG_V1(ID3V1)。ID3是MP3文件中附加关于该MP3文件的歌手、标题、专辑名称、年代、风格等等信息,有两个版本ID3V1和ID3V2。ID3V1固定存放在MP3文件末尾,固定长度为128字节,以TAG三个字符开头,后面跟上歌曲信息。因为ID3V1可存储信息量有限,有些MP3文件添加了ID3V2,ID3V2是可选的,如果存在ID3V2那它必然存在在MP3文件起始位置,它实际是ID3V1的补充。

2、MP3数据帧

经过压缩后的MP3文件数据是由多个帧组成的,帧是MP3文件的最小组成单位。每个帧又由帧头 、附加信息和声音数据组成,每个帧的长度会随着位率的不同而变化,有些MP3文件末尾还有些额外的字节数据存放非声音数据的说明信息等。每个帧包含一段音频的压缩数据,通过解码库解码即可得到对应PCM音频数据,就可以通过I2S发送到CS4344芯片播放音乐,按顺序解码所有帧就可以得到整个MP3文件的音轨。

3、MP3解码库

MP3文件是经过压缩算法压缩而存在的,为得到PCM信号,需要对MP3文件进行解码,解码 过程大致为:比特流分析、霍夫曼编码、逆量化处理、立体声处理、频谱重排列、抗锯齿处理、 IMDCT 变换、子带合成、PCM输出。整个过程涉及很多算法计算,要自己编程实现不是一件现 实的事情,还好有很多公司经过长期努力实现了解码库编程。具体的MP3文件格式内容解析可以参考附件中的《MP3文件格式解析》一文,文本不需要对MP3数据帧的细节做深入的研究,我只需要掌握如何使用当前比较常用的开源软件来播放MP3音频文件即可。

现在合适在小型嵌入式控制器移植运行的有两个版本的开源MP3解码库,分别为libmad解码库和Helix解码库。

其中,libmad是一个开源的高精度MPEG音频解码库,是专门面向嵌入式应用的MP3解码程序,可以简单地实现MP3数据解码工作,支持MPEG-1、MPEG-2,以及MPEG-2.5标准,它可以提供24位PCM输出,用定点运算模拟浮点运算,因此不需要处理器有浮点运算功能,非常适合没有浮点支持的平台上使用;libmad对MP3解码中关键部分采用了优化的算法,这些优化算法能够大幅度地减少计算量,而且大多应用于MP3解码的VLSI实现中。libmad的源代码文件目录下的mad.h文件中,可以看到绝大部分该库的数据结构和API等,软件库结构清晰,易于使用和开发。

而Helix解码库则支持浮点和定点这两种的计算实现,它同样支持MPEG-1、MPEG-2以及MPEG-2.5标准的Layer3解码,此外Helix解码库还支持可变位速率、恒定位速率,以及立体声和单声道音频格式。这两个解码库都是以一帧为解码单位的,一次解码一帧。

各有优点,至于哪个更好,我还没有深入研究,但从使用下来最明显的体验来说,就是libmad库对堆栈空间大小的要求肯定是比Helix要大得多的,所以如果为了节省些RAM空间,可以优先考虑选择Helix库。

4、Helix MP3解码库在MM32中的播放实现

void MP3_Helix_PlaySong(char *Path, char *Name)
{
    char FilePath[100];
    memset( FilePath, 0x00, sizeof(FilePath));
    sprintf(FilePath, "%s%s",   Path,   Name);


    if(f_open(&MP3_Helix_File, FilePath, FA_READ) == FR_OK)
    {
        hMP3Decoder = MP3InitDecoder();                 /* 初始化MP3解码器 */


        if(hMP3Decoder == 0)
        {
            f_close(&MP3_Helix_File); return;
        }


        MP3_Helix_RES = f_read(&MP3_Helix_File, MP3_Helix_iBuffer, MP3_HELIX_I_BUFFER_SIZE, &MP3_Helix_BR);


        if((MP3_Helix_RES == FR_OK) && (MP3_Helix_BR != 0))
        {
            printf("\r\nMP3 Play\r\n");


            I2S_InitGPIO();
            I2S_PowerON(1);


            MP3_Helix_InPointer  = MP3_Helix_iBuffer;   /* 数据读取缓存指针 */
            MP3_Helix_BytesLeft  = MP3_Helix_BR;


            MP3_Helix_PlayEnded  = 0;
            MP3_Helix_SampleRate = 0;


            I2S_DMA_Finish = 1;


            while(!MP3_Helix_PlayEnded)
            {
                MP3_Helix_PrepareData();


                EVENT_Scanning();


                MP3_Helix_PlayHandler();


                TASK_Scheduling();
            }
        }
    }
    else
    {
        printf("\r\nMP3 File Open Fail!\r\n");
    }
}
5、libmad MP3解码库在MM32中的播放实现
void MP3_libmad_PlaySong(char *Path, char *Name)
{
    char     FilePath[100];
    int      TagSize   = 0;
    uint32_t FrameCount  = 0;


    /* First the structures used by libmad must be initialized. */
    mad_stream_init(&MP3_libmad_Stream);
    mad_frame_init( &MP3_libmad_Frame );
    mad_synth_init( &MP3_libmad_Synth );
    mad_timer_reset(&MP3_libmad_Timer );


    memset( FilePath, 0x00, sizeof(FilePath));
    sprintf(FilePath, "%s%s",   Path,   Name);


    if(f_open(&MP3_libmad_File, FilePath, FA_READ) == FR_OK)
    {
        I2S_InitGPIO();
        I2S_PowerON(1);


        MP3_libmad_PlayEnded = 0;
        I2S_DMA_Finish       = 1;




        MP3_libmad_RES = f_read(&MP3_libmad_File, MP3_libmad_iBuffer, MP3_LIBMAD_I_BUFFER_SIZE, &MP3_libmad_BR);


        if(strncmp("ID3", (char *)MP3_libmad_iBuffer, 3) == 0)
        {
            /*计算标签信息总大小  不包括标签头的10个字节*/
            TagSize =  ((unsigned int)MP3_libmad_iBuffer[6] << 21) |
                       ((unsigned int)MP3_libmad_iBuffer[7] << 14) |
                       ((unsigned int)MP3_libmad_iBuffer[8] << 7)  |
                       ((unsigned int)MP3_libmad_iBuffer[9] << 0);


            TagSize += 10;


            printf("\r\nMP3 TAG Size : %d\r\n", TagSize);
        }


        f_lseek(&MP3_libmad_File, TagSize);   /* 跳过TAG信息 */




        while(1)
        {
            if((MP3_libmad_Stream.buffer == NULL) || (MP3_libmad_Stream.error == MAD_ERROR_BUFLEN))
            {
                size_t         ReadSize, Remaining;               
                unsigned char *ReadStart = NULL;


                if(MP3_libmad_Stream.next_frame != NULL)
                {
                    Remaining = MP3_libmad_Stream.bufend - MP3_libmad_Stream.next_frame;
                    memmove(MP3_libmad_iBuffer, MP3_libmad_Stream.next_frame, Remaining);


                    ReadStart = MP3_libmad_iBuffer       + Remaining;
                    ReadSize  = MP3_LIBMAD_I_BUFFER_SIZE - Remaining;
                }
                else
                {
                    ReadSize  = MP3_LIBMAD_I_BUFFER_SIZE,
                    ReadStart = MP3_libmad_iBuffer,
                    Remaining = 0;
                }


                MP3_libmad_RES = f_read(&MP3_libmad_File, (char *)ReadStart, ReadSize, &MP3_libmad_BR);


                if((MP3_libmad_BR <= 0) || (MP3_libmad_BR < ReadSize))
                {
                    printf("\r\nEnd Of File\r\n");  break;
                }


                mad_stream_buffer(&MP3_libmad_Stream, MP3_libmad_iBuffer, MP3_libmad_BR + Remaining);
                MP3_libmad_Stream.error = MAD_ERROR_NONE;
            }


            if(mad_frame_decode(&MP3_libmad_Frame, &MP3_libmad_Stream))
            {
                if(MAD_RECOVERABLE(MP3_libmad_Stream.error))
                {
                    if((MP3_libmad_Stream.error != MAD_ERROR_LOSTSYNC) || (MP3_libmad_Stream.this_frame != NULL))
                    {
                        printf("\r\nRecoverable   Frame Level Error (%s)\r\n", MP3_libmad_MadErrorString(&MP3_libmad_Stream));
                    }


                    continue;
                }
                else
                {
                    if(MP3_libmad_Stream.error == MAD_ERROR_BUFLEN)
                    {
                        continue;
                    }
                    else
                    {
                        printf("\r\nUnrecoverable Frame Level Error (%s)\r\n", MP3_libmad_MadErrorString(&MP3_libmad_Stream));
                        break;
                    }
                }
             }


            if(FrameCount == 0)
            {
                MP3_libmad_PrintFrameInfo(&MP3_libmad_Frame.header);
            }


            FrameCount++;
            mad_timer_add(&MP3_libmad_Timer, MP3_libmad_Frame.header.duration);


            mad_synth_frame(&MP3_libmad_Synth, &MP3_libmad_Frame);


            for(uint32_t i = 0; i < MP3_libmad_Synth.pcm.length; i++)
            {
                short Sample = MP3_libmad_MadFixedToSshort(MP3_libmad_Synth.pcm.samples[0][i]);


                MP3_libmad_oBuffer[MP3_libmad_NextIndex][MP3_libmad_BufferSize++] = Sample;


                if(MAD_NCHANNELS(&MP3_libmad_Frame.header) == 2)        
                {
                    Sample = MP3_libmad_MadFixedToSshort(MP3_libmad_Synth.pcm.samples[1][i]);
                }


                MP3_libmad_oBuffer[MP3_libmad_NextIndex][MP3_libmad_BufferSize++] = Sample;


                MP3_libmad_PlayHandler(MP3_libmad_Synth.pcm.samplerate);
            }


            if(MP3_libmad_PlayEnded == 1)
            {
                break;
            }
        }


        DMA_Cmd(DMA2_Channel2, DISABLE);


        f_close(&MP3_libmad_File);


        I2S_PowerON(0);
    }


    mad_synth_finish( &MP3_libmad_Synth );
    mad_frame_finish( &MP3_libmad_Frame );
    mad_stream_finish(&MP3_libmad_Stream);


    char Buffer[80];
    mad_timer_string(MP3_libmad_Timer, Buffer, "%lu:%02lu.%03u", MAD_UNITS_MINUTES, MAD_UNITS_MILLISECONDS, 0);
    printf("\r\n%d Frames Decoded (%s).\r\n", FrameCount, Buffer);
}
七、代码实现

代码实现部分,我们只展示出功能实现的主体部分,对于像FatFs文件系统的移植、LED控制、KEY按键处理、Xmodem文件传输协议的实现等部分,这些在之前的分享帖中有详细的描述,可以参考之前的分享**,当然也可以直接下载附件中的软件工程源代码,直接查看源代码。

  • 音频播放整体功能控制逻辑
void AUDIO_Handler(void/* 由于字数限制,请参考源代码 */
  • 根据识别按键处理对应功能
void KEY_Handler(eKEY_VALUE value, eKEY_TYPE type/* 由于字数限制,请参考源代码 */
  • 加载中文字库编码点阵数据,根据LCD显示方向进行旋转

void LCD_ShowCN(uint16_t StartX, uint16_t StartY, const char *str/* 由于字数限制,请参考源代码 */
  • 实现自动判断中英文字符并显示在显示屏上
uint16_t LCD_ShowLOG(uint16_t StartX, uint16_t StartY, const char *str) /* 由于字数限制,请参考源代码 */
  • 通过FatFs文件系统列举当前目录文件,并显示在LCD屏上

FRESULT AUDIO_ScanFiles(char *path) /* 由于字数限制,请参考源代码 */
八、测试运行

系统初始化加载:

歌曲目录文件显示:

播放WAV歌曲:

通过Helix解码库播放MP3歌曲:


通过labmad解码库播放MP3歌曲:


通过Xmodem串行传输协议下载中文字库到SPI FLASH:

(1)通过Xmodem串行传输协议下载字库

(2)通过Xmodem串行传输协议上传字库

(3)比较下载的字库文件和上传的字库文件是否一致

以上就是基于MM32实现音频播放系统的应用实例了,如果有需要查看原图、代码、视频演示的小伙伴,请点击底部“阅读原文”进行下载。

END

作者:xld0932
来源:21ic论坛

版权归原作者所有,如有侵权,请联系删除。

推荐阅读
让人眼前一亮的Linux终端工具!
CPU明明8个核,网卡为什么拼命折腾一号核?
为什么中国的数字是四位一进,西方的是三位一进?

→点关注,不迷路←
嵌入式ARM 关注这个时代最火的嵌入式ARM,你想知道的都在这里。
评论
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 626浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 181浏览
  • 故障现象 一辆2007款日产天籁车,搭载VQ23发动机(气缸编号如图1所示,点火顺序为1-2-3-4-5-6),累计行驶里程约为21万km。车主反映,该车起步加速时偶尔抖动,且行驶中加速无力。 图1 VQ23发动机的气缸编号 故障诊断接车后试车,发动机怠速运转平稳,但只要换挡起步,稍微踩下一点加速踏板,就能感觉到车身明显抖动。用故障检测仪检测,发动机控制模块(ECM)无故障代码存储,且无失火数据流。用虹科Pico汽车示波器测量气缸1点火信号(COP点火信号)和曲轴位置传感器信
    虹科Pico汽车示波器 2025-01-23 10:46 80浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 123浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 325浏览
  • 飞凌嵌入式基于瑞芯微RK3562系列处理器打造的FET3562J-C全国产核心板,是一款专为工业自动化及消费类电子设备设计的产品,凭借其强大的功能和灵活性,自上市以来得到了各行业客户的广泛关注。本文将详细介绍如何启动并测试RK3562J处理器的MCU,通过实际操作步骤,帮助各位工程师朋友更好地了解这款芯片。1、RK3562J处理器概述RK3562J处理器采用了4*Cortex-A53@1.8GHz+Cortex-M0@200MHz架构。其中,4个Cortex-A53核心作为主要核心,负责处理复杂
    飞凌嵌入式 2025-01-24 11:21 50浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 666浏览
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 159浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 135浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 195浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦