【嵌入式】HC32F07X CAN通讯配置和使用配置不同缓冲器以连续发送

一 背景说明

        使用小华(华大)的MCU HC32F07X实现 CAN 通讯配置和使用

二 原理分析

【1】CAN原理说明(参考文章《CAN通信详解》):

        CAN是控制器局域网络(Controller Area Network, CAN)的简称,是一种能够实现分布式实时控制的串行通信网络。

        (i)CAN通信形式:CAN 使用称为 CANH / CANL 的通信线路执行传输和接收。电位差较小的电信号称为隐性信号,其逻辑值为1。电位差较大的电信号称为显性信号,其逻辑值0。如果通信总线上发生显性和隐性冲突,则显性优先。总线空闲时保持隐性。

        (ii)CAN数据格式:CAN的数据定义了有5种帧类型:

        (ii)CAN数据帧:数据帧一般由 7 个段构成,即:

(1) 帧起始。表示数据帧开始的段。
(2) 仲裁段。表示该帧优先级的段。
(3) 控制段。表示数据的字节数及保留位的段。
(4) 数据段。数据的内容,一帧可发送 0~8 个字节的数据。
(5) CRC 段。检查帧的传输错误的段。
(6) ACK 段。表示确认正常接收的段。
(7) 帧结束。表示数据帧结束的段

        图中 D 表示显性电平, R 表示隐形电平。

        更多具体内容不再赘述,可以参考上面的文章链接或者自行搜索。

【2】HC32F07X的CAN外设

        芯片CAN外设的主要特性:

■ 完全支持 CAN2.0A/CAN2.0B 协议。
■ 向上兼容 CAN-FD 协议。
■ 支持最高通信波特率 1Mbit/s
■ 支持 1~1/256 的波特率预分频, 灵活配置波特率。
■ 10 个接收缓冲器
- FIFO 方式
- 错误或者不被接收的数据不会覆盖存储的消息
■ 1 个高优先主发送缓冲器 PTB
■ 4 个副发送缓冲器 STB
- FIFO 方式
- 优先级仲裁方式
■ 8 组独立的筛选器
- 支持 11 位标准 ID 和 29 位扩展 ID
- 可编程 ID CODE 位以及 MASK 位
■ PTB/STB 均支持支持单次发送模式
■ 支持静默模式
■ 支持回环模式
■ 支持捕捉传输的错误种类以及定位仲裁失败位置
■ 可编程的错误警告值
■ 支持 ISO11898-4 规定时间触发 CAN 以及接收时间戳

        系统框图如下:

        更多详细的内容可以参考HC32F07X芯片的DATASHEET。

三 CAN通讯硬件设计

        以下推荐了两个CAN收发的硬件电路,可以将外部的 CANH/CANL 差分信号,转换为 CAN_TX/CAN_RX 信号用以内部MCU处理。一个是官方提供的,一个是开发板提供的,都可以正常使用。

        注意CAN通信需要5V,用以给收发器供电

【1】推荐电路1

        参考官方的硬件设计指南《AN_HC32L072_HC32L073_HC32F072系列硬件开发指南_Rev1.1》,里面对于CAN通信收发的硬件电路有如下推荐电路,其中使用了NXP的 TJA1042 作为收发器

【2】推荐电路2

        使用的周立功开发板中也引出了CAN功能,其中使用了NXP的TJA1051T作为收发器

四 CAN通讯软件配置

        选用引脚 PD00(CAN_RX)、PD01(CAN_TX)、PC12(CAN_STB)实现CAN通信功能,使用时钟频率为48MHz(官方例程使用的是外部8M晶振),CAN通讯波特率为1M,标准帧ID号为1。

【1】系统时钟配置

