I2C系列(三):软件模拟I2C读写24C02

news2024/11/26 17:01:39

一.目标

        PC 端的串口调试软件通过 RS-485 与单片机通信,控制单片机利用软件模拟 I2C 总线对 EEPROM(24C02) 进行任意读写。 

二.硬件简述

2.1 24C02硬件参数

        24C02器件地址为0x50,存储容量为256字节,存储单元地址位数为8。地址发送方法如下图所示。

2.2 RS-485简述

        在工业控制领域,传输距离越长,要求抗干扰能力也越强。由于 RS-232 无法消除共模干扰,且传输距离只有 15m 左右,无法满足要求。
        工业标准组织提出了 RS-485 接口标准。 RS-485 标准采用差分信号传输方式,因此具有很强的抗共模干扰能力。 RS-485 接口芯片 SP485E 的封装及引脚说明如下图 1。

        RS-485 的逻辑电平为:

①当 A 的电位比 B 高 200mV 以上时, 为逻辑 1;

②当 B 的电位比 A 电位高200mA 以上时为逻辑 0,传输距离可达 1200m。由于是差分传输,因此无需公共地,在 RS-485 总线上仅需连接两根线 A 和 B。
       单片机与 RS-485 接口芯片的电路连接图如下图 2。

三.控制命令定义

        定义如下命令:

①c——串口接收数据函数初始化
②s——单片机将接收到的数据发送到串口调试终端显示,以确认单片机是否已正确接收数据
③w——将接收缓冲区 wbuf 中的数据写入 EEPROM 中
④r——将刚才写入 EEPROM 中的数据读出到缓冲区 rbuf 中,并发送到串口调试终端显示

四.C代码

        本代码注重功能实现,以期达到理解I2C协议和24C02读写方法的目的。实际项目还须考虑代码质量,如可读性、可维护性等。

4.1 I2C基础时序模拟

4.1.1 引脚初始化

void i2cinit(void)
{
	sdaout;/*引脚输出模式*/
	sclout;
	sda = 1; /*释放总线*/
	scl = 1;
}

4.1.2 延时函数

1.SCL 时序控制延时函数

        78K0指令的最短时钟周期为2个,一条NOP指令即为2个时钟周期,若使用内部8MHz时钟,则执行一条NOP指令需0.25us。

void delay(void)
{
	UCHAR i;
	for(i = 0;i < NOP_num;i++)
		NOP();
}

2.长延时函数

void delay_long(UINT a)
{
	UINT i,j;
	for(i = 0;i < a;i++)
	    for(j = 0;j < 100;j++);
}

4.1.3 起始信号模拟

        SCL 线为高电平期间, SDA 线由高电平向低电平的变化表示起始信号。

void i2cstart(void)
{
	sdaout;	
	sclout;
	/*1.初始化SDA为高电平:在SCL低电平期间拉高SDA*/
	scl = 0;
	delay();
	sda = 1;
	delay();
	
	/*2.模拟一个起始信号*/
	scl = 1;
	delay();
	sda = 0;
	delay();
}

4.1.4 停止信号模拟

        SCL 线为高电平期间, SDA 线由低电平向高电平的变化表示终止信号。

void i2cstop(void)
{
	sdaout;
	sclout;
	
	/*1.初始化SDA为低电平:在SCL低电平期间拉低SDA*/
	scl=0;
	delay();
	sda=0; 
	delay();
	
	/*2.模拟一个停止信号*/
	scl=1;
	delay();
	sda=1;
	delay();
} 

4.1.5 应答信号模拟

        每一个字节必须保证是 8 位长度。数据传送时,先传送最高位(MSB),每一个被传送的
字节后面都必须跟随一位应答位(即一帧共有 9 位)。

         在第 9 个时钟信号的高电平期间:若 SDA为 0,则为应答;若 SDA 为 1,则为非应答。

1.主机发送应答信号

void i2c_ack_write(UCHAR ack)
{
	sdaout;
	sclout;
	
	/*1.初始化SDA为应答信号/非应答电平:在SLC低电平期间改变SDA*/
	scl=0; /*sda 变化前,先将 scl 置 0,一个时钟周期的开始*/
	delay();
	if(ack == 1)
		sda = 1;/*1,不应答从机,通知从机释放 sda*/
	else 
		sda = 0;/*0,应答从机*/
	delay();
	
	/*2.scl 置高,通知从机读取SDA*/
	scl= 1;
	delay();
} 

