[嵌入式开发模块]环形缓冲区/循环队列C语言实现

李肖遥 2023-03-22 21:53
    关注、星标公众号,直达精彩内容

来源:https://blog.csdn.net/lin_strong/article/details/73604561



这里分享一个自己用纯C实现的环形缓冲区。

环形缓冲区有很多作用,比如嵌入式中的通信可以用环形缓冲区作为信道,一个线程往里放字节,一个线程取字节进行处理,只要保证取的速度大于读的速度,就可以保证通信顺畅进行,不丢一个字节。

简要介绍:

环形缓冲区其实就是一个队列,里头的元素是先入先出的,但是因为其(逻辑上)是环形的,所以不需要像很多队列的实现那样在内部元素变动的时候需要移动内部剩下的元素。这样就使元素出队入队的时间复杂度只有O(1)。具体实现一般有链表和数组两种方法,当不能确定需要的缓冲区大小时使用链表较好,能确定时使用数组可以节省很多动态分配内存的开销。

在嵌入式开发中,一般不动态分配内存,而是使用静态分配的数组。所以这里我使用数组实现了环形缓冲区,为了能够在不同的程序中复用代码,使用结构体模拟了面向对象编程,这样就可以用一套代码管理不同的缓冲区了。

废话不多说,直接上代码。以下是.h 文件:

/*
*********************************************************************************************************
*
*
*                                       RingQueueStruct
*                                         环形队列结构
*
* File : RingQueue.h
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date : 2018/02/23
* version: V1.2
* NOTE(s): 这段程序用来对一个给定的缓冲区进行模拟环形队列的管理
*                   程序本身不会自动分配缓冲区空间,用户需要自己负责分配空间,并且要保证不直接访问缓存区
*                   // 在某处分配内存空间
*                   RQTYPE buffer[BUFFER_SIZE];
*                   RING_QUEUE que,*ptr_que;
*                   unsigned char err;
*                   // 初始化
*                   ptr_que = RingQueueInit(&que,buffer,BUFFER_SIZE,&err);
*                   if(err == RQ_ERR_NONE  ){
*                     // 初始化成功,使用其他函数
*                   }
* History : 2017/04/25   the original version of RingQueueStruct.
*           2017/10/16   put functions used frequently,RingQueueIn and RingQueueOut, in non-banked address;
*                        modify single line function RingQueueIsEmpty and RingQueueIsFull to marco function;
*                        to get better efficiency.
*           2018/02/23   1.add the marco(RQ_ARGUMENT_CHECK_EN) to controll argument check so user can save 
*                          more code.
*                        2.add the ADDRESSING MODE so the buffer can be defined in banked addressing area.
*********************************************************************************************************
*/



#ifndef   RING_QUEUE_H
#define   RING_QUEUE_H

/*
********************************************************************************************
*                                   MISCELLANEOUS
********************************************************************************************
*/


#ifndef  FALSE
#define  FALSE    0
#endif

#ifndef  TRUE
#define  TRUE     1
#endif

/*
*********************************************************************************************************
*                                       ADDRESSING MODE 寻址模式
*********************************************************************************************************
*/


// uncomment the corresponding line to select the addressing mode to the buffer of RingQueue module.
// if you don't understand. Just use the extended addressing mode
// 取消对应行的注释以选择环形缓冲区模块访问缓冲区时使用的寻址方式
// 如果你不知道这是什么意思的话,那就用扩展寻址就行了,这是默认的方式

// extended addressing mode 扩展区寻址(默认)
#define RQ_ADDRESSING_MODE
// banked RAM addressing mode   RAM分页区寻址
//#define RQ_ADDRESSING_MODE __rptr
// global addressing mode   全局寻址
//#define RQ_ADDRESSING_MODE __far

/*
*********************************************************************************************************
*                                       CONFIGURATION  配置
*********************************************************************************************************
*/


#define RQ_ARGUMENT_CHECK_EN    TRUE     // TRUE: arguments will be checked, however,this will 
                                         //       cost a little code volume.

/*
*********************************************************************************************************
*                                        CONSTANTS     常量
*********************************************************************************************************
*/

#define   RQ_ERR_NONE                        0u

#define   RQ_ERR_POINTER_NULL                1u
#define   RQ_ERR_SIZE_ZERO                   2u