static void App_SysClkInit(void)
{stc_sysctrl_clk_cfg_t stcCfg;stc_sysctrl_pll_cfg_t stcPLLCfg;Sysctrl_SetPeripheralGate(SysctrlPeripheralFlash, TRUE);    ///< 使能FLASH模块的外设时钟Flash_WaitCycle(FlashWaitCycle1);Sysctrl_SetRCHTrim(SysctrlRchFreq4MHz);             ///< PLL使用RCH作为时钟源,因此需要先设置RCHstcPLLCfg.enInFreq    = SysctrlPllInFreq4_6MHz;     ///< RCH 4MHzstcPLLCfg.enOutFreq   = SysctrlPllOutFreq36_48MHz;  ///< PLL 输出48MHzstcPLLCfg.enPllClkSrc = SysctrlPllRch;              ///< 输入时钟源选择RCHstcPLLCfg.enPllMul    = SysctrlPllMul12;            ///< 4MHz x 12 = 48MHzSysctrl_SetPLLFreq(&stcPLLCfg);///< 选择PLL作为HCLK时钟源;stcCfg.enClkSrc  = SysctrlClkPLL;///< HCLK SYSCLK/2stcCfg.enHClkDiv = SysctrlHclkDiv1;///< PCLK 为HCLK/8stcCfg.enPClkDiv = SysctrlPclkDiv1;///< 系统时钟初始化Sysctrl_ClkInit(&stcCfg);
}

【2】CAN初始化GPIO

//CAN通信引脚定义
#define CAN_RX_PORT     (GpioPortD)
#define CAN_RX_PIN      (GpioPin0)
#define CAN_TX_PORT     (GpioPortD)
#define CAN_TX_PIN      (GpioPin1)
#define CAN_STB_PORT    (GpioPortC)
#define CAN_STB_PIN     (GpioPin12)#define  APB1_CLK       48000000    //CAN 的输入时钟
#define  CAN_BAUD       1000000     //CAN 的波特率/**************************************************************************
* 函数名称: COM_Init
* 功能描述: CAN通信初始化GPIO
**************************************************************************/
void COM_Init(void)
{stc_gpio_cfg_t stcGpioCfg;Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);stcGpioCfg.enDir = GpioDirIn;       ///< 端口方向配置->输入stcGpioCfg.enDrv = GpioDrvL;        ///< 端口驱动能力配置->高驱动能力stcGpioCfg.enPu  = GpioPuDisable;   ///< 端口上下拉配置->无stcGpioCfg.enPd  = GpioPdDisable;stcGpioCfg.enOD  = GpioOdDisable;   ///< 端口开漏输出配置->开漏输出关闭stcGpioCfg.enCtrlMode = GpioAHB;    ///< 端口输入/输出值寄存器总线控制模式配置->AHBGpio_Init(CAN_RX_PORT, CAN_RX_PIN, &stcGpioCfg);stcGpioCfg.enDir = GpioDirOut;Gpio_Init(CAN_TX_PORT, CAN_TX_PIN, &stcGpioCfg);Gpio_Init(CAN_STB_PORT, CAN_STB_PIN, &stcGpioCfg);///<CAN RX\TX复用功能配置Gpio_SetAfMode(CAN_RX_PORT, CAN_RX_PIN, GpioAf1);Gpio_SetAfMode(CAN_TX_PORT, CAN_TX_PIN, GpioAf1);///<STB 低-PHY有效Gpio_ClrIO(CAN_STB_PORT, CAN_STB_PIN);
}

【3】CAN波特率自适应配置接口

/**************************************************************************
* 函数名称: COM_BaudCfg
* 功能描述: CAN通信波特率自动配置
* 其他说明: 48MHz主频,1M波特率计算得到:SJW=2, PRESC=1-1, SEG_2=15, SEG_1=30若输入500K波特率,PRESC为2-1; 输入250K波特率,PRESC为4-1
**************************************************************************/
void COM_BaudCfg(stc_can_init_config_t *p_stcCanInitCfg, uint32_t src_clk, uint32_t baud)
{uint32_t i,value = baud,record = 1;uint32_t remain = 0,sum_prescaler = 0;while(( baud == 0 )||( src_clk == 0 ));sum_prescaler = src_clk / baud;for ( i = 73; i > 3; i-- ) {remain = sum_prescaler - ((sum_prescaler / i)*i);if( remain == 0 ) {record = i;break;} else {if (remain < value) {value = remain;record = i;}}}/* 设置重新同步跳跃宽度为2个时间单位 */p_stcCanInitCfg->stcCanBt.SJW = 2;p_stcCanInitCfg->stcCanBt.PRESC = (sum_prescaler/record) - 1;p_stcCanInitCfg->stcCanBt.SEG_2 = (record - 3) / 3;p_stcCanInitCfg->stcCanBt.SEG_1 = (record - 3) - p_stcCanInitCfg->stcCanBt.SEG_2;
}

        【注】:CAN波特率的计算和配置,也可以使用CAN波特率计算器工具来计算得到(下载地址:CAN波特率计算器下载):

