【硬件模块】SGP30气体传感器

news2024/12/22 22:35:06

SGP30

这是SGP30官方文档里开头的介绍,简单来说就是SGP30是一个数字多像素气体传感器,然后具有长期稳定性和低漂移。

这些我们都不用管,我们只需要知道SGP30是通过I2C来通信的,并且可以采集的数据有CO2和TVOC的含量。TVOC是“Total Volatile Organic Compounds”,意思是总挥发性有机化合物。

可以来看一下它的参数。

TVOC的输出范围是0~60000ppb,而CO2的范围是400~60000ppm。一开始没注意范围,我看CO2一直都在400以上还以为出了啥问题。

对了,在SGP30上电初始化之后会有一段时间输出的CO2固定是400,而TVOC固定是0,是正常现象,等一会就可以正常采集数据了,后面会再说

接下来是电气规格,这边要注意电压不能超过1.98V!!!跟我们平时常用的3.3V和5V不一样。直接使用SGP30需要进行电平转换。

不过我用的是模块,已经把电平转换芯片加上去了,供电3.3V~5V都是可以的。

除了电气规则,还有一个就是物理环境,但是大家一般都不会处于这么极端的环境吧。

工作温度在-40℃~85℃之间,湿度在10%95%之间。

然后是通信时间,可以看到SGP30支持的I2C最大速率是400K。

了解完上面的内容之后就可以开始研究如何和SGP30用I2C通信了。

SGP30的七位从机地址是0x58,因此从机地址+读的地址就是0xB1,从机地址+写的地址就是0xB0,我们也可以写成 ( 0x58<<1 | 0x01) 和 ( 0x58<<1 | 0x00)

通信的时序就是I2C的标准,不一样的是SGP30的指令分两个字节发送,也就是说我们发送一个命令需要发送两次。

并且SGP30发来的数据,每俩字节就跟一个CRC校验位。

CRC校验多项式是0x31,我们可以直接搜索CRC在线校验计算器帮我们计算。当然,我们也可以忽略掉,但是还是要接收。

接下来看看指令。

虽然不多,但是我们用到的更少,我们基本上只用俩命令,第一个是0x2003初始化,第二个是0x2008获取采集数据。

我们在一开始的发送0x2003初始化一下,等待12ms(文档里说的,但我们最好多延时一会儿)

然后我们就可以发送0x2008采集数据了,等待10ms(我们最好多等一会),会返回给我们6个byte的数据,其中前俩字节是CO2的数据,第三个是CO2数据的CRC校验码,第四五个字节是TVOC的数据,最后一个字节是TVOC的CRC校验码。

根据文档里说的,在初始化(0x2003)的15s内,我们获取采集数据(0x2008)收到的结果会是400和0。并且我们需要每秒发送一次0x2008就可以保证SGP30内部的补偿算法生效,采集的数据会更精确。

至此我们就知道应该如何使用SGP了,接下来我会贴出示例代码,结合代码和注释以及上文,相信大家就都可以将SGP30这个模块移植到各自的板子上了。

软件I2C使用SGP30(以GD32为例)

虽然我这边演示的是GD32(因为最近在用的板子是GD32),但是其他板子也是一样的流程,不一样的只是操作GPIO的方式不一样,自己修改一下即可。

另外有个小坑需要注意一下,我们STM32模拟I2C的时候GPIO配置的是推挽输出模式(没试过开漏),然后在弄GD32的时候一开始我也配置的是推挽,结果连ACK都没收到,排查了好久才发现需要将GD32的GPIO配置为开漏才可以进行软件模拟I2C。

#include "board.h"
#include <stdio.h>
#include "Z_UART.h"

#define SCL_Pin GPIO_PIN_8
#define SDA_Pin GPIO_PIN_9
#define IIC_PORT GPIOB
 
//下面Z_I2C开头的是软件I2C,不是使用SGP30的重点
void Z_I2C_Init(void){
    rcu_periph_clock_enable(RCU_GPIOB);
    
    gpio_mode_set(IIC_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP,SCL_Pin|SDA_Pin);
    gpio_output_options_set(IIC_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,SCL_Pin|SDA_Pin);
    
    gpio_bit_write(IIC_PORT,SCL_Pin,1);
    gpio_bit_write(IIC_PORT,SDA_Pin,1);
}
    
void Z_I2C_SetSCL(uint8_t signal){
    if(signal==1) gpio_bit_write(IIC_PORT,SCL_Pin,1);
    else gpio_bit_write(IIC_PORT,SCL_Pin,0);
    delay_us(5);
}
 