#define   RQ_ERR_BUFFER_FULL                 3u
#define   RQ_ERR_BUFFER_EMPTY                4u

#define   RQ_OPTION_WHEN_FULL_DISCARD_FIRST  0u       // discard the first element when ring buffer is full
#define   RQ_OPTION_WHEN_FULL_DONT_IN        1u       // discard new element when ring buffer is full
/*
*********************************************************************************************************
*                                    DATA TYPE    数据类型
*********************************************************************************************************
*/


// define the data type that stores in the RingQueue.       定义存在环形缓冲区内的数据的类型
typedef unsigned char RQTYPE;
typedef RQTYPE *RQ_ADDRESSING_MODE pRQTYPE;
typedef struct {
    unsigned short  RingBufCtr;              /* Number of characters in the ring buffer */
    unsigned short  RingBufSize;             /* Ring buffer Size */    
    pRQTYPE RingBufInPtr;                    /* Pointer to where next character will be inserted        */  
    pRQTYPE RingBufOutPtr;                   /* Pointer from where next character will be extracted     */  
    pRQTYPE RingBuf;                         /* Ring buffer array */  
    pRQTYPE RingBufEnd;                      /* Point to the end of the buffer */
} RING_QUEUE;

/*
*********************************************************************************************************
*                                  FUNCTION PROTOTYPES 函数原型
*********************************************************************************************************
*/


RING_QUEUE *RingQueueInit(RING_QUEUE *pQueue,pRQTYPE pbuf,unsigned short bufSize,unsigned char *perr);
#pragma CODE_SEG __NEAR_SEG NON_BANKED
unsigned short RingQueueIn(RING_QUEUE *pQueue,RQTYPE data,unsigned char option,unsigned char *perr);
RQTYPE RingQueueOut(RING_QUEUE *pQueue,unsigned char *perr);
#pragma CODE_SEG DEFAULT
short RingQueueMatch(RING_QUEUE *pQueue,pRQTYPE pbuf,unsigned short len);
void RingQueueClear(RING_QUEUE *pQueue);

/*
*********************************************************************************************************
*                                        RingQueueIsEmpty()
*
* Description :  whether the RingQueue is empty.   环形队列是否为空
*
* Arguments   :  pQueue  pointer to the ring queue control block;     指向环形队列控制块的指针
*
* Return      :  TRUE    the RingQueue is empty.
*                FALSE   the RingQueue is not empty.
* Note(s)     :
*********************************************************************************************************
*/


#define RingQueueIsEmpty(pQueue) ((pQueue)->RingBufCtr == 0)

/*
*********************************************************************************************************
*                                        RingQueueIsFull()
*
* Description : whether the RingQueue is full.    环形队列是否为空
*
* Arguments   : pQueue  pointer to the ring queue control block;   指向环形队列控制块的指针
*
* Return      : TRUE    the RingQueue is full.
*               FALSE   the RingQueue is not full.
* Note(s)     :
*********************************************************************************************************
*/


#define RingQueueIsFull(pQueue)  ((pQueue)->RingBufCtr >= (pQueue)->RingBufSize)

#endif

然后下面是.c文件。

/*
*********************************************************************************************************
*
*
*                                       RingQueueStruct
*                                         环形队列结构
*
* File : RingQueue.c
* By   : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date : 2018/02/23
* version: V1.2 
* NOTE(s): 
*
* History : 2017/04/25   the original version of RingQueueStruct.
*           2017/10/16   put functions used frequently,RingQueueIn and RingQueueOut, in non-banked address;
*                        modify single line function RingQueueIsEmpty and RingQueueIsFull to marco function;
*                        to get better efficiency.
*           2018/02/23   1.add the marco(RQ_ARGUMENT_CHECK_EN) to controll argument check so user can save 
*                          more code.
*                        2.add the ADDRESSING MODE so the buffer can be defined in banked addressing area.
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                     INCLUDES
*********************************************************************************************************
*/

#include "RingQueue.h"

/*
*********************************************************************************************************
*                                LOCAL FUNCTION DECLARATION
*********************************************************************************************************
*/


#if(RQ_ARGUMENT_CHECK_EN == TRUE)
  #define argCheck(cond,err,rVal)  if(cond) { *perr = (err); return (rVal); }