【4】CAN初始化配置(其中,波特率配置为1M,滤波器配置标准帧ID为1

/**************************************************************************
* 函数名称: COM_Cfg
* 功能描述: CAN通信初始化配置
**************************************************************************/
void COM_Cfg(void)
{stc_can_init_config_t   stcCanInitCfg;stc_can_filter_t        stcFilter;Sysctrl_SetPeripheralGate(SysctrlPeripheralCan, TRUE);///<CAN 波特率配置COM_BaudCfg(&stcCanInitCfg, APB1_CLK, CAN_BAUD);    //48MHz主频,1M波特率stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 16-1;stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 10;stcCanInitCfg.enCanRxBufAll  = CanRxNormal;stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;stcCanInitCfg.enCanSTBMode   = CanSTBFifoMode;CAN_Init(&stcCanInitCfg);///<CAN 滤波器配置stcFilter.enAcfFormat = CanAllFrames;stcFilter.enFilterSel = CanFilterSel1;stcFilter.u32CODE     = 0x00000001;stcFilter.u32MASK     = 0x1FFFFFFF;CAN_FilterConfig(&stcFilter, TRUE);CAN_IrqCmd(CanRxIrqEn, TRUE);EnableNvic(CAN_IRQn, IrqLevel0, TRUE);
}

【5】CAN中断服务子程序(用于CAN接收)

stc_can_rxframe_t       stcRxFrame;
stc_can_txframe_t       stcTxFrame;
uint8_t                 u8RxFlag = FALSE;/**************************************************************************
* 函数名称: Can_IRQHandler
* 功能描述: CAN中断服务函数
**************************************************************************/
void Can_IRQHandler(void)
{if(TRUE == CAN_IrqFlgGet(CanRxIrqFlg)){CAN_IrqFlgClr(CanRxIrqFlg);CAN_IrqCmd(CanRxIrqEn, FALSE);CAN_Receive(&stcRxFrame);u8RxFlag = TRUE;}
}

【6】CAN发送接口(用于CAN发送)

/**************************************************************************
* 函数名称: COM_Tx
* 功能描述: CAN通信发送测试
**************************************************************************/
void COM_Tx(void)
{//中断接收,循环发送uint8_t u8Idx = 0;if(TRUE == u8RxFlag){u8RxFlag = FALSE;if(1 == stcRxFrame.Cst.Control_f.RTR){return;}//<<Can TxstcTxFrame.StdID         = stcRxFrame.StdID;stcTxFrame.Control_f.DLC = stcRxFrame.Cst.Control_f.DLC;stcTxFrame.Control_f.IDE = stcRxFrame.Cst.Control_f.IDE;stcTxFrame.Control_f.RTR = stcRxFrame.Cst.Control_f.RTR;for(u8Idx=0; u8Idx<stcRxFrame.Cst.Control_f.DLC; u8Idx++){stcTxFrame.Data[u8Idx] = stcRxFrame.Data[u8Idx];}CAN_SetFrame(&stcTxFrame);CAN_TransmitCmd(CanPTBTxCmd);CAN_IrqCmd(CanRxIrqEn, TRUE);}
}

【7】主函数调用

int32_t main(void)
{//系统时钟App_SysClkInit();//通信模块COM_Init();COM_Cfg();while(1){//通信COM_Tx();delay1ms(10);}
}

五 CAN通讯测试1(中断接收,Echo发送单帧)

        进行CAN测试的方法很多,如果没有USB-CAN通信转换工具/CAN协议分析工具,可以增加CAN外部回环或者内部回环的配置,配合Log串口输出或者仿真器Debug进行测试。我这边使用了USB-CAN通信转换工具(CAN-II)/CAN协议分析工具(CANTest)直接进行收发测试:

【1】选择 CANTest 中的对应设备 USBCAN2:

【2】匹配软件中的波特率为1M,确定并启动CAN:

【3】修改帧ID为1,点击发送,可以看到上位机发送数据到测试板,经由测试板返回相同长度及内容的数据

        以上配置及测试成功。

六 CAN通讯测试2(中断接收,发送多帧)

【1】发送多帧背景说明:

        实际应用中,往往需要收到一组请求之后,发送多组数据。尝试直接在 COM_Tx 函数中紧跟着第一帧数据发送之后再发一帧,有了如下操作:

        实测上述连续发送的方法是错误的,因为时间间隔太短,前一组通过主缓冲器(PTB)发送的数据还没有完成就又收到新的发送命令,导致后发送的命令失败

【2】同一个缓冲器连续发送多帧,中间加延时的方法:

        使用同一个主缓冲器(PTB)发送,中间增加1ms延时等待上一帧发送结束在我的系统上实测这个延迟的时间要大于500us,其他环境不绝对):