void Z_I2C_SetSDA(uint8_t signal){
    if(signal==1) gpio_bit_write(IIC_PORT,SDA_Pin,1);
    else gpio_bit_write(IIC_PORT,SDA_Pin,0);
    delay_us(5);
}
 
uint8_t Z_I2C_GetSDA(void){
    return gpio_input_bit_get(IIC_PORT,SDA_Pin);
}
 
void Z_I2C_Start(void){
    Z_I2C_SetSDA(1);
    Z_I2C_SetSCL(1);
    Z_I2C_SetSDA(0);
    Z_I2C_SetSCL(0);
}
 
void Z_I2C_End(){
    Z_I2C_SetSDA(0);
    Z_I2C_SetSCL(1);
    Z_I2C_SetSDA(1);
}
 
void Z_I2C_SendByte(uint8_t byte){
    Z_I2C_SetSCL(0);
    for(int i=0;i<8;++i){
        if((byte&0x80)==0) Z_I2C_SetSDA(0);
        else Z_I2C_SetSDA(1);
        byte<<=1;
        Z_I2C_SetSCL(1);
        Z_I2C_SetSCL(0);
    }
}
 
uint8_t Z_I2C_ReveiceByte(){
    uint8_t data=0x00;
    Z_I2C_SetSDA(1);
    for(int i=0;i<8;++i){
        Z_I2C_SetSCL(1);
        if(Z_I2C_GetSDA()==1) data|=(0x80>>i);
        Z_I2C_SetSCL(0);
    }
    return data;
}
 
void Z_I2C_SendACK(uint8_t ack){
    if(ack==0) Z_I2C_SetSDA(0);
    else Z_I2C_SetSDA(1);
    Z_I2C_SetSCL(1);
    Z_I2C_SetSCL(0);
}
 
uint8_t Z_I2C_ReveiceACK(){
    Z_I2C_SetSDA(1);
    Z_I2C_SetSCL(1);
    uint8_t ack=Z_I2C_GetSDA();
    Z_I2C_SetSCL(0);
    return ack;
}

//获取SGP30的数据并打印
void printfSGP30(void){
    Z_I2C_Start();                                          //I2C起始时序
    Z_I2C_SendByte(0x58<<1|0x00);                           //发送从机地址+写(0xB0)
    if(0 != Z_I2C_ReveiceACK()) printf("ACK error\r\n");    //接收ACK
    
    Z_I2C_SendByte(0x20);                                   //发送采集命令0x2008,需要分两次发送
    if(0 != Z_I2C_ReveiceACK()) printf("ACK error\r\n");
    Z_I2C_SendByte(0x08);
    if(0 != Z_I2C_ReveiceACK()) printf("ACK error\r\n");

    Z_I2C_End();                                            //结束I2C
    
    delay_ms(100);                                          //需要等待10ms,保险起见延时久一点
    
    uint16_t data[4] = {0};
    
    Z_I2C_Start();
    Z_I2C_SendByte(0x58<<1|0x01);                           //发送从机地址+读(0xB0)
    if(0 != Z_I2C_ReveiceACK()) printf("ACK error\r\n");    //接收ACK
        
    data[0] = Z_I2C_ReveiceByte();                          //接收CO2的高8位
    Z_I2C_SendACK(0);                                       //发送ACK
    data[1] = Z_I2C_ReveiceByte();                          //接收CO2的低八位
    Z_I2C_SendACK(0);
    
    printf("CRC is 0x%X\r\n",Z_I2C_ReveiceByte());          //获取并打印CO2的CRC,可以不处理,但是一定要读取
    Z_I2C_SendACK(0);
    
    data[2] = Z_I2C_ReveiceByte();                          //接收TVOC(16bit)
    Z_I2C_SendACK(0);
    data[3] = Z_I2C_ReveiceByte();
    Z_I2C_End();                                            //TVOC的CRC不接收了,直接结束I2C通信
    
    printf("%X\t%X\t%X\t%X\r\n",data[0],data[1],data[2],data[3]);               //打印一下原始数据
    printf("CO2 is %d,TVOC is %d\r\n",data[0]<<8|data[1],data[2]<<8|data[3]);   //打印一下CO2和TVOC
    
}