2.读取从机的应答信号

UCHAR i2c_ack_read(void)
{
	UCHAR sack;
	sdaout;
	sclout;
	/*1.释放SDA,让从机控制:在SLC低电平期间拉高SDA*/
	scl=0;
	delay();
	sda=1;
	delay();
	sdain; /*sda 设置为输入模式,以检测从机的应答信号*/
	
	/*2.scl 置高,读取从机的应答信号*/
	scl=1
	delay();
	if(sda==1)
		sack=1;/*从机无应答*/
	else 
		sack=0;/*从机应答*/
	return sack; 
} 

4.1.6 写一个字节数据

        只是数据段传送的操作,即开始与应答之间的操作,但不包括开始和应答。

void writebyte(UCHAR dat)
{
	UCHAR temp=0;
	UCHAR i;
	sdaout;
	sclout;
	for(i = 0;i < 8;i++)
	{
		/*1.在SCL低电平时,准备好SDA*/
		temp = dat&0x80;
		scl = 0; 
		delay();
		if(temp == 0)
			sda = 0;
		else 
			sda = 1; 
		delay();
		
		/*2.拉高SCL,通知从机读SDA*/
		scl = 1;
		delay();
		
		dat = dat << 1;
	}
	
	/*3.释放SDA总线*/
	scl = 0;
	delay();
	sda = 1;
	delay();
}

4.1.7 读一个字节数据

        只是数据段传送的操作,即开始与应答之间的操作,但不包括开始和应答。

UCHAR readbyte(void)
{
	UCHAR i;
	UCHAR temp = 0;
	sdaout;
	sclout;
	/*1.主机释放SDA,并将SDA设为输入模式*/
	scl = 0;
	delay();
	sda = 1;
	delay();
	sdain; 
	
	for(i = 0;i < 8;i++)
	{
		/*1.拉低SCL,通知从机发送数据*/
		scl=0;
		delay();
		
		/*2.拉高SCL,读取SDA*/
		scl=1;
		delay();
		if(sda == 1)
			temp = (temp << 1) | 0x01;
		else
			temp = (temp << 1) | 0x00;
	}
	return temp;
}

4.2 I2C读写数据

4.2.1 向任意地址写单字节数据

        包括数据传送、应答信号(从机),但不包括开始和停止信号。

UCHAR writebyte_to_anyaddr(UCHAR dev_addr,UCHAR mem_addr,UCHAR dat)
{
	UCHAR sack;
	
	/*1.写器件地址*/
	writebyte((dev_addr << 1) | 0);	
	sack = i2c_ack_read(); 
	if(sack	==	1)
		return 1;
	
	/*2.写存储单元地址*/
	writebyte(mem_addr);
	sack = i2c_ack_read(); 
	if(sack == 1)
		return 1;
	
	/*3.发送数据*/
	writebyte(dat);	
	sack = i2c_ack_read();
	if(sack == 1)
		return 1;
	else
		return 0;
} 

4.2.2 从任意地址读单字节数据

        包括数据传送、应答信号,但不包括开始和停止信号。

UCHAR readbyte_from_anyaddr(UCHAR dev_addr,UCHAR mem_addr,UCHAR *data)
{
	UCHAR temp = 0;
	UCHAR sack = 0;
	
	/*1.写器件地址*/
	writebyte((dev_addr << 1) | 0);
	sack = i2c_ack_read();
	if(sack == 1)
		return 1;
	
	/*2.写存储单元地址*/
	writebyte(mem_addr);
	sack = i2c_ack_read();
	if(sack == 1)
		return 1;
	
	/*3.重置开始,改为读方向*/
	i2cstart();	
	writebyte((dev_addr << 1) | 1);
	sack = i2c_ack_read();
	if(sack==1)
		return 1;
	
	/*4.读数据*/
	readbyte(&temp);
	
	/*5.读完后,主机不应答,通知从机释放 sda*/
	i2c_ack_write(M_NACK); 
	
	*data = temp;
	return 0; 
} 

4.2.3 写n字节数据到任意地址