/**************************************************************************
* 函数名称: COM_Tx
* 功能描述: CAN通信发送测试
* 其他说明: 
**************************************************************************/
void COM_Tx(void)
{uint8_t u8Idx = 0;if(TRUE == u8RxFlag){u8RxFlag = FALSE;if(1 == stcRxFrame.Cst.Control_f.RTR){return;}//<<主缓冲器Can Tx第一帧stcTxFrame.StdID         = 0;stcTxFrame.Control_f.DLC = 8;stcTxFrame.Control_f.IDE = 0;stcTxFrame.Control_f.RTR = 0;stcTxFrame.TBUF32_2[0] = 0;stcTxFrame.TBUF32_2[1] = 1;CAN_SetFrame(&stcTxFrame);CAN_TransmitCmd(CanPTBTxCmd);   //PTB发送命令delay1ms(1);    //若使用单一缓冲器,连续发送失败,需要中间加延时等待上一帧发送结束(实测大于500us)stcTxFrame.StdID         = 1;stcTxFrame.Control_f.DLC = 8;stcTxFrame.Control_f.IDE = 0;stcTxFrame.Control_f.RTR = 0;stcTxFrame.TBUF32_2[0] = 2;stcTxFrame.TBUF32_2[1] = 3;CAN_SetFrame(&stcTxFrame);CAN_TransmitCmd(CanPTBTxCmd);   //PTB发送命令CAN_IrqCmd(CanRxIrqEn, TRUE);}
}

        测试结果如下:  

【3】使用不同缓冲器发送多帧的方法:

        除了上述同一个缓冲器加延时以实现连续发送多帧数据之外,还可以依赖MCU CAN外设提供的另外几组缓冲器实现连续发送多帧数据的目的(更可靠)

        由芯片说明书可以看到,主缓冲器(PTB)只能缓冲一帧数据。而另外的副缓冲器(STB)可以缓冲4帧数据。实现代码如下(收到信号之后,一次发送5帧数据,其中第一帧挂载主缓冲器PTB上,其他四帧挂载副缓冲器STB上):

/**************************************************************************
* 函数名称: COM_Tx
* 功能描述: CAN通信发送测试
* 其他说明: 
**************************************************************************/
void COM_Tx(void)
{uint8_t u8Idx = 0;if(TRUE == u8RxFlag){u8RxFlag = FALSE;if(1 == stcRxFrame.Cst.Control_f.RTR){return;}//<<主缓冲器Can Tx第一帧stcTxFrame.StdID         = 0;stcTxFrame.Control_f.DLC = 8;stcTxFrame.Control_f.IDE = 0;stcTxFrame.Control_f.RTR = 0;stcTxFrame.TBUF32_2[0] = 0;stcTxFrame.TBUF32_2[1] = 1;CAN_SetFrame(&stcTxFrame);CAN_TransmitCmd(CanPTBTxCmd);   //PTB发送命令//        delay1ms(1);    //若使用单一缓冲器,连续发送失败,需要中间加延时等待上一帧发送结束(实测大于500us)//<<副缓冲器Can Tx第二帧stcTxFrame.StdID         = 1;stcTxFrame.Control_f.DLC = 8;stcTxFrame.Control_f.IDE = 0;stcTxFrame.Control_f.RTR = 0;stcTxFrame.enBufferSel   = CanSTBSel;stcTxFrame.TBUF32_2[0] = 2;stcTxFrame.TBUF32_2[1] = 3;CAN_SetFrame(&stcTxFrame);//<<副缓冲器Can Tx第三帧stcTxFrame.StdID         = 2;stcTxFrame.Control_f.DLC = 8;stcTxFrame.Control_f.IDE = 0;stcTxFrame.Control_f.RTR = 0;stcTxFrame.enBufferSel   = CanSTBSel;stcTxFrame.TBUF32_2[0] = 4;stcTxFrame.TBUF32_2[1] = 5;CAN_SetFrame(&stcTxFrame);//<<副缓冲器Can Tx第四帧stcTxFrame.StdID         = 3;stcTxFrame.Control_f.DLC = 8;stcTxFrame.Control_f.IDE = 0;stcTxFrame.Control_f.RTR = 0;stcTxFrame.enBufferSel   = CanSTBSel;stcTxFrame.TBUF32_2[0] = 6;stcTxFrame.TBUF32_2[1] = 7;CAN_SetFrame(&stcTxFrame);//<<副缓冲器Can Tx第五帧stcTxFrame.StdID         = 4;stcTxFrame.Control_f.DLC = 8;stcTxFrame.Control_f.IDE = 0;stcTxFrame.Control_f.RTR = 0;stcTxFrame.enBufferSel   = CanSTBSel;stcTxFrame.TBUF32_2[0] = 8;stcTxFrame.TBUF32_2[1] = 9;CAN_SetFrame(&stcTxFrame);CAN_TransmitCmd(CanSTBTxAllCmd);    //STB所有帧发送命令CAN_IrqCmd(CanRxIrqEn, TRUE);}
}

        测试结果如下:

        综上,CAN通信收发测试完成。

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

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

相关文章

HTML基础知识——URL、文本标签、链接标签、图片标签、列表标签

目录 URL&#xff08;统一资源定位符&#xff09; 概述 网址的组成部分 协议 主机 端口 路径 查询参数 锚点 文本标签 示例&#xff1a; 链接标签 示例&#xff1a; 图片标签 示例&#xff1a; 列表标签 示例&#xff1a; URL&#xff08;统一资源定位符&#xff09;…

Go 中的 OOP - 多态性

Go 中的多态性是通过接口实现的。正如我们已经讨论过的&#xff0c;接口在 Go 中是隐式实现的。如果类型为接口中声明的所有方法提供定义&#xff0c;则该类型实现了接口。让我们看看 Go 中如何借助接口实现多态性。 使用接口的多态性 任何为接口的所有方法提供定义的类型都被…

玩转AIGC:如何选择最佳的Prompt提示词?

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

面试经典150题——Day30

文章目录 一、题目二、题解 一、题目 209. Minimum Size Subarray Sum Given an array of positive integers nums and a positive integer target, return the minimal length of a subarray whose sum is greater than or equal to target. If there is no such subarray, …

周赛369(位运算、分类讨论、记忆化搜索==>动态规划、树形DP)

文章目录 周赛369[2917. 找出数组中的 K-or 值](https://leetcode.cn/problems/find-the-k-or-of-an-array/)位运算模拟 [2918. 数组的最小相等和](https://leetcode.cn/problems/minimum-equal-sum-of-two-arrays-after-replacing-zeros/)分类讨论 [2919. 使数组变美的最小增量…

docker部署MySQL服务

部署 MySQL8.0.35社区版 1.下载镜像 docker pull container-registry.oracle.com/mysql/community-server:8.0.35 查看镜像 docker images 2. 启动MySQL服务器实例 docker run --namemysql8 --restart on-failure -p 3309:3306 -d container-registry.oracle.com/mysql/comm…

探索C++中的不变之美:const与构造函数的深度剖析

W...Y的主页&#x1f60a; 代码仓库分享&#x1f495; &#x1f354;前言&#xff1a; 关于C的博客中&#xff0c;我们已经了解了六个默认函数中的四个&#xff0c;分别是构造函数、析构函数、拷贝构造函数以及函数的重载。但是这些函数都是有返回值与参数的。提到参数与返回…

GPT的使用和反思

GPT的场景 GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一种基于Transformer结构的语言模型&#xff0c;它在自然语言处理领域有广泛的应用。一般情况下&#xff0c;以下几种情况会使用GPT&#xff1a; 文本生成&#xff1a;GPT可以生成自然流畅的文本&a…

零日漏洞预防

零日漏洞&#xff0c;是软件应用程序或操作系统&#xff08;OS&#xff09;中的意外安全漏洞&#xff0c;负责修复该漏洞的一方或供应商不知道该漏洞&#xff0c;它们仍然未被披露和修补&#xff0c;为攻击者留下了漏洞&#xff0c;而公众仍然没有意识到风险。 零日攻击是如何…

Unity中Shader的烘培分支的判断

文章目录 前言一、上一篇文章中所需要的 lightmapUV 只有在烘焙时才会使用1、查看帮助文档后&#xff0c;Unity中判断烘培是否开启&#xff0c;使用的是LIGHTMAP_ON2、我们在 appdata 和 v2f 中&#xff0c;定义第二套UV 前言 Unity中Shader的烘培分支的判断&#xff0c;基于上…

【Linux网络编程_TCP/UDP_字节序_套接字 实现: FTP 项目_局域网聊天项目 (已开源) 】.md updata:23/11/03

文章目录 TCP/UDP对比端口号作用字节序字节序转换api套接字 socket实现网络通讯服务端 逻辑思路demo&#xff1a; 满血版双方通讯/残血版多方通讯服务端 demo客户端 demo FTP 项目实现sever demo:client demo: 局域网多方通讯 配合线程实现sever demo:client demo: TCP/UDP对比…

Django使用APSchedule实现简单定时任务

一、环境依赖 系统&#xff1a;windows10 python: python3.9.0 djnago3.2.0 APScheduler3.10.1 二、django中的配置 1、创建utils包&#xff0c;在包里面创建schedulers包 utils/schedulers/task.py #1、设置 Django 环境&#xff0c;就可以导入项目的模型类这些了 imp…

JDBC数据库连接---附通用的CRUD类

文章目录 JDBC数据库连接1 导包2 编写配置文件3 编写连接数据库代码4 测试工具类5 附加1 通用的CRUD类2 测试CURD类3 测试 JDBC数据库连接 本篇文章以 MySQL 数据库为例&#xff0c;若要切换其他数据库&#xff0c;只需修改 resource文件夹中的 jdbc.properties 配置文件即可。…

解决mysql数据库root用户看不到库

第一种方式&#xff1a; 1.首先停止MySQL服务&#xff1a;service mysqld stop 2.加参数启动mysql&#xff1a;/usr/bin/mysqld_safe --skip-grant-tables & 然后就可以无任何限制的访问mysql了 3.root用户登陆系统&#xff1a;mysql -u root -p mysql 4.切换数据库&#…

【Flutter】Flutter 动画深入解析(1):掌握 AnimationController 的使用

【Flutter】Flutter 动画深入解析(1):掌握 AnimationController 的使用 文章目录 一、前言二、AnimationController 简介三、AnimationController 的主要功能四、Ticker 提供者五、AnimationController 的生命周期六、与 AnimationController 一起使用的 Future七、实际业务…

PS2024免费磨皮滤镜Portraiture插件下载

Portraiture 4是一款适用于LR的人像智能磨皮美化滤镜插件&#xff0c;操作简便、省去了选择蒙版和逐步像素处理的繁琐流程&#xff0c;帮助您实现高效的肖像修饰。快速对照片中皮肤、头发、眉毛等部位进行美化&#xff0c;无需手动调整&#xff0c;大大提高P图效率。全新4版本&…

C#线程学习,线程的创建,线程的暂停,线程的锁lock,Monitor,线程使用中的注意事项(一)

C#线程学习&#xff0c;线程的创建&#xff0c;线程的暂停&#xff0c;线程的锁lock,Monitor&#xff0c;线程使用中的注意事项&#xff08;一&#xff09; 八股文 线程和进程 进程是指程序的一次执行过程&#xff0c;而线程是指进程中执行的一条单一逻辑控制流。 进程是由多…

Redis ACL安全策略详解

一&#xff0c;redis新特性ACL安全策略介绍 在 Redis6 之前的版本&#xff0c;我们只能使用 requirepass 参数给 default 用户配置登录密码&#xff0c;同一个 redis 集群的所有开发都共享 default 用户&#xff0c;难免会出现误操作把别人的 key 删掉或者数据泄露的情况。 因此…

基于单片机的智能鱼缸控制系统的设计与实现

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录 概要 一、开发技术和原理的相关知识2.1开发设计目标2.2 开发设计使用技术和原理2.2.1嵌入式技术2.2.2传感器技术 二、基于单片机的智能鱼缸控制系统的总体设计3.1智能鱼缸控制系统的基本组成3.1.1系统的构成部分3.2需求…

高校动物实验室建设要点

高校动物实验室应按照合理的规划布局进行设计&#xff0c;以便满足实验教学和科学研究的需求。如区分功能区域。根据实验室的不同功能&#xff0c;划分出饲养区、实验区、准备区和储存区等功能区域。动物房应根据不同种类动物的需求进行布置&#xff0c;确保各种动物的饲养条件…