int main(void){
    board_init();
    //初始化串口,为了将结果打印到串口助手上,不懂怎么操作的小伙伴可以看看之前关于串口的文章
    Z_UART_Init();
    Z_I2C_Init();                                       //初始化软件I2C相关引脚
    
    Z_I2C_Start();                                      //I2C起始时序
    Z_I2C_SendByte(0xB0);                               //发送从机地址+写
    if(0 != Z_I2C_ReveiceACK()) printf("ACK error\r\n");
    
    Z_I2C_SendByte(0x20);                               //发送初始化命令0x2003
    if(0 != Z_I2C_ReveiceACK()) printf("ACK error\r\n");
    Z_I2C_SendByte(0x03);
    if(0 != Z_I2C_ReveiceACK()) printf("ACK error\r\n");

    Z_I2C_End();                                        //结束I2C
    delay_ms(100);                                      //初始化需要10ms,但我们还是延时久一点
    
    while (1){
        printfSGP30();
        delay_ms(1000);
    }
}


可以收到数据,并且前十几秒的数据固定是400和0是正常现象。

GD32硬件I2C

之前的文章讲了GD32的引脚IIC,那么我们也加上GD32引脚IIC的例子吧。没看过且感兴趣的小伙伴可以再回顾一下。

【GD32】08 - IIC(以SHT20为例)-CSDN博客文章浏览阅读550次,点赞26次,收藏14次。接下来是设置IIC通信的模式与地址,模式我们自然是选择I2C模式的,而地址可以选择7位或者是10位的(10位的参数截图没截上,因为卡在手册的下一页了),这个根据我们通信的模块的从机地址而定。今天来了解一下GD32中的硬件IIC,其实我个人是觉得软件IIC比较方便的,不过之前文章里用的都是软件IIC,今天就算是走出自己的舒适圈,我们来了解了解GD32中的硬件IIC。关于IIC以及本文中演示的SHT20,在之前的文章里都有,并且也不是本文的重点,因此这里就不介绍了,不了解且感兴趣的小伙伴可以去看看之前的文章。https://blog.csdn.net/m0_63235356/article/details/140020224?spm=1001.2014.3001.5501

#include "board.h"
#include <stdio.h>
#include "Z_UART.h"


//获取SGP30的数据并打印
void printfSGP30(void){

    i2c_start_on_bus(I2C0);                                     //I2C起始时序
    while(!i2c_flag_get(I2C0,I2C_FLAG_SBSEND) );
    
    i2c_master_addressing(I2C0,0xB0,I2C_TRANSMITTER);           //发送从机地址+写
    while(!i2c_flag_get(I2C0,I2C_FLAG_ADDSEND) );               //等待从机发送完毕之后得到回应(即从机地址正确)
    i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);
    
    i2c_data_transmit(I2C0,0x20);
    while(!i2c_flag_get(I2C0,I2C_FLAG_BTC) ); 
    i2c_data_transmit(I2C0,0x08);
    while(!i2c_flag_get(I2C0,I2C_FLAG_BTC) ); 

    i2c_stop_on_bus(I2C0);                                       //结束I2C
    
    delay_ms(100);                                              //需要等待10ms,保险起见延时久一点

    i2c_start_on_bus(I2C0);                                     //I2C起始时序
    while(!i2c_flag_get(I2C0,I2C_FLAG_SBSEND) );

    i2c_master_addressing(I2C0,0xB0,I2C_RECEIVER);              //发送从机地址+读
    while(!i2c_flag_get(I2C0,I2C_FLAG_ADDSEND) );               //等待从机发送完毕之后得到回应(即从机地址正确)
    i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);
        
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);   
       
    uint16_t data[4] = {0};

    while(!i2c_flag_get(I2C0,I2C_FLAG_RBNE) );          //等待接收缓冲区不为空
    data[0] = i2c_data_receive (I2C0); 
    
    while(!i2c_flag_get(I2C0,I2C_FLAG_RBNE) );          //等待接收缓冲区不为空
    data[1] = i2c_data_receive (I2C0); 
    
    while(!i2c_flag_get(I2C0,I2C_FLAG_RBNE) );          //等待接收缓冲区不为空
    uint8_t crc = i2c_data_receive (I2C0); 
    printf("CRC is %X\r\n",crc);
    
    while(!i2c_flag_get(I2C0,I2C_FLAG_RBNE) );          //等待接收缓冲区不为空
    data[2] = i2c_data_receive (I2C0); 
    
    i2c_ack_config(I2C0, I2C_ACK_DISABLE);
    
    while(!i2c_flag_get(I2C0,I2C_FLAG_RBNE) );          //等待接收缓冲区不为空
    data[3] = i2c_data_receive (I2C0); 
    
    i2c_stop_on_bus(I2C0); 
    
    printf("%X\t%X\t%X\t%X\r\n",data[0],data[1],data[2],data[3]);               //打印一下原始数据
    printf("CO2 is %d,TVOC is %d\r\n",data[0]<<8|data[1],data[2]<<8|data[3]);   //打印一下CO2和TVOC
    
}

