关于USB-AUDIO使用ALSA编程的一点问题

转载自:http://blog.chinaunix.net/uid-25272011-id-3153434.html

 

最近在调试一款原相PAP7501摄像头中的USB的麦克风,USB层走的应该是标准的UAC协议,具体可以见USB的官网:http://www.usb.org/developers/devclass_docs#approved,而音频部分则可以跑目前Linux标准的ALSA的PCM接口,对于硬件CODEC来说,与其是完全兼容的。
     给出一份参考代码:
     这个是仿照arecord写的一个简略的测试代码,保存为wav格式的。
1、recod.c


  1. /*

  2. This example reads from the default PCM device
  3. and writes to standard output for 5 seconds of data.

  4. */

  5. /* Use the newer ALSA API */
  6. #define ALSA_PCM_NEW_HW_PARAMS_API

  7. #include <alsa/asoundlib.h>

  8. /**************************************************************/
  9. #define ID_RIFF 0x46464952
  10. #define ID_WAVE 0x45564157
  11. #define ID_FMT 0x20746d66
  12. #define ID_DATA 0x61746164

  13. typedef unsigned long uint32_t;
  14. typedef unsigned short uint16_t;

  15. #define FORMAT_PCM 1

  16. static uint32_t totle_size = 0;

  17. struct wav_header {
  18.     /* RIFF WAVE Chunk */
  19.     uint32_t riff_id;
  20.     uint32_t riff_sz;
  21.     uint32_t riff_fmt;
  22.     /* Format Chunk */
  23.     uint32_t fmt_id;
  24.     uint32_t fmt_sz;
  25.     uint16_t audio_format;
  26.     uint16_t num_channels;
  27.     uint32_t sample_rate;
  28.     uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */
  29.     uint16_t block_align; /* num_channels * bps / 8 */
  30.     uint16_t bits_per_sample;
  31.     /* Data Chunk */
  32.     uint32_t data_id;
  33.     uint32_t data_sz;
  34. }__attribute__((packed));

  35. static struct wav_header hdr;

  36. /**************************************************************/
  37. int record_file(unsigned rate, unsigned channels, int fd, unsigned count)
  38. {
  39.     long loops;
  40.     int val;
  41.     int rc;
  42.     int size;
  43.     snd_pcm_t *handle;
  44.     snd_pcm_hw_params_t *params;
  45.     int dir;
  46.     snd_pcm_uframes_t frames;
  47.     char *buffer;                    /* TODO */

  48.     /* Open PCM device for recording (capture). */
  49.     rc = snd_pcm_open(&handle, "plughw:0,0", SND_PCM_STREAM_CAPTURE, 0);
  50.     if (rc < 0) {
  51.         fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
  52.         exit(1);
  53.     }

  54.     /* Allocate a hardware parameters object. */
  55.     snd_pcm_hw_params_alloca(&params);

  56.     /* Fill it in with default values. */
  57.     snd_pcm_hw_params_any(handle, params);

  58.     /* Set the desired hardware parameters. */

  59.     /* Interleaved mode */
  60.     snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

  61.     /* Signed 16-bit little-endian format */
  62.     snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

  63.     /* Two channels (stereo) */
  64.     snd_pcm_hw_params_set_channels(handle, params, channels);

  65.     /* rate bits/second sampling rate (CD quality) */
  66.     snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir);

  67.     /* Set period size to 32 frames. */
  68.     frames = 320;     /* 这边的大小也不是绝对的,可以调整 */
  69.     snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);

  70.     /* Write the parameters to the driver */
  71.     rc = snd_pcm_hw_params(handle, params);
  72.     if (rc < 0) {
  73.         fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
  74.         exit(1);
  75.     }

  76.     /* Use a buffer large enough to hold one period */
  77.     snd_pcm_hw_params_get_period_size(params, &frames, &dir);/* 获取实际的frames */
  78.     
  79.     size = frames * 2; /* 2 bytes/sample, 1 channels */
  80.     buffer = (char *) malloc(size);

  81.     /* We want to loop for 20 seconds 时间不一定准确 */
  82.     snd_pcm_hw_params_get_period_time(params, &val, &dir);
  83.     loops = 20000000 / val;
  84.     
  85.     while (loops > 0) {
  86.         loops--;
  87.         rc = snd_pcm_readi(handle, buffer, frames);
  88.         if (rc == -EPIPE) {
  89.          /* EPIPE means overrun */
  90.          fprintf(stderr, "overrun occurred\n");
  91.          snd_pcm_prepare(handle);
  92.         } else if (rc < 0) {
  93.          fprintf(stderr, "error from read: %s\n", snd_strerror(rc));
  94.         } else if (rc != (int)frames) {
  95.          fprintf(stderr, "short read, read %d frames\n", rc);
  96.         }
  97.         rc = write(fd, buffer, size);
  98.         totle_size += rc;                        /* totle data size */
  99.         if (rc != size)
  100.          fprintf(stderr, "short write: wrote %d bytes\n", rc);
  101.     }
  102.     
  103.     lseek(fd, 0, SEEK_SET);      /* 回到文件头,重新更新音频文件大小 */
  104.     hdr.riff_sz = totle_size + 36;
  105.     hdr.data_sz = totle_size;
  106.     
  107.     if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
  108.         fprintf(stderr, "arec: cannot write header\n");
  109.         return -1;
  110.     }
  111.     
  112.     snd_pcm_drain(handle);
  113.     snd_pcm_close(handle);
  114.     free(buffer);

  115.     return 0;
  116. }

  117. /**************************************************************/
  118. int rec_wav(const char *fn)
  119. {
  120.     unsigned rate, channels;
  121.     int fd;
  122.     fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664);
  123.     if (fd < 0) {
  124.         fprintf(stderr, "arec: cannot open '%s'\n", fn);
  125.         return -1;
  126.     }

  127.     hdr.riff_id = ID_RIFF;
  128.     hdr.riff_fmt = ID_WAVE;
  129.     hdr.fmt_id = ID_FMT;
  130.     hdr.audio_format = FORMAT_PCM;
  131.     hdr.fmt_sz = 16;
  132.     hdr.bits_per_sample = 16;
  133.     hdr.num_channels = 1;
  134.     hdr.data_sz = 0;                        /* TODO before record over */
  135.     hdr.sample_rate = 16000;
  136.     hdr.data_id = ID_DATA;
  137.     
  138.     hdr.byte_rate = hdr.sample_rate * hdr.num_channels * hdr.bits_per_sample / 8;
  139.     hdr.block_align = hdr.num_channels * hdr.bits_per_sample / 8;
  140.     
  141.     if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
  142.         fprintf(stderr, "arec: cannot write header\n");
  143.         return -1;
  144.     }
  145.     fprintf(stderr,"arec: %d ch, %ld hz, %d bit, %s\n",
  146.             hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
  147.             hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
  148.     
  149.     return record_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz);
  150. }

  151. int main(int argc, char **argv)
  152. {
  153.     if (argc != 2) {
  154.         fprintf(stderr,"usage: arec <file>\n");
  155.         return -1;
  156.     }

  157.     return rec_wav(argv[1]);
  158. }