UCHAR writenbytes_to_anyaddr(UCHAR dev_addr,UCHAR mem_addr,const UCHAR* buf,UCHAR buflen)
{
	UCHAR i = 0;
	UCHAR sack = 0;
	i2cstart();
	writebyte_to_anyaddr(dev_addr,mem_addr,buf[i]);/*向指定地址写一个数据*/
	for(i = 1;i < buflen;i++)
	{
		/*页边界处理*/
		if(0x07 == (mem_addr & 0x07))/*地址的低 3 位为“111”时,主机须送下一页的起始地址*/
		{
			i2cstop(); /*到页边界时,主机须发停止信号,通知从机结束当前页的传送*/
			delay_long(1);/*结束信号与开始信号之间须延时*/
			i2cstart();/*开始*/
			writebyte((dev_addr << 1) | 0); /*送器件地址,写*/
			sack = i2c_ack_read(); /*检测从机应答*/
			if(sack == 1)
				return 1;/*无应答,返回 1*/
		
			writebyte(mem_addr + 1);/*写数据地址,地址值加 1*/
			sack=i2c_ack_read();/*检测从机应答*/
			if(sack == 1)
				return 1;/*无应答,返回 1*/
		}
		
		 /*页内写字节,地址自动加 1*/
		writebyte(buf[i]);
		sack=i2c_ack_read();
		if(sack == 1)
			return 1;
	
		mem_addr++;/*mem_addr 始终等于当前写入数据的地址,以便进行页边界判断*/
	}
	return 0; /*返回 0,写成功*/
} 

4.2.4 从任意地址读n字节数据

UCHAR readnbytes_from_anyaddr(UCHAR dev_addr,UCHAR mem_addr,UCHAR* buf,UCHAR buflen)
{
	UCHAR i=0;
	UCHAR sack;
	i2cstart();/*开始*/
	writebyte((dev_addr << 1) | 0);/*送器件地址,写*/
	sack=i2c_ack_read();/*检测从机应答*/
	if(sack==1)
		return 1;
	
	writebyte(mem_addr);/*送数据地址*/
	sack=i2c_ack_read();/*检测从机应答*/
	if(sack==1)
		return 1;
	
	i2cstart();/*开始*/
	writebyte((dev_addr << 1) | 1);/*送器件地址,读*/
	sack=i2c_ack_read();/*检测从机应答*/
	if(sack==1)
		return 1;
	
	for(i=0;i<buflen;i++)
	{
		buf[i]=readbyte(); /*读一字节数据到指定的缓冲区中*/
		if(i==(buflen-1))
			i2c_ack_write(M_NACK); /*读完后,主机不应答,通知从机释放 sda*/
		else
			i2c_ack_write(M_ACK); /*若未读完,主机应答,继续读*/
	}
	return 0;/*返回 0,读成功*/
}

4.3 串口中断服务函数

4.3.1 接收中断处理函数

__interrupt void MD_INTSR0(void)
{
	UCHAR err_type;
	UCHAR rx_data;
	err_type = ASIS0;
	rx_data = RXB0;
	P7=rx_data;
	if( err_type & 0x07 )
	{
		CALL_UART0_Error( err_type );
		return;
	}
	if(rx_data=='c') /*接收到 c 命令, flag 置 1*/
	{
		flag=1;
		return;
	}
	if(rx_data=='s') /*接收到 s 命令, flag 置 2*/
	{
		flag=2;
		return;
	}
	if(rx_data=='w') /*接收到 w 命令, flag 置 4*/
	{
		flag=4;
		return;
	}
	if(rx_data=='r')/*接收到 r 命令, flag 置 5*/
	{
		flag=5;
		return;
	}
	if(gUart0RxLen > gUart0RxCnt)/*正常接收数据,非命令*/
	{
		*gpUart0RxAddress = rx_data;
		gpUart0RxAddress++;
		gUart0RxCnt++;
	}
	else
		flag=3;/*接收缓冲区满, flag 置 3*/
} 

4.3.2 发送中断处理函数

__interrupt void MD_INTST0(void)/*发送中断处理函数*/
{
	if( gUart0TxCnt > 0 )
	{
		TXS0 = *gpUart0TxAddress;
		gpUart0TxAddress++;
		gUart0TxCnt--;
	}
	else /*发送完毕*/
	{
		P1.2=0;/*将 485 设置为接收模式*/
		SRMK0=0;/*开接收中断*/
	}
}