int main(void){
    board_init();
    //初始化串口,为了将结果打印到串口助手上,不懂怎么操作的小伙伴可以看看之前关于串口的文章
    Z_UART_Init();
    //开启时钟
    rcu_periph_clock_enable(RCU_I2C0);
    rcu_periph_clock_enable(RCU_GPIOB);
    //初始化硬件IIC的引脚
    gpio_af_set(GPIOB, GPIO_AF_4,GPIO_PIN_8|GPIO_PIN_9);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8|GPIO_PIN_9);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_8|GPIO_PIN_9);
       
    i2c_deinit(I2C0);                                           //复位IIC0
    i2c_clock_config(I2C0, 100000, I2C_DTCY_2);                 //设置IIC速率为100k
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);                       //使能应答
    i2c_enable(I2C0);                                           //使能IIC
    

    i2c_start_on_bus(I2C0);                                     //I2C起始时序
    while(!i2c_flag_get(I2C0,I2C_FLAG_SBSEND) );

    i2c_master_addressing(I2C0,0xB0,I2C_TRANSMITTER);           //发送从机地址+写
    while(!i2c_flag_get(I2C0,I2C_FLAG_ADDSEND));                //等待从机发送完毕之后得到回应(即从机地址正确)
    i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);
   
    i2c_data_transmit(I2C0,0x20);
    while(!i2c_flag_get(I2C0,I2C_FLAG_BTC) ); 
    i2c_data_transmit(I2C0,0x03);
    while(!i2c_flag_get(I2C0,I2C_FLAG_BTC) ); 

    i2c_stop_on_bus(I2C0);                                      //结束I2C
    delay_ms(100);                                              //初始化需要10ms,但我们还是延时久一点
    
    while (1){
        printfSGP30();
        delay_ms(1000);
    }
}


ESP32硬件I2C

这边也提供一下ESP32硬件I2C的代码吧,ESP32的硬件I2C方便好多,一下子就调通了。

顺便一提,因为没找到实习,于是决定暑假开始录制ESP32(ESP-IDF)的视频了,可以的话可以把今年服务外包的项目(省赛都没进)的硬件部分当个练手项目分享出来(基于ESP32),还有时间的话可以再录制一下GD32的视频。

ESP32已经在录了,相信没过多久就可以和大家见面了。可以关注一下b站的同名账号,微信视频号也会一起发。

#include <stdio.h>
#include "driver/i2c.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

// 获取SGP30的数据并打印
void printfSGP30(void) {
    i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();

    i2c_master_start(cmd_handle);
    i2c_master_write_byte(cmd_handle, 0xB0, true);
    i2c_master_write_byte(cmd_handle, 0x20, true);
    i2c_master_write_byte(cmd_handle, 0x08, true);
    i2c_master_stop(cmd_handle);
    i2c_master_cmd_begin(I2C_NUM_0, cmd_handle, 100 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd_handle);

    vTaskDelay(100 / portTICK_PERIOD_MS);

    uint8_t data[6] = {0};

    cmd_handle = i2c_cmd_link_create();
    i2c_master_start(cmd_handle);
    i2c_master_write_byte(cmd_handle, 0xB1, true);
    i2c_master_read_byte(cmd_handle, &data[0], I2C_MASTER_ACK);
    i2c_master_read_byte(cmd_handle, &data[1], I2C_MASTER_ACK);
    i2c_master_read_byte(cmd_handle, &data[2], I2C_MASTER_ACK);
    i2c_master_read_byte(cmd_handle, &data[3], I2C_MASTER_ACK);
    i2c_master_read_byte(cmd_handle, &data[4], I2C_MASTER_ACK);
    i2c_master_read_byte(cmd_handle, &data[5], I2C_MASTER_ACK);
    i2c_master_stop(cmd_handle);
    i2c_master_cmd_begin(I2C_NUM_0, cmd_handle, 100 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd_handle);

    printf("CO2 is %d,TVOC is %d\r\n", (uint16_t)data[0] << 8 | data[1],
           (uint16_t)data[3] << 8 | data[4]);  // 打印一下CO2和TVOC
}