对于上述代码补充说明一点,这个是设计ALSA的一点概念:

样本长度(sample):样本是记录音频数据最基本的单位,常见的有8位和16位。

通道数(channel):该参数为1表示单声道,2则是立体声。

桢(frame):桢记录了一个声音单元,其长度为样本长度与通道数的乘积。

采样率(rate):每秒钟采样次数,该次数是针对桢而言。

周期(period):音频设备一次处理所需要的桢数,对于音频设备的数据访问以及音频数据的存储,都是以此为单位。

交错模式(interleaved):是一种音频数据的记录方式,在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声格式),再开始桢2的记录。而在非交错模式下,首先记录的是一个周期内所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。不过多数情况下,我们只需要使用交错模式就可以了。

具体可以参照:http://blog.chinaunix.net/uid-25272011-id-3151136.html

一开始我犯过一个错误就是rc = snd_pcm_readi(handle, buffer, frames),这个函数的参数3的单位应该是帧大小,而一个帧的大小是根据你的量化位数和声道数决定的,对于本代码,是16bit单声道,自然一个帧大小是2字节,起初我将申请的buffer大小传给了这个参数,结果必然导致“卡顿”或者“快进”,“卡顿”是因为我在项目中是实时传输,会导致阻塞,毕竟数据量大了一倍,“快进”则是因为缓冲区的大小是实际读取数据的一半,有一半的数据在buffer中被自己给覆盖掉了,所以要慎重啊。