#else
  #define argCheck(cond,err,rVal)
#endif // of (SPI_ARGUMENT_CHECK_EN == TRUE)



/*
*********************************************************************************************************
*                                LOCAL FUNCTION DECLARE
*********************************************************************************************************
*/

#pragma CODE_SEG __NEAR_SEG NON_BANKED
// 内部使用,给定将给定指针在环形缓冲区内向前移动一步(到尾了会移回头)
static void _forwardPointer(RING_QUEUE *pQueue,pRQTYPE* pPointer);
#pragma CODE_SEG DEFAULT
/*
*********************************************************************************************************
*                                        RingQueueInit()
*
* Description : To initialize the ring queue.    初始化环形队列
*
* Arguments   : pQueue   pointer to the ring queue control block;     指向环形队列控制块的指针
*               pbuf     pointer to the buffer(an array);             指向自定义的缓冲区(实际就是个数组)
*               bufSize  the Size of the buffer;                      缓冲区的大小;
*               perr     a pointer to a variable containing an error message which will be set by this
*                          function to either:
*
*                           RQ_ERR_NONE                                       
*                           RQ_ERR_SIZE_ZERO
*                           RQ_ERR_POINTER_NULL
*
* Return      : the pointer to the ring queue control block;        返回指向环形队列控制块的指针
*               0x00 if any error;                                  如果出错了则返回NULL
*
*Note(s):
*********************************************************************************************************
*/


RING_QUEUE* RingQueueInit(RING_QUEUE *pQueue,pRQTYPE pbuf,unsigned short bufSize,unsigned char *perr){
  argCheck(pQueue == 0x00 || pbuf == 0x00,RQ_ERR_POINTER_NULL,0x00);
  argCheck(bufSize == 0,RQ_ERR_SIZE_ZERO,0x00);
  pQueue->RingBufCtr = 0;
  pQueue->RingBuf = pbuf;
  pQueue->RingBufInPtr = pbuf;
  pQueue->RingBufOutPtr = pbuf;
  pQueue->RingBufSize = bufSize;
  pQueue->RingBufEnd = pbuf + bufSize;
  *perr = RQ_ERR_NONE;     
  return pQueue;
}

/*
*********************************************************************************************************
*                                        RingQueueIn()
*
* Description : Enqueue an element.    入队一个元素
*
* Arguments   : pQueue   pointer to the ring queue control block;    指向环形队列控制块的指针
*               data     the data to enqueue;                        要入队的数据
*               option   option when queue is full ,you can choose:  当队列满的时候的选项,你可以选择:
*                            RQ_OPTION_WHEN_FULL_DISCARD_FIRST          抛弃队头的元素来填进去新的元素
*                            RQ_OPTION_WHEN_FULL_DONT_IN                不入队新给的元素
*               perr     a pointer to a variable containing an error message which will be set by this
*                          function to either:
*
*                             RQ_ERR_NONE                            if no err happen
*                             RQ_ERR_POINTER_NULL                    if pointer is 0x00
*                             RQ_ERR_BUFFER_FULL                     if buffer is full
*
* Return       : the Elements Count after enqueue the element
*                    调用函数后队列中的元素个数
*Note(s)       :
*********************************************************************************************************
*/

#pragma CODE_SEG __NEAR_SEG NON_BANKED
unsigned short RingQueueIn(RING_QUEUE *pQueue,RQTYPE data,unsigned char option,unsigned char *perr){
  argCheck(pQueue == 0x00,RQ_ERR_POINTER_NULL,0x00);
  if(pQueue->RingBufCtr >= pQueue->RingBufSize){
    *perr = RQ_ERR_BUFFER_FULL;     
    if(option == RQ_OPTION_WHEN_FULL_DISCARD_FIRST){
      _forwardPointer(pQueue,&pQueue->RingBufOutPtr); /* Wrap OUT pointer                          */  
    }else{                                            // option == RQ_OPTION_WHEN_FULL_DONT_IN
      return pQueue->RingBufCtr;
    }
  }else{
    pQueue->RingBufCtr++;                             /* No, increment character count            */      
    *perr = RQ_ERR_NONE;
  }
  *pQueue->RingBufInPtr = data;                       /* Put character into buffer                */  
  _forwardPointer(pQueue,&pQueue->RingBufInPtr);      /* Wrap IN pointer                          */  
  return pQueue->RingBufCtr;
}
/*
*********************************************************************************************************
*                                        RingQueueOut()
*
* Description : Dequeue an element.       出队一个元素
*
* Arguments   : pQueue   pointer to the ring queue control block;     指向环形队列控制块的指针
*               perr     a pointer to a variable containing an error message which will be set by this
*                          function to either:
*
*                              RQ_ERR_NONE                            if no err happen
*                              RQ_ERR_POINTER_NULL                    if pointer is 0x00
*                              RQ_ERR_BUFFER_EMPTY                    if buffer is empty
*
* Return      : 0                 if any error or the data is 0;
*               others            the data 
*               
*Note(s):
*********************************************************************************************************
*/