void app_main(void) {
    printf("hello world\r\n");
    i2c_config_t i2c_initer = {
        .clk_flags = 0,              // 选择默认时钟源
        .master.clk_speed = 100000,  // 指定速率为100Kbit,最大可以为400Kbit
        .mode = I2C_MODE_MASTER,  // 主机模式
        .scl_io_num = 7,          // 指定SCL的GPIO口
        .scl_pullup_en = true,    // SCL接上拉电阻
        .sda_io_num = 8,          // 指定SDA的GPIO口
        .sda_pullup_en = true,    // SDA接上拉电阻
    };
    if (i2c_param_config(I2C_NUM_0, &i2c_initer) == ESP_OK)
        printf("i2c parm config success\r\n");
    else
        printf("config fail\r\n");

    if (i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0) == ESP_OK)
        printf("i2c driver install success\r\n");
    else
        printf("driver fail\r\n");

    i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();

    i2c_master_start(cmd_handle);
    i2c_master_write_byte(cmd_handle, 0xB0, true);
    i2c_master_write_byte(cmd_handle, 0x20, true);
    i2c_master_write_byte(cmd_handle, 0x03, true);
    i2c_master_stop(cmd_handle);
    i2c_master_cmd_begin(I2C_NUM_0, cmd_handle, 100 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd_handle);

    while (1) {
        printfSGP30();
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

也可以正常打印出结果。 

文档原文包括译文,以及卖家发的资料我都打包好了,大家可以关注我的同名公众号“折途想要敲代码”,回复关键词“SGP30”即可免费下载啦。

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

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

相关文章

记一次android打包,因路由规则设置不合理而导致pom文件无法访问的错误

一、错误详情 FAILURE: Build failed with an exception.* What went wrong: Could not determine the dependencies of task :mediaplayer:compileReleaseAidl. > Could not resolve all task dependencies for configuration :mediaplayer:releaseCompileClasspath.> C…

编译原理必考大题:构造项目集规范族,构造LR(0)分析表

在学习项目集规范族的构造之前,要先知道什么是项目?什么是项目集的闭包运算? 文章目录 前置知识LR(0)项目项目集的闭包运算项目转换函数GO 构造项目集规范族解决方法 构造LR(0)分析表真题实战: 前置知识 LR(0)项目 项目就是规则加上’’ 例如一条规则,A→abc 它对应的项目就…

【C++】开源:命令行解析库CLI11配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍命令行解析库CLI11配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#x…

智能改写工具大比拼:5款免费工具帮你告别重复内容

写作人员在创作文章时&#xff0c;经常面临着展现知识深度和创新思维的双重挑战。 在此过程中难免会遇到内容重复或灵感不足的问题。但不必过于焦虑。文章智能改写工具可以成为你的得力助手&#xff0c;帮你克服大部分写作难题。 接下来&#xff0c;让我们一起探索那些备受推…

重生奇迹mu精灵之心怎么搭配

玩家可以通过召唤来召唤多种精灵之心&#xff0c;每种精灵之心增加的属性也不同。精灵之心的作用是为了提升各种各样的属性。我们可以通过召唤获得精灵之心&#xff0c;前面的解锁费用较低&#xff0c;而后面的解锁需要大量的金币来解锁。 召唤精灵之心后&#xff0c;我们可以…

ROS2 rosbag2记录仪

rosbag2类似于行车记录仪&#xff0c;录制一段话题数据&#xff0c;录制完成后可以多次发布出来进行测试和实验&#xff0c;也可以将话题数据分享给别人用于验证算法等。 1.启动talker服务 ros2 run demo_nodes_cpp talker 2.记录话题数据 chatter ros2 bag record /chatte…

STL的六大组件

一.总体概念 STL&#xff08;Standard Template Library&#xff0c;标准模板库&#xff09;是C标准库的一部分&#xff0c;提供了丰富且高效的数据结构和算法。STL主要由六大组件组成&#xff0c;它们是&#xff1a; 容器&#xff08;Containers&#xff09;&#xff1a;STL提…

AIGC文生图lora微调训练案例;SD-Train界面训练stable Diffusion lora模型

lora仓库&#xff08;1000多个lora微调模型分享&#xff09;&#xff1a; https://lorastudio.co/models 参考&#xff1a; https://huggingface.co/blog/lora https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image_lora.py http…

UMI 命令行手册

Translate to English 命令行手册&#xff1a; README_CLI.mdHTTP接口手册&#xff1a; README_HTTP.md 命令行手册 基础说明 命令行调用入口就是主程序 Umi-OCR.exe 。如果你使用的是备用启动器&#xff08;如UmiOCR-data/RUN_GUI.bat&#xff09;&#xff0c;可能无法使用…

【TS】TypeScript 原始数据类型深度解析

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 TypeScript 原始数据类型深度解析一、引言二、基础原始数据类型2.1 boolean2.2 …

推荐系统三十六式学习笔记:原理篇.MAB问题|16|简单却有效的Bandit算法

目录 推荐就是选择MAB问题Bandit算法1.汤普森采样算法2.UCB算法3.Epsilon贪婪算法4.效果对比 冷启动总结 推荐系统的使命就是建立用户和物品之间的连接。建立连接可以理解成;为用户匹配到最佳的物品&#xff1b;但也有另一个理解就是&#xff0c;在某个时间某个位置为用户选择最…

彩虹PLM系统:电子制造业的高效协同平台

彩虹PLM系统&#xff1a;电子制造业的高效协同平台 在当今竞争激烈的电子制造业中&#xff0c;企业亟需一种能够整合全生命周期数据、促进跨部门协同并提升生产效率的解决方案。彩虹PLM系统&#xff0c;作为产品生命周期管理的佼佼者&#xff0c;凭借其卓越的技术实力和丰富的行…

前端基础--Vue3

Vue3基础 VUE3和VUE2的区别 2020年9月18日&#xff0c;Vue.js发布版3.0版本&#xff0c;代号&#xff1a;One Piece 于 2022 年 2 月 7 日星期一成为新的默认版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。体积更小 Vue3.0 打包大小减少41%。 同时Vue3可以更好的支持T…

AI 影评生成

电影作为一种重要的艺术形式&#xff0c;承载着无穷的想象力和情感表达。它不仅是娱乐的载体&#xff0c;更是一面照亮人性、社会和历史的镜子。通过电影&#xff0c;观众可以体验不同的世界、感受各种情感&#xff0c;甚至找到共鸣和启发。在这个充满多样性和创意的电影世界中…

自养号测评:引领跨境电商新纪元的策略与实践

在跨境电商的浩瀚蓝海中&#xff0c;自养号测评如同一股不可忽视的潮流&#xff0c;正悄然重塑着行业的未来。这一策略通过精心培育海外买家账号&#xff0c;不仅有效规避了服务商测评的诸多风险&#xff0c;更成为众多卖家提升产品销量与口碑的黑科技运营武器。 核心科技&…

支付宝服务商支付,如何邀请商户入驻?

支付宝服务商支付&#xff1a;如何邀请商户入驻 一、支付宝服务商支付 支付宝服务商支付模式为商户带来了诸多优势。它能够整合多种支付方式&#xff0c;包括扫码支付、刷脸支付、线上支付等&#xff0c;满足不同消费者的支付习惯。同时&#xff0c;提供了强大的财务管理功能…

【MindSpore学习打卡】应用实践-计算机视觉-ShuffleNet图像分类:从理论到实践

在当今的深度学习领域&#xff0c;卷积神经网络&#xff08;CNN&#xff09;已经成为图像分类任务的主流方法。然而&#xff0c;随着网络深度和复杂度的增加&#xff0c;计算资源的消耗也显著增加&#xff0c;特别是在移动设备和嵌入式系统中&#xff0c;这种资源限制尤为突出。…

数据结构(JAVA)—代码题

01-数据结构—判断题 02-数据结构—选择题 03 数据结构—多选填空程序填空 ​ 01-顺序表的建立及遍历 import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; import java.util.Scanner;public class Main {public static void main(St…

有哪些好的 Stable Diffusion 提示词(Prompt)可以参考?

Docker 作图咒语生成器 docker-prompt-generator 是一个开源项目&#xff0c;可以利用模型反推出提示词&#xff0c;让你偷偷懒&#xff0c;无需琢磨怎么写prompt&#xff0c;只需要找一个差不多的模型反推一下&#xff0c;直接用就好了&#xff0c;支持支持 MidJourney、Stab…

《Linux开发笔记》C语言编译

C语言编译过程 编译过程主要分为四步&#xff1a;预处理、编译、汇编、链接 预处理&#xff1a;主要用于查找头文件、展开宏 编译&#xff1a;把.i文件编译成.s文件 汇编&#xff1a;把.s文件汇编为.o文件 链接&#xff1a;把多个.o文件链接成一个app 以上四个步骤主要由3个命…