4.4 宏定义和声明

extern volatile USHORT gUart0RxCnt; /*接收数据统计*/
extern UCHAR flag;/*串口调试软件终端发送的命令标识*/

#define NOP_num 60/*延时函数中 NOP()指令的执行次数*/
#define scl P6.0 /*开漏输出引脚 P6.0 作为时钟引脚*/
#define sda P6.1 /*开漏输出引脚 P6.1 作为数据引脚*/
#define sclout PM6.0=0 /*时钟引脚输出模式*/
#define sdaout PM6.1=0 /*数据引脚输出模式*/
#define sclin PM6.0=1 /*时钟引脚输入模式*/
#define sdain PM6.1=1 /*数据引脚输入模式*/

#define DEV_ADDR 0x50 /*器件地址宏定义,输出*/

#define M_NACK 1 /*主机无应答常量定义*/
#define M_ACK 0 /*主机应答常量定义*/

void delay(void); /*SCL 时序控制延时函数*/
void delay_long(UINT a);/*长延时函数*/

void i2cinit(void);/*IIC 引脚初始化函数*/

void i2cstart(void);/*启动函数*/
void i2cstop(void);/*停止函数*/
void i2c_ack_write(UCHAR);/*主机应答处理函数*/
UCHAR i2c_ack_read(void);/*从机应答处理函数*/

void writebyte(UCHAR dat);/*写一个字节函数,只是数据段传送的操作,即开始与应答之间的操作,但不包括开始和应答*/
UCHAR readbyte(void);/*读一个字节函数,只是数据段传送的操作,即开始与应答之间的操作,但不包括开始和应答*/

UCHAR writebyte_to_anyaddr(UCHAR dev_addr,UCHAR mem_addr,UCHAR dat);/*向任意地址写一个数,包括开始信号、数据传送、应答信号(从机),但不包括停止信号*/
UCHAR readbyte_from_anyaddr(UCHAR dev_addr,UCHAR mem_addr);/*从任意地址中读一个数,包括开始信号和数据传送,但不包括应答信号(主机)和停止信号*/

UCHAR writenbytes_to_anyaddr(UCHAR dev_addr,UCHAR mem_addr,UCHAR* buf,UCHAR buflen);/*向任一地址开始的连续多个储存单元写一串数据*/
UCHAR readnbytes_from_anyaddr(UCHAR dev_addr,UCHAR mem_addr,UCHAR* buf,UCHAR buflen);/*从任一地址开始的连续多个储存单元读出一串数据*/

4.5 主处理函数main

void main( void )
{
	UCHAR wbuf[256]={0};/*待写到 EEPROM 中的数据缓冲区*/
	UCHAR rbuf[256]={0};/*从 EEPROM 中读出的数据缓冲区*/
	UCHAR wend[] = "write end!";/*写完成提示*/
	UCHAR temp=0;
	UCHAR i;
	UCHAR wnum=0;
	i2cinit();/*IIC 引脚初始化*/
	UART0_ReceiveData( wbuf,256);/*串口接收数据函数初始化*/
	P1.2=0;/*RS-485 使能引脚,设置为数据接收模式*/
	UART0_Start(); /*启动串口*/
	P7.0=0; /*程序运行 LED 指示*/
	while (1)
	{
		if(flag == 1)/*c 命令,串口接收数据函数初始化*/
		{
			UART0_ReceiveData( wbuf,256);
			flag=0;
		}
		if(flag == 2)/*s 命令,单片机将接收到的数据发送到串口调试终端显示*/
		{
			SRMK0=1;/*屏蔽接收中断*/
			P1.2=1; /*单片机设置为数据发送模式*/
			delay_long(1);
			flag=0;
			temp=(UCHAR)gUart0RxCnt;/*强制类型转换*/
			UART0_SendData(wbuf,temp);/*将接收的数据发送到串口调试终端*/
		}
		if(flag==3)/*接收缓冲区满,初始化串口接收函数,覆盖原来的数据*/
		{
			flag=0;
			UART0_ReceiveData( wbuf,256);
		}
		if(flag==4)/*w 命令,将 wbuf 中的数据写入 EEPROM 中*/
		{
			flag=0;
			DI();/*写过程,禁止中断*/
			temp=(UCHAR)gUart0RxCnt;
			writenbytes_to_anyaddr(DEV_ADDR,0,wbuf,temp);
			i2cstop();
			delay_long(2);
			i2cstart();
			writebyte_to_anyaddr(DEV_ADDR,250, temp);
			i2cstop();
			EI();/*开中断*/
			SRMK0=1;/*屏蔽接收中断*/
			P1.2=1; /*设置为发送模式*/
			UART0_SendData( wend,sizeof(wend));/*发送写结束字符串到串口调试终端显示*/
		}
		if(flag==5)/*r 命令,将刚才写入到 EEPROM 中的数据读出到 rbuf 中,并发送到串口调试终端显示*/
		{
			flag=0;
			DI();/*读过程中,禁止中断*/
			i2cstart();
			readbyte_from_anyaddr(DEV_ADDR,250,&wnum);
			i2cstop();
			delay_long(1);
			readnbytes_from_anyaddr(DEV_ADDR,0,rbuf,wnum); /*读数据*/
			i2cstop();
			EI();/*开中断*/
			SRMK0=1;
			P1.2=1;
			delay_long(1);
			UART0_SendData(rbuf,wnum);
		}
	}
}