RQTYPE RingQueueOut(RING_QUEUE *pQueue,unsigned char *perr){
  RQTYPE data;
  argCheck(pQueue == 0x00,RQ_ERR_POINTER_NULL,0x00);
  if(pQueue->RingBufCtr == 0){
    *perr = RQ_ERR_BUFFER_EMPTY;        
    return 0;
  }
  pQueue->RingBufCtr--;                                      /*  decrement character count           */  
  data = *pQueue->RingBufOutPtr;                      /* Get character from buffer                */  
  _forwardPointer(pQueue,&pQueue->RingBufOutPtr);        /* Wrap OUT pointer                          */  
  *perr = RQ_ERR_NONE;
  return data;
}
#pragma CODE_SEG DEFAULT
/*
*********************************************************************************************************
*                                        RingQueueMatch()
*
* Description : Match the given buffer in RingQueue          在环形队列中匹配给定缓冲区
*
* Arguments   : pQueue   pointer to the ring queue control block;     指向环形队列控制块的指针
*               pbuf     pointer to the chars need to match;
*               len      the length of the chars
* Return      :  -1       Don't match            -1    则没有匹配到
*                >= 0     match                  >= 0  则匹配到了
*
*Note(s):
*********************************************************************************************************
*/


short RingQueueMatch(RING_QUEUE *pQueue,pRQTYPE pbuf,unsigned short len){
  pRQTYPE pPosQ,pCurQ,pCurB,pEndB;
  unsigned short rLen,Cnt;
  if(len > pQueue->RingBufCtr)
    return -1;
  pPosQ = pQueue->RingBufOutPtr;
  pEndB = pbuf + len;
  Cnt = 0;
  rLen = pQueue ->RingBufCtr;
  while(rLen-- >= len){          // if remian length of queue bigger than buffer. continue
    pCurQ = pPosQ;
    pCurB = pbuf;
    while(pCurB != pEndB && *pCurQ == *pCurB) {    // compare one by one,until match all(pCurB==pEndB) or some one don't match
      _forwardPointer(pQueue,&pCurQ);
      pCurB++;
    }
    if(pCurB == pEndB)                                                 // if match all
       return Cnt;
     Cnt++;
     _forwardPointer(pQueue,&pPosQ);
  }
  return -1;
}

/*
*********************************************************************************************************
*                                        RingQueueClear()
*
* Description:  Clear the RingQueue.        清空环形队列
*
* Arguments  :  pQueue    pointer to the ring queue control block;     指向环形队列控制块的指针
*
* Return:             
*
* Note(s):
*********************************************************************************************************
*/


void RingQueueClear(RING_QUEUE *pQueue){
#if(RQ_ARGUMENT_CHECK_EN == TRUE)
  if(pQueue == 0x00)
    return;
#endif
  pQueue->RingBufCtr = 0;
  pQueue->RingBufInPtr = pQueue -> RingBufOutPtr;
}

/*
*********************************************************************************************************
*                                       LOCAL FUNCTION 
*********************************************************************************************************
*/


#pragma CODE_SEG __NEAR_SEG NON_BANKED
static void _forwardPointer(RING_QUEUE *pQueue,pRQTYPE* pPointer){
  if (++*pPointer == pQueue->RingBufEnd)   
    *pPointer = pQueue->RingBuf;        /* Wrap OUT pointer                          */  
}
#pragma CODE_SEG DEFAULT

简单解释下。