2、Makefile

  1. exe = record
  2. src = record.c
  3. CC = arm-linux-gcc
  4. INC = -I/nfs/usr/local/arm-alsa/include
  5. LDFLAGS = -lpthread -L/nfs/usr/local/arm-alsa/lib -lasound

  6. $(exe) : $(src) FORCE
  7.     $(CC) -o $@ $(src) $(LDFLAGS) $(INC)


  8. FORCE:

  9. clean:
  10.     rm -f ./*.o $(exe)

      此处的alsa-lib库就是之前介绍的安装的库的路径,编译可以引用该路径的库,而运行之后库的路径可不受限制,按照你定义的环境变量找到即可。
     对于内核的配置则在
     
  1. Device Drivers --->
  2. <*> Sound card support --->
  3. <*> Advanced Linux Sound Architecture --->
  4. [*] USB sound devices --->
  5. <*> USB Audio/MIDI driver


     对于这款USB麦克风,我正常的去录音的时候,上层的直观感觉就是卡顿,这个与上面提到的是有区别的,因为同样的代码在arm上是好的,所以就怀疑是底层读慢了,(我们的应用背景是开发板实时录音,通过USB-WIFI发到上位机同步播放)很明显的是读取音频数据慢了。而同样的代码跑硬件的CODEC是很好的,不卡顿,所以很有可能问题出在USB上。我们刚好有USB的协议分析仪,我们USB是跑的全速模式,其描述符为

  1. Interface Descriptor:
  2.       bLength 9
  3.       bDescriptorType 4
  4.       bInterfaceNumber 3
  5.       bAlternateSetting 0
  6.       bNumEndpoints 0
  7.       bInterfaceClass 1
  8.       bInterfaceSubClass 2
  9.       bInterfaceProtocol 0
  10.       iInterface 0
  11.     Interface Descriptor:
  12.       bLength 9
  13.       bDescriptorType 4
  14.       bInterfaceNumber 3
  15.       bAlternateSetting 1
  16.       bNumEndpoints 1
  17.       bInterfaceClass 1
  18.       bInterfaceSubClass 2
  19.       bInterfaceProtocol 0
  20.       iInterface 0
  21.       AudioStreaming Interface Descriptor:
  22.         bLength 7
  23.         bDescriptorType 36
  24.         bDescriptorSubtype 1 (AS_GENERAL)
  25.         bTerminalLink 3
  26.         bDelay 1 frames
  27.         wFormatTag 1 PCM
  28.       AudioStreaming Interface Descriptor:
  29.         bLength 11
  30.         bDescriptorType 36
  31.         bDescriptorSubtype 2 (FORMAT_TYPE)
  32.         bFormatType 1 (FORMAT_TYPE_I)
  33.         bNrChannels 1
  34.         bSubframeSize 2
  35.         bBitResolution 16
  36.         bSamFreqType 1 Discrete
  37.         tSamFreq[ 0] 16000
  38.       Endpoint Descriptor:
  39.         bLength 9
  40.         bDescriptorType 5
  41.         bEndpointAddress 0x83 EP 3 IN
  42.         bmAttributes 5
  43.           Transfer Type Isochronous
  44.           Synch Type Asynchronous
  45.           Usage Type Data
  46.         wMaxPacketSize 0x0020 1x 32 bytes
  47.         bInterval 4
  48.         bRefresh 0
  49.         bSynchAddress 0
  50.         AudioControl Endpoint Descriptor:
  51.           bLength 7
  52.           bDescriptorType 37
  53.           bDescriptorSubtype 1 (EP_GENERAL)
  54.           bmAttributes 0x01
  55.             Sampling Frequency
  56.           bLockDelayUnits 0 Undefined
  57.           wLockDelay 0 Undefined
  58. /************************************************************************/
  59.     Interface Descriptor:
  60.       bLength 9
  61.       bDescriptorType 4
  62.       bInterfaceNumber 3
  63.       bAlternateSetting 2
  64.       bNumEndpoints 1
  65.       bInterfaceClass 1
  66.       bInterfaceSubClass 2
  67.       bInterfaceProtocol 0
  68.       iInterface 0
  69.       AudioStreaming Interface Descriptor:
  70.         bLength 7
  71.         bDescriptorType 36
  72.         bDescriptorSubtype 1 (AS_GENERAL)
  73.         bTerminalLink 3
  74.         bDelay 1 frames
  75.         wFormatTag 1 PCM
  76.       AudioStreaming Interface Descriptor:
  77.         bLength 11
  78.         bDescriptorType 36
  79.         bDescriptorSubtype 2 (FORMAT_TYPE)
  80.         bFormatType 1 (FORMAT_TYPE_I)
  81.         bNrChannels 1
  82.         bSubframeSize 2
  83.         bBitResolution 16
  84.         bSamFreqType 1 Discrete
  85.         tSamFreq[ 0] 48000
  86.       Endpoint Descriptor:
  87.         bLength 9
  88.         bDescriptorType 5
  89.         bEndpointAddress 0x83 EP 3 IN
  90.         bmAttributes 5
  91.           Transfer Type Isochronous
  92.           Synch Type Asynchronous
  93.           Usage Type Data
  94.         wMaxPacketSize 0x0060 1x 96 bytes
  95.         bInterval 4
  96.         bRefresh 0
  97.         bSynchAddress 0
  98.         AudioControl Endpoint Descriptor:
  99.           bLength 7
  100.           bDescriptorType 37
  101.           bDescriptorSubtype 1 (EP_GENERAL)
  102.           bmAttributes 0x01
  103.             Sampling Frequency
  104.           bLockDelayUnits 0 Undefined
  105.           wLockDelay 0 Undefined
   
    看到描述符,顺便插一句,对照端点大小计算一下,蓝色字体,这款USB-AUDIO只支持16K和48K的16bit单声道录音,拿16K为例,1s数据量应该是16K*16/8=32KB,对应于端点的大小32B*1000=32KB,也就是说全速模式下应该是每帧(1ms)请求一次才对,而对于图中的红色字体,说明的意思是全速模式下的ISO传输请求间隔参数是4,对应我们的USB的控制器,意思即为每8帧才发起一次ISO请求,抓包验证确实如此,这一点确实比较诡异,问题可能就出在这里:



      但是对于几乎同样的驱动版本,我们611的是2.6.32.9而arm的是2.6.32.2,其sound目录下的usbaudio.c基本是相同的,描述符又是相同的,所以上层获取描述符进行的配置应该也是相同的,唯一的区别就是USB的控制器,我们611的是musb,而arm的是OHCI,我们musb对这个bInterval的配置是