五.测试结果

        发送 “1,2,3....18” 共 18 个数给单片机,让单片机以页写的方式写入 24C04 中。

        结果如下:
1) 若不进行页边界处理,则 17 和 18 两个数覆盖 01 和 02,即为页上卷,且说明页内字节数为
16字节。(如下图 )

2)进行页边界处理后,结果如下图 :
 

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

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

相关文章

Docker安装xxl-job并整合到SpringBoot项目

1. 创建数据库 执行如下SQL语句创建相关表 CREATE database if NOT EXISTS xxl_job default character set utf8mb4 collate utf8mb4_general_ci; use xxl_job;SET NAMES utf8mb4; CREATE TABLE xxl_job_info (id int(11) NOT NULL AUTO_INCREMENT,job_group int(11) NOT NUL…

YOLOV8逐步分解(2)_DetectionTrainer类初始化过程

接上篇文章yolov8逐步分解(1)--默认参数&超参配置文件加载继续讲解。 1. 默认配置文件加载完成后&#xff0c;创建对象trainer时&#xff0c;需要从默认配置中获取类DetectionTrainer初始化所需的参数args&#xff0c;如下所示 def train(cfgDEFAULT_CFG, use_pythonFalse…

Java基础语法(二)

前言 Hello&#xff0c;大家好&#xff01;很开心与你们在这里相遇&#xff0c;我是一个喜欢文字、喜欢有趣的灵魂、喜欢探索一切有趣事物的女孩&#xff0c;想与你们共同学习、探索关于IT的相关知识&#xff0c;希望我们可以一路陪伴~ 1. 类型转换 1.1 自动类型转换 什么是自…

政安晨:专栏目录【TensorFlow与Keras机器学习实战】

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 本篇是作者政安晨的专栏《TensorFlow与Keras机器…

AI新工具 小模型也有大智慧Qwen1.5-MoE;大模型动态排行榜;马斯克更新Grok-1.5

✨ 1: Qwen1.5-MoE 阿里巴巴一款小型 MoE 模型&#xff0c;只有 27 亿个激活参数&#xff0c;但性能与最先进的 7B 模型&#xff08;如 Mistral 7B 和 Qwen1.5-7B&#xff09;相匹配。 Qwen1.5-MoE是一个使用混合专家模型&#xff08;Mixture-of-Experts&#xff0c;MoE&…

H5实现3D旋转照片墙教程

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

从关键词到上下文:GPT 如何重新定义 SEO 策略

如何利用GPT技术革新SEO内容创建&#xff1f; 新的 SEO 格局 探索 SEO 的快速变化&#xff0c;重点关注从以关键字为中心的策略到更深入地了解用户意图和上下文的转变。 GPT 简介及其对内容创建、用户参与和搜索引擎优化 (SEO) 的革命性影响。 了解 GPT&#xff1a;技术范式转…

Stable Diffusion 模型下载:epiCPhotoGasm(真实、照片)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 该模型对照片是什么有很高的了解&#xff0c;所以…

Stable Diffusion之核心基础知识和网络结构解析

Stable Diffusion核心基础知识和网络结构解析 一. Stable Diffusion核心基础知识1.1 Stable Diffusion模型工作流程1. 文生图(txt2img)2. 图生图3. 图像优化模块 1.2 Stable Diffusion模型核心基础原理1. 扩散模型的基本原理2. 前向扩散过程详解3. 反向扩散过程详解4. 引入Late…

农学院智慧农业产教融合基地解决方案

第一章 背 景 1.1国际数字农业发展概况 随着全球信息化、智能化技术的快速发展&#xff0c;数字农业作为现代农业发展的重要方向&#xff0c;正日益受到国际社会的广泛关注。数字农业依托物联网、大数据、云计算、人工智能等现代信息技术&#xff0c;实现农业生产全过程的智能…

软件接口安全设计规范及审计要点

1.token授权安全设计 2.https传输加密 3.接口调用安全设计 4.日志审计里监控 5.开发测试环境隔离&#xff0c;脱敏处理 6.数据库运维监控审计 项目管理全套资料获取&#xff1a;软件开发全套资料_数字中台建设指南-CSDN博客

GRE、VPN实验报告

一、实验拓扑图 二、实验要求 1、按照图示配置IP地址 2、在R1和R3上配置默认路由使公网区域互通 3、在R1和R3上配置GRE VPN&#xff0c;使两端私网能够互相访问&#xff0c;Tunnel口IP地址如图 4、在R1和R3上配置RIPv2或者ospf或者静态&#xff0c;来传递两端私网路由 三、…

golang import引用项目下其他文件内函数

初始化项目 go mod init [module名字] go mod init project 项目结构 go mod 文件 代码 需要暴露给外界使用的变量/函数名必须大写 在main.go中引入&#xff0c;当前项目模块名/要引用的包名 package mainimport (// 这里的路径开头为项目go.mod中的module"project/…

OpenGL的MVP矩阵理解

OpenGL的MVP矩阵理解 右手坐标系 右手坐标系与左手坐标系都是三维笛卡尔坐标系&#xff0c;他们唯一的不同在于z轴的方向&#xff0c;如下图&#xff0c;左边是左手坐标系&#xff0c;右边是右手坐标系 OpenGL中一般用的是右手坐标系 1.模型坐标系&#xff08;Local Space&…

springboot项目中如何实现邮件告警功能(监控平台服务模拟)

介绍 模拟服务器故障&#xff0c;然后实现邮件告警 一、首先配置邮件的maven依赖 代码如下&#xff1a; <!--邮件告警--><!-- Spring Boot的邮件发送依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spri…

递归方法的理解

递归方法调用 &#xff1a;方法自己调用自己的现象就称为递归。 递归的分类 : 直接递归、间接递归。 直接递归&#xff1a;方法自身调用自己 public void methodA (){ methodA (); } 间接递归&#xff1a;可以理解为A()方法调用B()方法&#xff0c;B()方法调用C()方法&am…

3.Labview字符串与路径精讲(下) — 字符串及路径的用法汇总

本章讲解labview中的字符串和路径具体实践用例&#xff0c;从前面板字符串属性到后面板字符串函数应用做出详细概述&#xff0c;通过本文的学习希望大家了解到字符串及路径在labview编程中的重要地位。 本系列文章为labview 从基础到强化到精通的学习文章&#xff0c;大家可以随…

【linux】基础IO |文件操作符

需要掌握&#xff1a;操作文件&#xff0c;本质&#xff1a;进程操作文件。进程和文件的关系 向文件中写入&#xff0c;本质上向硬件中写入->用户没有权利直接写入->操作系统是硬件的管理者&#xff0c;我们可以通过操作系统往硬件写入->操作系统必须提供系统调用&…

Linux 学习之路--工具篇--yum

前面介绍了权限有关的内容&#xff0c;这里继续介绍有关Linux里面常用的工具之一yum 目录 一、简单介绍 <1> 源代码安装 <2>rpm 包安装 <3>yum / apt-get(ubuntu) 安装 二、简单使用 <1>安装包介绍 <2> yum 的基本指令 -- install <…

本地部署的stable diffusion 如何更新controlnet?

stable diffusion 未启动状态 点击“版本管理” 点击“扩展” 找到controlnet&#xff0c;点击右边的“更新”按钮 完成&#xff01;