在.h文件中定义了一个环形缓冲区的控制块,当然也可以当其为一个环形缓冲区对象,用户需要为每个环形缓冲区分配一个控制块和其缓冲区(也就是一个数组)。理想情况下,虽然用户知道控制块的结构,但也不应该直接访问内部字段,而应该通过提供的函数来访问。

队列中默认的元素是无符号字符,如果要改成缓存其他类型的话改下.h文件中的typedef unsigned char RQTYPE;这行就行了。

使用示例:

#include "RingQueue.h"
#define RX_BUF_MAX_SIZE     200        // 定义缓冲区的最大大小为200
static unsigned char RxBuffer[RX_BUF_MAX_SIZE];   // 定义缓冲区
static RING_QUEUE RxRingQ;             // 定义环形缓冲区的控制块
void main(){
   unsigned char err;
   // 初始化缓冲区
   RingQueueInit(&RxRingQ,RxBuffer,RX_BUF_MAX_SIZE,&err);
   if(err != RQ_ERR_NONE){
       //初始化缓冲区失败的处理
   }
   ……
}

然后调用所有方法都需要传递环形缓冲区控制块的指针。如入队就像:

// 往RxRingQ缓冲区内入队一个元素c,如果满的话丢弃第一个元素
RingQueueIn(&RxRingQ,c,RQ_OPTION_WHEN_FULL_DISCARD_FIRST,&err); 

出队就像:

// 从RxRingQ缓冲区内提取一个字符
c = RingQueueOut(&RxRingQ,&err);

其他就不一 一举例了。要特别说明下的是RingQueueMatch()这个方法并不是队列应该有的方法,这是为了比如我需要在缓冲区中匹配到某一串字符后做某些事情而特别加上的,不需要的话删掉即可。比如我需要一旦出现“abc”就做某些事情,那我代码可以类似这么写:

static const unsigned char* StringsWait = "abc";
……
while(true){
    //比如从某处获得了下一个字符c
    ……
    // 将字符c入队
    RingQueueIn(&RxRingQ,c,RQ_OPTION_WHEN_FULL_DISCARD_FIRST,&err); 
    if(RingQueueMatch(&RxRingQ,StringsWait,3) >= 0){  // 如果在缓冲区内找到"abc"
         // RingQueueClear(&RxRingQ);     // 可能需要清空缓冲区
         // 做想要做的事
         ……
    }
}

有什么建议或意见请留言,谢谢!

版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

关注我的微信公众号,回复“加群”按规则加入技术交流群。


点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