因此驱动固然是8帧请求一次。我在OHCI的控制器中未找到类似的寄存器,猜想可能是OHCI默认的就是ISO传输每一帧会保证一次,其抓包图如下:



所以只好强制去修改musb的驱动配置,/drivers/usb/musb/musb_host.c

  1. 2013 /* precompute rxtype/txtype/type0 register */
  2. 2014 type_reg = (qh->type << 4) | qh->epnum;
  3. 2015 switch (urb->dev->speed) {
  4. 2016 case USB_SPEED_LOW:
  5. 2017 type_reg |= 0xc0;
  6. 2018 break;
  7. 2019 case USB_SPEED_FULL:
  8. 2020 type_reg |= 0x80;
  9. 2021 break;
  10. 2022 default:
  11. 2023 type_reg |= 0x40;
  12. 2024 }
  13. 2025 qh->type_reg = type_reg;
  14. 2026
  15. 2027 /* Precompute RXINTERVAL/TXINTERVAL register */
  16. 2028 switch (qh->type) {
  17. 2029 case USB_ENDPOINT_XFER_INT:
  18. 2030 /*
  19. 2031 * Full/low speeds use the linear encoding,
  20. 2032 * high speed uses the logarithmic encoding.
  21. 2033 */
  22. 2034 if (urb->dev->speed <= USB_SPEED_FULL) {
  23. 2035 interval = max_t(u8, epd->bInterval, 1);
  24. 2036 break;
  25. 2037 }
  26. 2038 /* FALLTHROUGH */
  27. 2039 case USB_ENDPOINT_XFER_ISOC:
  28. 2040 /* ISO always uses logarithmic encoding */
  29. 2041 //interval = min_t(u8, epd->bInterval, 16);
  30. 2042 interval = min_t(u8, epd->bInterval, 1); //JGF
  31. 2043 break;
  32. 2044 default:

这样USB就是每帧请求一次,同样的代码,效果和2440的也一样了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/253387.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fiddler4入门——手机抓包

一、下载工具包 百度搜索”fiddler 下载“ &#xff0c;安装最新版本 下载的软件安装包为“fiddler_4.6.20171.26113_setup.exe”格式&#xff0c;双击安装。安装成功&#xff0c;在“开始”-“所有程序”&#xff0c;就会看见这样的图标&#xff0c;若是常用的话&#xff0c;也…

(五)DOM4j进行XML文件的解析及生成

DOM4j本身还是需要使用SAX建立解析器&#xff0c;然后通过文档依次找到根节点&#xff0c;再通过根节点查找每一个节点的内容. 1.写操作 import java.io.File;import java.io.FileOutputStream;import java.util.Iterator; import org.dom4j.Document;import org.dom4j.Documen…

Linux系统基础.作业

要求以root用户登录系统&#xff0c;右击桌面打开终端&#xff0c;查看当前登陆Linux系统所使用的用户名 查看哪些用户在系统上工作 修改当前时间为2018年8月26号11:28 查看2015年10月份日历 使用两种方法查看ls命令的使用说明 清除屏幕 ctrlL使用“useradd tom”命令新建tom用…

Alsa中PCM参数设置

分类&#xff1a; LINUX 1) PCM设备的句柄.2) 指定同时可供回放或截获的PCM流的方向3) 提供一些关于我们想要使用的设置选项的信息,比如缓冲区大小,采样率,PCM数据格式等4) 检查硬件是否支持设置选项.4.1) 初始化PCM变量4.2) 分配hwparams结构4.3) 打开PCM设备4.4) 以声卡的全部…

java5

java基础&#xff08;五&#xff09;命名规则&#xff1a; 名字中只能包含->字母、_、数字、$&#xff0c;且开头不能为数字包名必须都小写文件名首字母和后面英文文件单词首字母都要大写变量和方法名 首字母小写&#xff0c;后面英文单词首字母大写java中的方法&#xff1a…

最新历史版本 :H.265

原来对264有深入的研究&#xff0c;现在想详细了解下265啦&#xff0c;愿265尽快广泛的使用起来&#xff0c;人们可以享受无处不在的视觉盛宴。 H.265是ITU-T VCEG 继H.264之后所制定的新的视频编码标准。H.265标准围绕着现有的视频编码标准H.264&#xff0c;保留原来的某些技术…

凯撒密码、GDP格式化输出、99乘法表

1.恺撒密码的编码 sinput(请输入明文:) print(密文为:) for i in s:print(chr(ord(i)3),end)运行结果为&#xff1a; 2.国家名称 GDP总量&#xff08;人民币亿元&#xff09; 中国 &#xffe5;765873.4375 澳大利亚 &#xffe5; 78312.4375 &#xff08;国家名称左对齐&am…

【BZOJ3453】XLkxc [拉格朗日插值法]

XLkxc Time Limit: 20 Sec Memory Limit: 128 MB[Submit][Status][Discuss]Description 给定 k,a,n,d,p  f(i)1^k2^k3^k......i^k  g(x)f(1)f(2)f(3)....f(x)  求(g(a)g(ad)g(a2d)......g(and))mod p Input 第一行数据组数&#xff0c;(保证小于6)  以下每行四个整数 …

hive安装

雷顿学院大数据雷顿学院大数据&#xff1a;http://www.leidun.site/hive安装下载hivehttp://mirror.bit.edu.cn/apache/hive/下载后解压配置命令将hive加入命令vim ~/.bash_profile添加如下命令export HIVE_HOME/usr/local/Cellar/hive/1.2.1/libexec保存文件mysql数据库驱动cu…

Alsa驱动分析(转)

1. Abstract 2. Introduction 3. 音频驱动框架介绍 3.1 音频设备的注册 3.2 音频驱动的注册 3.2.1 Probe函数的调用 3.2.2 Soc_probe函数 4. 通常的使用流程的分析 4.1.1 open过程介绍 4.1.2 snd_pcm_hw_params流程分析 4.1.3 …

[BZOJ] 1620: [Usaco2008 Nov]Time Management 时间管理

1620: [Usaco2008 Nov]Time Management 时间管理 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 850 Solved: 539[Submit][Status][Discuss]Description Ever the maturing businessman, Farmer John realizes that he must manage his time effectively. He has N jobs con…

DDR工作原理

DDR SDRAM全称为Double Data Rate SDRAM&#xff0c;中文名为“双倍数据流SDRAM”。DDR SDRAM在原有的SDRAM的基础上改进而来。也正因为如此&#xff0c;DDR能够凭借着转产成本优势来打败昔日的对手RDRAM&#xff0c;成为当今的主流。本文只着重讲讲DDR的原理和DDR SDRAM相对于…

智能故事机方案简介

智能故事机&#xff0c;又叫WiFi故事机&#xff0c;AI故事机&#xff0c;通过WiFi联网&#xff0c;用户语音就可以跟它进行问答、点歌等互动&#xff1b;由于联网所以可以播放云端海量的儿童音频内容&#xff1b;手机端在微信公众号或者专属APP上操作&#xff0c;可以点播相应内…

weui-switch开关控件,表单提交后如何取值

最近在学习weui这个框架&#xff0c;做了一些小的试验&#xff0c;发现weui-switch控件直接提交不能获取到表单信息&#xff0c;在segmentfault上发现也有人提了这个问题&#xff0c;有人说可以设置一个隐含标签来捕获开关的状态&#xff0c;试了一下&#xff0c;确实可以&…

麦克风设计指导与选型参考

随着语音识别技术的成熟&#xff0c;智能音箱类产品的火爆&#xff0c;越来越多的产品可以升级为语音交互产品&#xff1b; 下面简单介绍下此类产品的语音前端--麦克风阵列设计相关注意事项&#xff1a; 线性四麦阵列构型&#xff1a;如上图所示&#xff0c;麦克风直线等距摆…

云计算在未来一定是不可或缺的

2019独角兽企业重金招聘Python工程师标准>>> 在2018京东云合作伙伴大会上&#xff0c;京东云总裁申元庆表示&#xff0c;技术发展的大趋势是“分久必合&#xff0c;合久必分”循环往复的波动&#xff0c;近十年来云计算的发展将算力、存储、带宽全部集中在中央部分&…

智能音箱 之 音频通路质量--测试与参数

一、概述 当将语音识别算法接入到设备时&#xff0c;务必要保证设备的音频通路具有足够的质量。因此对设备进行音频测试&#xff0c;以评估能够影响语音识别性能的音频前端的音频参数。如下要点对语音识别至关重要&#xff1a; 自然声音合适的增益良好的信噪比一致的响应&…

Python学习 - 常用模块(二)

目录 一. 常用模块 - hashlib 二. 常用模块 - hmac 三. 常用模块 - logging 四. 常用模块 - re 五. 常用模块 - requests 六. 常用模块 - paramiko 一. 常用模块 - hashlib hash: 一种算法, 3.x里代替了md5模块和sha模块, 主要提供 SHA1, SHA224, SHA256, SHA384, SHA512, MD5 …

UART介绍

1. 概述 UART, Universal Asynchronous Receiver-Transmitter, 通用异步收发器&#xff1b; 串口&#xff1a;在嵌入式里指的是UART口&#xff0c;常用TTL电平即3.3V或者5.0V&#xff1b; COM口&#xff1a;在台式机上常用的口&#xff0c;DB9那种接口&#xff0c;接口协议只…

mongodb环境安装

1、mongodb安装 我采用的是离线安装&#xff0c; &#xff08;1&#xff09;在mongodb的官方网址下载所需要的版本。我下载的是 mongodb-linux-x86_64-ubuntu1604-3.4.5.tgz 。 &#xff08;2&#xff09;下载后解压缩到待安装目录&#xff0c;我这里下载在了Downloads目录…