李肖遥 公众号“技术让梦想更伟大”,作者:李肖遥,专注嵌入式,只推荐适合你的博文,干货,技术心得,与君共勉。
评论
  • 戴上XR眼镜去“追龙”是种什么体验?2024年11月30日,由上海自然博物馆(上海科技馆分馆)与三湘印象联合出品、三湘印象旗下观印象艺术发展有限公司(下简称“观印象”)承制的《又见恐龙》XR嘉年华在上海自然博物馆重磅开幕。该体验项目将于12月1日正式对公众开放,持续至2025年3月30日。双向奔赴,恐龙IP撞上元宇宙不久前,上海市经济和信息化委员会等部门联合印发了《上海市超高清视听产业发展行动方案》,特别提到“支持博物馆、主题乐园等场所推动超高清视听技术应用,丰富线下文旅消费体验”。作为上海自然
    电子与消费 2024-11-30 22:03 107浏览
  • 概述 说明(三)探讨的是比较器一般带有滞回(Hysteresis)功能,为了解决输入信号转换速率不够的问题。前文还提到,即便使能滞回(Hysteresis)功能,还是无法解决SiPM读出测试系统需要解决的问题。本文在说明(三)的基础上,继续探讨为SiPM读出测试系统寻求合适的模拟脉冲检出方案。前四代SiPM使用的高速比较器指标缺陷 由于前端模拟信号属于典型的指数脉冲,所以下降沿转换速率(Slew Rate)过慢,导致比较器检出出现不必要的问题。尽管比较器可以使能滞回(Hysteresis)模块功
    coyoo 2024-12-03 12:20 170浏览
  • 遇到部分串口工具不支持1500000波特率,这时候就需要进行修改,本文以触觉智能RK3562开发板修改系统波特率为115200为例,介绍瑞芯微方案主板Linux修改系统串口波特率教程。温馨提示:瑞芯微方案主板/开发板串口波特率只支持115200或1500000。修改Loader打印波特率查看对应芯片的MINIALL.ini确定要修改的bin文件#查看对应芯片的MINIALL.ini cat rkbin/RKBOOT/RK3562MINIALL.ini修改uart baudrate参数修改以下目
    Industio_触觉智能 2024-12-03 11:28 110浏览
  • 11-29学习笔记11-29学习笔记习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-02 23:58 92浏览
  • 作为优秀工程师的你,已身经百战、阅板无数!请先醒醒,新的项目来了,这是一个既要、又要、还要的产品需求,ARM核心板中一个处理器怎么能实现这么丰富的外围接口?踌躇之际,你偶阅此文。于是,“潘多拉”的魔盒打开了!没错,USB资源就是你打开新世界得钥匙,它能做哪些扩展呢?1.1  USB扩网口通用ARM处理器大多带两路网口,如果项目中有多路网路接口的需求,一般会选择在主板外部加交换机/路由器。当然,出于成本考虑,也可以将Switch芯片集成到ARM核心板或底板上,如KSZ9897、
    万象奥科 2024-12-03 10:24 96浏览
  • 当前,智能汽车产业迎来重大变局,随着人工智能、5G、大数据等新一代信息技术的迅猛发展,智能网联汽车正呈现强劲发展势头。11月26日,在2024紫光展锐全球合作伙伴大会汽车电子生态论坛上,紫光展锐与上汽海外出行联合发布搭载紫光展锐A7870的上汽海外MG量产车型,并发布A7710系列UWB数字钥匙解决方案平台,可应用于数字钥匙、活体检测、脚踢雷达、自动泊车等多种智能汽车场景。 联合发布量产车型,推动汽车智能化出海紫光展锐与上汽海外出行达成战略合作,联合发布搭载紫光展锐A7870的量产车型
    紫光展锐 2024-12-03 11:38 126浏览
  • 最近几年,新能源汽车愈发受到消费者的青睐,其销量也是一路走高。据中汽协公布的数据显示,2024年10月,新能源汽车产销分别完成146.3万辆和143万辆,同比分别增长48%和49.6%。而结合各家新能源车企所公布的销量数据来看,比亚迪再度夺得了销冠宝座,其10月新能源汽车销量达到了502657辆,同比增长66.53%。众所周知,比亚迪是新能源汽车领域的重要参与者,其一举一动向来为外界所关注。日前,比亚迪汽车旗下品牌方程豹汽车推出了新车方程豹豹8,该款车型一上市就迅速吸引了消费者的目光,成为SUV
    刘旷 2024-12-02 09:32 138浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2024-12-02 10:40 143浏览
  •         温度传感器的精度受哪些因素影响,要先看所用的温度传感器输出哪种信号,不同信号输出的温度传感器影响精度的因素也不同。        现在常用的温度传感器输出信号有以下几种:电阻信号、电流信号、电压信号、数字信号等。以输出电阻信号的温度传感器为例,还细分为正温度系数温度传感器和负温度系数温度传感器,常用的铂电阻PT100/1000温度传感器就是正温度系数,就是说随着温度的升高,输出的电阻值会增大。对于输出
    锦正茂科技 2024-12-03 11:50 141浏览
  • TOF多区传感器: ND06   ND06是一款微型多区高集成度ToF测距传感器,其支持24个区域(6 x 4)同步测距,测距范围远达5m,具有测距范围广、精度高、测距稳定等特点。适用于投影仪的无感自动对焦和梯形校正、AIoT、手势识别、智能面板和智能灯具等多种场景。                 如果用ND06进行手势识别,只需要经过三个步骤: 第一步&
    esad0 2024-12-04 11:20 103浏览
  • RDDI-DAP错误通常与调试接口相关,特别是在使用CMSIS-DAP协议进行嵌入式系统开发时。以下是一些可能的原因和解决方法: 1. 硬件连接问题:     检查调试器(如ST-Link)与目标板之间的连接是否牢固。     确保所有必要的引脚都已正确连接,没有松动或短路。 2. 电源问题:     确保目标板和调试器都有足够的电源供应。     检查电源电压是否符合目标板的规格要求。 3. 固件问题: &n
    丙丁先生 2024-12-01 17:37 114浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