单片机-89C51部分:11、IIC 、传感器温湿度
飞书文档https://x509p6c8to.feishu.cn/wiki/Cczpw4oBeiyK71kFhKfcXkQmnad
一、简介
IIC协议,又称I2C协议,是由PHILP公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备,IIC属于半双工同步通信方式。
C |
多主控(multimastering)
其中任何能够进行发送和接收的设备都可以成为主总线,一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
特征:简单性和有效性
两根线,在标准模式下,I2C总线的最大长度为5米,最大速率为100 kbit/s。在快速模式下,I2C总线的最大长度为1米,最大速率为400 kbit/s。在高速模式下,I2C总线的最大长度为0.4米,最大速率为3.4 Mbit/s。需要注意的是,总线长度的实际限制还取决于总线上的电容负载和电缆质量等因素。
二、构成
IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生,数据线是用来传输数据的,时钟线是用来使双方通信的时钟同步。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟钱SCL接到总线的SCL上,对于并联在一条总线上的每个IC都有唯一的地址。
主机与从机
主机(master),就是老板,上班时间、下班时间、都是他来决定的,指令都是他来发出来的,他要找谁干啥,谁就干啥,一般主机就是我们的单片机。
从机(Slave),就是员工,需要做什么听老板的,一般从机就是外围设备,例如温湿度传感器、EEPROM芯片、测距仪等等IIC子设备。
硬件IIC与软件IIC
硬件IIC:芯片里面把IIC的通讯协议通过电路实现了,有专用的IIC引脚,只需要配置下寄存器就能实现IIC通讯;
软件IIC:根据IIC通讯的时序协议,自己找两个引脚,按照IIC协议的时序实现。
51是不支持硬件IIC的,所以我们要驱动IIC设备,只能通过代码实现软件IIC,简单来说就是通过IO口模拟IIC的时序。
50kbit/s = 1s 50k周期 = 1周期 =1/50ks = 20us
通过IIC传输一个Byte数据的时序如下:
IIC完成的通讯过程如下:
IIC完整的通讯过程
- 1、总线是空闲状态,SCL=1,SDA =1;
- 2、要开始传输数据了,此时SCL还是高电平,SCL=1,主机将SDA从1变成0;
- 3、跟哪个从机通讯,把从机的地址发出去。一般地址是8个bit(也有16个bit的),这8个bit其实真实的地址是7个bit,最后1个bit是用来表示读或者写的。1表示读,0表示写;这个过程相当于主机往SDA上发了8个bit的数据(地址也是数据啊);
- 4、主机发地址的过程,相当于在找从机,从机是要给应答信号的,就是ACK,你老板喊你,你也得先回答声A吧;
- 5、应答之后,就是要传输数据了,如果第3步中发的地址是写操作,那就由主机来控制SDA的电平变化,如果第3步中发的地址是读操作,那就由从机来控制SDA的电平变化;
- 6、每次8bit的数据传输完成,都要有个应答信号,谁接收数据,谁来应答
- 7、完事之后,在SCL高电平时,主机把SDA从低电平拉高,表示结束。
10us延时函数
延时函数影响IIC速率
10us发送1bit,1ms=100bit 1s = 100kbit
void delay10us() //@11.0592MHz
{unsigned char i;i = 2;while (--i);
}
起始信号:
发送数据前要先发送起始信号,告知总线和从机开始通讯
-SCL为高时,SDA从高变低
#include <reg52.h>sbit sda = P0^1;
sbit scl = P0^2;void i2c_start()
{scl = 1;sda = 1;delay10us(); //起始信号建立时间,高电平时间持续大于4.7ussda = 0; //SDA拉低,下降沿delay10us(); //起始信号保持时间
}
结束信号:
发送完成需要发结束信号,告知总线和从机通讯完成
-SCL为高时,SDA从低变高
| |
void i2c_stop()
{scl = 1;sda = 0;delay10us(); //停止信号建立时间,SDA高电平时间持续大于4.7ussda = 1; //SDA拉高,上升沿delay10us(); //总线空闲时间保持
}
数据信号:
逐位发送数据或读取数据
0x20 = 0b0010 0000
发送1byte
1byte=8bit 发送1bit的流程是SCL拉低,SDA发送数据,维持一定时间,SCL拉高,维持一定时间,SCL拉低
单独实现:
void i2c_write_bit(unsigned char databit)
{scl = 0; //开始发送前,设置scl为0if(databit == 0) //设置需要发送的数据sda=0;elsesda=1;delay5us();scl=1; delay10us();scl=0;delay5us();
}void i2c_write_bit(unsigned char databit)
{scl = 0; //开始发送前,设置scl为0if(databit == 0) //设置需要发送的数据sda=0;elsesda=1;delay10us();scl=1; delay10us();scl=0;
}void i2c_write_byte(unsigned char datasend)
{for(i = 0; i < 8; i++){if(datasend & 0x80)i2c_write_bit(1);elsei2c_write_bit(0);datasend=datasend<<1;//左移一位,for循环8次,直到数据发送完}
}
合二为一:
void i2c_write_byte(unsigned char datasend)//发送数据
{unsigned char i;for(i = 0; i < 8; i++){scl = 0; //开始发送前,设置scl为0//判断最高位是1/0,是1设置sda输出高电平,是0设置sda输出低电平。if(datasend & 0x80)sda=1;elsesda=0;datasend=datasend<<1;//左移一位,for循环8次,直到数据发送完delay10us();scl=1;delay10us();scl=0;}
}
读取1byte
1byte=8bit 接收1bit的流程是SCL拉低,延时5us,拉高SCL延时10us,等待数据稳定,读取SDA的值,SCL拉低,延时5us
单独实现
unsigned char i2c_read_bit(){unsigned char databit = 0;scl=0; //每bit接收前,先设置scl为0delay5us();//scl为低电平的时间scl=1; //拉高scl开始接收数据delay10us();//等待数据稳定的时间if(sda)databit = 1;elsedatabit = 0;scl=0; delay5us();
}unsigned char i2c_read_bit(){unsigned char databit = 0;scl=0; //每bit接收前,先设置scl为0delay10us();//scl为低电平的时间scl=1; //拉高scl开始接收数据delay10us();//等待数据稳定的时间if(sda)databit = 1;elsedatabit = 0;return databit;
}unsigned char i2c_read_byte()//接收数据
{unsigned char value = 0;sda=1; //释放总线for(i=0;i<8;i++){if(i2c_read_bit())value = value|0x01;if(i < 7)value = value << 1;}scl=0; //接收完成后,设置scl为0delay10us();return value;
}
合二为一
unsigned char i2c_read_byte()//接收数据
{int i,value;sda=1; //释放总线for(i=0;i<8;i++){scl=0; //每bit接收前,先设置scl为0delay10us();//scl为低电平的时间scl=1; //拉高scl开始接收数据delay10us();//等待数据稳定的时间value=value<<1;if(sda){//每次向左移动一位以后,如果sda=1的时候就把最后一位置1,sda=0的时候则不用置,因为向左移动就有一个0了value=value|0x01;}}scl=0; //接收完成后,设置scl为0delay10us();return value;
}
应答信号:
完成数据发送后,通过读取应答信号判断从机是否收到数据
-应答信号:SCL从低到高再到低时,SDA都为低
-等待应答信号:SDA拉高(使得总线处于空闲状态),SCL从低到高时,检查SDA是否被拉低,如果被拉低,则获取到应答信号
0x55 - 0b0101 0101
| |
//发送应答信号
void i2c_ack()
{scl = 0;sda = 0; //SDA拉低,发出应答信号delay10us();scl = 1;delay10us();scl = 0;
}//等待应答信号
unsigned char i2c_wait_ack()
{unsigned char ucErr = 0;sda = 1; //sda为高电平释放总线,然后检测应答信号是否被拉低scl = 0; delay10us();scl = 1;delay10us();while(sda) //sda为高电平,就表示没有检查到ACK,{ucErr++;delay10us();if(ucErr > 250) //等一段时间,还没有ack,就停止总线{return 1;}}scl = 0;return 0;
}
上节课补充
void i2c_wirte_byte(unsigned char datasend)
改为
void i2c_write_byte(unsigned char datasend)void i2c_read_byte()
{unsigned char value = 0;unsigned char i = 0;sda = 0;for(i = 0;i < 8;i++){if(i2c_read_bit() == 1){value = value | 0x01;}else{value = value | 0x00;}if(i<7)value = value << 1;}scl = 0;Delay10us();
}
添加返回值,改为
unsigned char i2c_read_byte()
{unsigned char value = 0;unsigned char i = 0;sda = 0;for(i = 0;i < 8;i++){if(i2c_read_bit() == 1){value = value | 0x01;}else{value = value | 0x00;}if(i<7)value = value << 1;}scl = 0;Delay10us();return value;
}修改读取数据前,SDA释放为1
1、总线空闲状态,SCL=1,SDA =1;
unsigned char i2c_read_byte()
{unsigned char value = 0;unsigned char i = 0;sda = 1;for(i = 0;i < 8;i++){if(i2c_read_bit() == 1){value = value | 0x01;}else{value = value | 0x00;}if(i<7)value = value << 1;}scl = 0;Delay10us();return value;
}添加nack函数
void i2c_nack()
{scl = 0;sda = 1; //SDA拉高,发出非应答信号Delay10us();scl = 1;Delay10us();scl = 0;
}
三、温湿度传感器:CJ-GXHT3L
GXHT3L-DIS 是中科银河芯开发的新一代单芯片集成温湿度一 体传感器。
- ★ I2C 接口,通信速度高达 1MHz
- ★ 两个用户可选择的地址
- ★ GXHT3L 典型精度为±4%RH 和±0.5°C
- ★ GXHT30 典型精度为±3%RH 和±0.3°C
- ★ GXHT31 典型精度为±2%RH 和±0.3°C
- ★ 单芯片集成温湿传感器
- ★ 高可靠性和长期稳定性
- ★ 测量 0-100%范围相对湿度
- ★ 测量-45-130℃范围内温度
https://item.szlcsc.com/3199174.html
| | |
关于ADDR管脚说明:
这里要注意的是,0x44指的是I2C地址的高7位,第八位为读写标志位。
单次转换模式
| |
例如:设置高重复率,开启长转换持续时间,读取测量得到的温湿度数据
0x44 0b0100 0100 0b1000 1000
连续转换模式
1、设置转换模式
高重复率和周期转换频率,例如0x2130中,21代表每秒转换一次,30代表高重复率。
0x44 -> 0b0100 0100
100 01000 -》地址+写标志
100 01001 -》 地址+读标志
//注意:addr=0x44时,实际发送到总线的数据应该是0x44+读写标志位,0 为写,1 为读
#define GXHT3L_ADDR_WRITE 0x44<<1 //10001000
#define GXHT3L_ADDR_READ (0x44<<1)+1 //10001011//MSB和LSB设置为0x2130 初始化进入连续转换模式,高重复率,每秒测量一次
void gxht30_init(){i2c_start();i2c_write_byte(GXHT3L_ADDR_WRITE);i2c_wait_ack();i2c_write_byte(0x21);i2c_wait_ack();i2c_write_byte(0x30);i2c_wait_ack();i2c_stop();
}
2、进行数据读取
开始连续转换读取的命令0xE000
发送写标志+设备地址,发送开始连续指令(0xE000)
发送读标志+设备地址,等待SCL拉低,读取温湿度数据。
//周期测量模式读取数据命令
void gxht30_read_mode(){i2c_start();i2c_write_byte(GXHT3L_ADDR_WRITE);i2c_wait_ack();i2c_write_byte(0xE0);i2c_wait_ack();i2c_write_byte(0x00);i2c_wait_ack();i2c_stop();
}void gxht30_read(){int index = 0;unsigned char buffer[6];i2c_start();i2c_write_byte(GXHT3L_ADDR_READ);i2c_wait_ack();/*buffer[0]=i2c_read_byte(1);//温度高8位i2c_ack();buffer[1]=i2c_read_byte(1);//温度低8位i2c_ack();buffer[2]=i2c_read_byte(1);//CRCi2c_ack();buffer[3]=i2c_read_byte(1);//湿度高8位i2c_ack();buffer[4]=i2c_read_byte(1);//湿度低9位i2c_ack();buffer[5]=i2c_read_byte(0);//CRCi2c_nack();i2c_stop(); */for(index = 0;index < 6;index ++){buffer[index]=i2c_read_byte();if(index == 5)i2c_nack();elsei2c_ack();}i2c_stop();
}
3、温湿度转换
void gxht30_read(){int index = 0;unsigned char buffer[6];unsigned short tem=0,hum=0;float temperature = 0.0;float humidity = 0.0;i2c_start();i2c_write_byte(GXHT3L_ADDR_READ);i2c_wait_ack();for(index = 0;index < 6;index ++){buffer[index]=i2c_read_byte();if(index == 5)i2c_nack();elsei2c_ack();}i2c_stop();//合并高低字节 tem = ((buffer[0]<<8) | buffer[1]);hum = ((buffer[3]<<8) | buffer[4]);//进行温湿度转换temperature = (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)humidity = (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)
}
4、CRC8校验
即循环冗余校核,是一种根据网络数据包或电脑文件等数据产生简短固定位数校核码的快速算法,主要用来检测或校核数据传输或者保存后可能出现的错误。
#define POLYNOMIAL 0x31 // P(x) = x^8 + x^5 + x^4 + 1 = 00110001//CRC校验函数
unsigned char gxht30_crc8(unsigned char *crcdata, unsigned char nbrOfBytes)
{unsigned char Bit; // bit maskunsigned char crc = 0xFF; // calculated checksumunsigned char byteCtr; // byte counterfor(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++){crc ^= (crcdata[byteCtr]);for(Bit = 8; Bit > 0; --Bit){if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;else crc = (crc << 1);}}return crc;
}void gxht30_read(){int index = 0;unsigned char buffer[6];unsigned short tem=0,hum=0;float temperature = 0.0;float humidity = 0.0;i2c_start();i2c_write_byte(GXHT3L_ADDR_READ);i2c_wait_ack();for(index = 0;index < 6;index ++){buffer[index]=i2c_read_byte();if(index == 5)i2c_nack();elsei2c_ack();}i2c_stop();if(buffer[2]!=gxht30_crc8(buffer,2)) return; //CRC错误,直接退出,不进行转换if(buffer[5]!=gxht30_crc8(&buffer[3],2))return; //CRC错误,直接退出,不进行转换//合并高低字节 tem = ((buffer[0]<<8) | buffer[1]);hum = ((buffer[3]<<8) | buffer[4]);//进行温湿度转换temperature = (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)humidity = (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)printf("temperature = %f, humidity = %f\n", temperature, humidity);
}
5、串口打印温湿度
#include <stdio.h>
void uart_init(void) //9600bps@11.0592MHz
{PCON &= 0x7F; //波特率不倍速SCON = 0x50; //8位数据,可变波特率TMOD &= 0x0F; //清除定时器1模式位TMOD |= 0x20; //设定定时器1为8位自动重装方式TL1 = 0xFD; //设定定时初值TH1 = 0xFD; //设定定时器重装值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1
}/*
**重写printf调用的putchar函数,重定向到串口输出
**需要引入头文件<stdio.h>
*****/
char putchar(char dat){//输出重定向到串口SBUF = dat; //写入发送缓冲寄存器while(!TI); //等待发送完成,TI发送溢出标志位 置1TI = 0; //对溢出标志位清零return dat; //返回给函数的调用者printf
}
6、main函数实现
//带参延时函数
void delay_ms(unsigned int xms) //@12MHz
{unsigned int i, j;for(i=xms;i>0;i--){for(j=124;j>0;j--){}}
}void main()
{uart_init();gxht30_init();while(1){delay_ms(1000);gxht30_read_mode();gxht30_read();}
}
最终工程:
#include <reg52.h>
#include <stdio.h>sbit sda = P0^1;
sbit scl = P0^2;#define GXHT3L_ADDR_WRITE 0x44<<1 //0b0100 0100 -> 0b1000 1000
#define GXHT3L_ADDR_READ (0x44<<1)+1//0b0100 0100 -> 0b1000 1001void Delay10us() //@11.0592MHz
{unsigned char i;i = 2;while (--i);
}void i2c_start()
{scl = 1;sda = 1;Delay10us();sda = 0;
}void i2c_stop()
{scl = 1;sda = 0;Delay10us();sda = 1;
}void i2c_write_bit(unsigned char databit)
{scl = 0;if(databit == 1)sda = 1;elsesda = 0;Delay10us();scl = 1;Delay10us();
}void i2c_write_byte(unsigned char datasend)
{int i = 0;for(i = 0;i< 8;i++){if(datasend & 0x80){i2c_write_bit(1);}else{i2c_write_bit(0);}datasend = datasend << 1;}
}unsigned char i2c_read_bit()
{unsigned char databit = 0;scl = 0;Delay10us();scl = 1;Delay10us();if(sda == 1)databit = 1;elsedatabit = 0;return databit;
}unsigned char i2c_read_byte()
{unsigned char value = 0;unsigned char i = 0;sda = 1; //让总线处于空闲状态for(i = 0;i < 8;i++){if(i2c_read_bit() == 1){value = value | 0x01;}else{value = value | 0x00;}if(i<7)value = value << 1;}scl = 0;Delay10us();return value;
}void i2c_ack()
{scl = 0;sda = 0;Delay10us();scl = 1;Delay10us();scl = 0;
}void i2c_nack()
{scl = 0;sda = 1; //SDA拉高,发出非应答信号Delay10us();scl = 1;Delay10us();scl = 0;
}void i2c_wait_ack()
{unsigned char time = 0;scl = 0;sda = 1;Delay10us();scl = 1;Delay10us();while(sda){Delay10us();time ++;if(time > 100)break;}scl = 0;Delay10us();
}void gxht30_init()
{i2c_start();i2c_write_byte(GXHT3L_ADDR_WRITE);i2c_wait_ack();i2c_write_byte(0x22);i2c_wait_ack();i2c_write_byte(0x20);i2c_wait_ack();i2c_stop();
}void gxht30_read_mode()
{i2c_start();i2c_write_byte(GXHT3L_ADDR_WRITE);i2c_wait_ack();i2c_write_byte(0xE0);i2c_wait_ack();i2c_write_byte(0x00);i2c_wait_ack();i2c_stop();Delay10us();
}#define POLYNOMIAL 0x31 // P(x) = x^8 + x^5 + x^4 + 1 = 00110001//CRC校验函数
unsigned char gxht30_crc8(unsigned char *crcdata, unsigned char nbrOfBytes)
{unsigned char Bit; // bit maskunsigned char crc = 0xFF; // calculated checksumunsigned char byteCtr; // byte counterfor(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++){crc ^= (crcdata[byteCtr]);for(Bit = 8; Bit > 0; --Bit){if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;else crc = (crc << 1);}}return crc;
}void gxht30_read_data()
{unsigned short tem,hum;int index = 0;float temperature,humidity;unsigned char buffer[6];i2c_start();i2c_write_byte(GXHT3L_ADDR_READ);i2c_wait_ack();for(index = 0; index < 6;index ++){buffer[index] = i2c_read_byte();if(index == 5)i2c_nack();elsei2c_ack();}i2c_stop();if(gxht30_crc8(buffer,2) != buffer[2]){printf("crc error\n");return;}if(gxht30_crc8(&buffer[3],2) != buffer[5]){printf("crc error\n");return;}//合并两个8bit的数据为一个16bit的数据tem = (buffer[0] << 8) | buffer[1];hum = (buffer[3] << 8) | buffer[4];//进行温湿度转换temperature = (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)humidity = (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)printf("temperature=%f humidity=%f\n",temperature,humidity);
}void uart_init(void) //9600bps@11.0592MHz
{PCON &= 0x7F; //波特率不倍速SCON = 0x50; //8位数据,可变波特率TMOD &= 0x0F; //清除定时器1模式位TMOD |= 0x20; //设定定时器1为8位自动重装方式TL1 = 0xFD; //设定定时初值TH1 = 0xFD; //设定定时器重装值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1
}/*
**重写printf调用的putchar函数,重定向到串口输出
**需要引入头文件<stdio.h>
*****/
char putchar(char dat){//输出重定向到串口SBUF = dat; //写入发送缓冲寄存器while(!TI); //等待发送完成,TI发送溢出标志位 置1TI = 0; //对溢出标志位清零return dat; //返回给函数的调用者printf
}//带参延时函数
void delay_ms(unsigned int xms) //@12MHz
{unsigned int i, j;for(i=xms;i>0;i--){for(j=124;j>0;j--){}}
}void main()
{uart_init();gxht30_init();while(1){delay_ms(1000);gxht30_read_mode();gxht30_read_data();}
}
FYI:
有的细心的小伙伴,在做这个实验的时候发现,从传感器读取的数据会比实际环境温度高1~2度,这是因为这块彩色板卡设计时,为了美观做的牺牲。
因为我们板卡工作时,电源模块会有温升,所以温湿度传感设计时得在芯片周边挖空开槽,或者使用插件的方式,但我们实际上打样回来后,发现实在太丑了。
| | |
考虑到大家在学习过程中,主要学习I2C的驱动原理,所以就取消了这个设计。
相关文章:
单片机-89C51部分:11、IIC 、传感器温湿度
飞书文档https://x509p6c8to.feishu.cn/wiki/Cczpw4oBeiyK71kFhKfcXkQmnad 一、简介 IIC协议,又称I2C协议,是由PHILP公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备,IIC属于半双工同步通信方式。 C IIC是一种同…...
Java从入门到精通 - Java入门
Java 入门 此笔记参考黑马教程,仅学习使用,如有侵权,联系必删 文章目录 Java 入门01 Java快速入门1. Java 是什么?能干什么?1.1 Java 背景知识1.2 Java 能做什么?1.3 Java 技术体系 2. 如何使用 Java&…...
SLAM中的状态估计理论:从基础到前沿的完整解析
SLAM中的状态估计理论:从基础到前沿的完整解析 一、SLAM状态估计基础与问题建模 1.状态估计问题的数学描述 在SLAM(Simultaneous Localization and Mapping,同时定位与地图构建)中,状态估计问题的核心在…...
Android 自带的分享功能分享到三方应用
1. 分享视频到三方应用 var shareIntent Intent(Intent.ACTION_SEND)shareIntent.setType("video/*")shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(path))startActivity(Intent.createChooser(shareIntent, "")) 2. 分享音频到三方应用 var sha…...
宇树科技开启“人形机器人格斗盛宴”
2025年5月至6月,一场备受瞩目的全球性科技盛事——全球首届“人形机器人格斗大赛”将由杭州宇树科技隆重开启。赛事将带来前所未有的机器人格斗视觉冲击,吸引全球目光聚焦。 为打造顶级参赛队伍,宇树科技的技术精英团队已连续多周开展密集的算…...
K8S - 命名空间实战 - 从资源隔离到多环境管理
引言 在传统的物理机或虚拟机环境中,不同业务应用共享资源,容易导致权限冲突、资源争用和管理混乱。Kubernetes 通过 命名空间(Namespace)实现资源逻辑隔离,将集群划分为多个虚拟子集群,从而解决以下问题&…...
【安全扫描器原理】基于协议的服务扫描器
【安全扫描器原理】基于协议的服务扫描器 1.概述2.服务扫描的基本原理3.WWW服务扫描4.FTP服务扫描5.Telnet服务扫描1.概述 一台计算机逻辑上可以提供多项服务,每安装一个服务,即打开了一个或多个端口。从这个角度上看,每个服务对应一个或几个指定端口,反之,如果能检测到某…...
第十六届蓝桥杯 2025 C/C++组 数列差分
目录 题目: 题目描述: 题目链接: 思路: 核心算法: 思路详解: 代码: 代码详解: 题目: 题目描述: 题目链接: P12342 [蓝桥杯 2025 省 B/Py…...
模式识别的基本概念与理论体系
前面在讨论专家系统时曾经说过,为了使计算机具有自动获取知识的能力,除了应使它具有学习能力外,还应使它具有能识别诸如文字、图形、图象、声音等的能力,计算机的这种识别能力是模式识别研究的主要内容。当然,模式识别…...
机器学习,深度学习
定义(非正式):不进行明确编程的情况下,提供大量数据让计算机进行自我学习分类:监督(supervised)学习,无监督(unsupervised)学习监督学习:提供的数据中包含了问题到正确答案(x到y)的映射…...
smolagents - Guided tour
https://colab.research.google.com/github/huggingface/notebooks/blob/main/smolagents_doc/en/pytorch/guided_tour.ipynbhttps://colab.research.google.com/github/huggingface/notebooks/blob/main/smolagents_doc/en/pytorch/guided_tour.ipynb...
【keil使用】无法打开keil工程,只有空白界面的解决方法
【keil使用】无法打开keil工程,只有空白界面的解决方法 一、最常见的原因 在我们新建keil工程或下载其他大佬的keil工程的时候可能会出现工程无法正常打开的情况,如图所示: 其中最常见的一个原因就是keil工程的目录路径太长了,W…...
openEuler 22.03 安装 Nginx,支持离线安装
目录 一、环境检查1.1 必要环境检查1.2 在线安装(有网络)1.3 离线安装(无网络) 二、下载Nginx2.1 在线下载2.2 离线下载 三、安装Nginx四、开机自启服务五、开放防火墙端口六、常用命令 一、环境检查 1.1 必要环境检查 # 查看 g…...
Excel 数组功能及应用示例
Excel表格中的数组(Array)是一个可以同时存储和操作多个数据的结构。数组可以是单行、单列(一维数组)或多行多列(二维数组)。在Excel中,数组公式或动态数组功能可以一次性处理多个值,…...
C++后端服务器开发:侵入式与非侵入式程序结构解析
在C后端服务器开发中,架构设计是决定系统性能、可扩展性和可维护性的关键因素之一。尽管不同的业务需求会导致服务器架构的多样化,但网络通信模块作为所有服务的通用部分,为我们提供了一个抽象和讨论的基础。基于此,我们可以将服务…...
「Mac畅玩AIGC与多模态09」开发篇05 - 使用自定义天气查询插件开发智能体应用
一、概述 本篇介绍如何在 macOS 环境下,通过编写自定义 OpenAPI Schema,将天气查询服务接入 Dify 平台,并开发基于实时天气信息的智能体应用。本案例培养路径参数与查询参数结合的插件开发技巧,实现智能体和外部实时数据的动态联动。 二、环境准备 1. 确认本地开发环境 …...
Maven插件学习(五)—— 将项目构建生成的 OSGi Bundles(或 Features)发布到一个 P2 仓库
发布OSGi Bundles到一个 P2 仓库 读取项目中properties文件中的属性 <plugin><groupId>org.codehaus.mojo</groupId><artifactId>properties-maven-plugin</artifactId><version>1.0-alpha-2</version><executions><exec…...
欧拉计划 Project Euler61(循环的多边形数)题解
欧拉计划 Project Euler 61 题解 题干思路code 题干 思路 先生成所有四位数的多边形数集合分类保存,然后dfs找即可 code // 2512 1281 8128 2882 8256 5625 // 28684 #include <bits/stdc.h>using namespace std;using ll long long;typedef vector<i…...
C语言与Unix的传奇起源
C语言与Unix的传奇起源 背景:Multics项目的困境 这段历史要从20世纪60年代中叶的美国说起。当时,三大技术巨头——麻省理工学院(MIT)、AT&T贝尔实验室和通用电气(GE)——联手为GE-645大型机开发一个名…...
C#扩展方法与Lambda表达式基本用法
C# 扩展方法与 Lambda 表达式详解 一、扩展方法详解 1. 基本概念 扩展方法允许为现有类型"添加"方法,而无需修改原始类型或创建派生类型。 定义条件: 必须在静态类中定义方法本身必须是静态的第一个参数使用this修饰符指…...
C#规避内存泄漏的编码方法
C#规避内存泄漏的编码方法 内存泄漏是C#开发中常见的问题,尽管.NET有垃圾回收机制(GC),但不当的编码实践仍可能导致内存无法被及时回收。以下是系统性的规避内存泄漏的方法: 一、理解内存泄漏的常见原因 未释放的事件订阅静态…...
ARM 指令集(ubuntu环境学习) 第一章:ARM 指令集概述
1.1 ARM 架构简介 ARM(Advanced RISC Machine)是一种精简指令集计算机(RISC)架构,最初由英国的 ARM Holdings 公司设计。与复杂指令集计算机(CISC)不同,RISC 架构通过使用简单且高效的指令集,使得处理器能够以更高的速度和更低的功耗执行任务。ARM 架构被广泛应用于各…...
OpenCV实战教程:从零开始的计算机视觉之旅
第一部分:基础入门 OpenCV简介 什么是OpenCV及其应用领域开发环境搭建(Windows/MacOS/Linux)安装配置和第一个程序"Hello OpenCV" 图像基础 图像的数字表示方式色彩空间(RGB、HSV、灰度图)图像读取、显示与…...
零基础做自动驾驶集成测试(仿真)
图 1:使用 GPUDrive 进行极快的多代理模拟。上图:GPUDrive 中 Waymo Open Motion Dataset 场景的鸟瞰图,方框表示受控智能体,圆圈表示其目标。底部:相应的代理视图,以一个代理为中心。可以根据用户的目标轻…...
阿里云dns服务器不可用怎么办?dns可以随便改吗?
阿里云DNS服务器不可用怎么办?dns可以随便改吗? 当DNS服务器不可用时,可能导致无法访问网站或网络服务。以下是常见的解决方法: 1. 检查网络连接 确保设备已连接到互联网(如Wi-Fi或有线网络)。 尝试访问其他网站或服务&#x…...
神经网络用于地震数据时空均匀插值的方法与开源资料
神经网络用于地震数据时空均匀插值的方法与开源资料 地震数据的不均匀采样是一个常见问题,神经网络提供了一种有效的解决方案。以下是关于如何使用神经网络进行地震数据时空均匀插值的概述和可用资源。 主要方法 1. 基于深度学习的插值方法 卷积神经网络(CNN)&a…...
线性微分方程与非线性微分方程
方程一 d x d t x \frac{dx}{dt} x dtdxx 这是一个一阶线性常微分方程,可以直接分离变量求解。 将变量分离: d x x d t \frac{dx}{x} dt xdxdt 两边积分: ∫ 1 x d x ∫ 1 d t ⇒ ln ∣ x ∣ t C \int \frac{1}{x} \, dx \…...
Windows查看和修改IP,IP互相ping通
Windows系统 查看IP地址 winr 输入cmd 打开终端使用 ipconfig 或 ipconfig -all 命令查看当前网络 IPV4地址 Windows系统 修改IP地址 自动获取IP(DHCP): 打开 控制面板,点击 网络和Internet。点击 网络和共享中心。选择 更改适配…...
ESP32开发之freeRTOS的信号量
什么是信号量信号量能干啥信号量的函数实例举例总结什么是信号量 简而言之,就是发出通知,接收通知的任务获得通知后去干啥啥。通知有多有少。自定义通知数量的,叫计数型信号量;只有有无(即“0”,“1”)通知的,叫二进制信号量。 信号量能干啥 资源管理:控制多个任务对…...
CRMEB-PRO系统定时任务扩展开发指南
适用场景 当系统内置定时任务类型无法满足业务需求时,开发者可通过本教程快速掌握自定义定时任务的扩展方法。本指南以"定时检测服务"为例,演示完整开发流程。 我想添加一个定时任务 ,而这里没有我需要的,我怎么来添加 比如我想添加一个定时检…...
单片机不同通信方式的适用场景
一、串口通信 UART 通信双方约定好波特率,每次发送一个字节(8位数据) 这种通信方式一共有2根线,且互相独立不受影响。 串口通信的缺点 二、RS232和RS485 优点是能够远距离传输信号 RS232达到30m RS485达到1000m 同时RS485还具有一对多的功能 三、S…...
【神经网络与深度学习】探索全连接网络如何学习数据的复杂模式,提取高层次特征
引言 全连接网络(Fully Connected Network,FCN)是深度学习中的重要架构,广泛用于模式识别、分类和回归任务。其强大的特征提取能力使其能够自动学习输入数据中的复杂模式,并逐步形成高层次特征。这种能力主要依赖于参…...
股指期货贴水对对冲的影响大吗?
如果你持有股票,又担心股市下跌,可能会想到用股指期货来“对冲风险”——比如买入股票的同时,卖出股指期货合约。但如果股指期货处于贴水状态(期货价格低于现货价格),对冲效果会受影响吗? 一、…...
浙江大学 | DeepSeek系列公开课 | 当艺术遇见AI:科艺融合的前沿探索
今天要给大家分享一份由浙江大学出品的DeepSeek系列公开课第三季第一期,公开课的主题是当艺术遇见AI,科艺融合的新探索。本报告系统展示了浙江大学在艺术与人工智能融合领域的研究成果,涵盖古画修复流程、色彩复原技术、诗画融合模型、图像召…...
(Go Gin)Gin学习笔记(三)数据解析和绑定:结构体分析,包括JSON解析、form解析、URL解析,区分绑定的Bind方法
1. 数据解析和绑定 bind或bindXXX函数(后文中我们统一都叫bind函数)的作用就是将请求体中的参数值绑定到对应的结构体上,以方便后续业务逻辑的处理 1.1 JSON数据解析和绑定 客户端传参,后端接收并解析到结构体 package mainim…...
【JavaEE】网络原理之初识(1.0)
目录 编辑 局域网与广域网 IP地址和端口号 实现简单的服务器客户端交互 简单理解socket TCP和UDP的差别(初识) socket面对udp DatagramSocket API DatagramSocket 构造方法 DatagramSocket 方法: DatagramPacket API Data…...
Go与Cpp的本质区别
这个问题是我们经常听到的问题 常见的观点有 Go 与 C 的差异主要体现在设计哲学、内存管理、并发模型、语法特性及应用场景等方面,以下从多个维度进行详细对比: 一、内存管理机制 C:需手动管理内存(如 new/delete、智能…...
Vulkan 学习(16)---- 使用 VertexBuffer
Vertex Buffer 创建一个 VertexBuffer 存储 Vertex data,代替之前在 Shader 中使用固定顶点值的做法 Vertex Shader 修改 GLSL 的 VertexShader 如下: 注意这里指定了 input Vertex data 的 location 和 格式 #version 450 layout(location 0) in vec2 inPosit…...
论文阅读 2024 arxiv Comprehensive Assessment of Jailbreak Attacks Against LLMs
总目录 大模型安全相关研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 Comprehensive Assessment of Jailbreak Attacks Against LLMs https://arxiv.org/pdf/2402.05668 https://www.doubao.com/chat/4015423571416834 速览 这篇论文是关于大…...
SIFT特征点检测
刚看完了SIFT特征点检测的原理,阅读的是两篇csdn博客,一个全面和一个最全面,不得不说,你俩写的都很全面,这么用心奉献知识的博主是全人类的财富。 现在用我这张笨拙的嘴先说一下我理解的流程 首先先将图像扩大一倍&a…...
开源模型应用落地-qwen模型小试-Qwen3-8B-快速体验-pipeline方式(二)
一、前言 阿里云最新推出的 Qwen3-8B 大语言模型,作为国内首个集成“快思考”与“慢思考”能力的混合推理模型,凭借其 80 亿参数规模及 128K 超长上下文支持,正在重塑 AI 应用边界。该模型既可通过轻量化“快思考”实现低算力秒级响应,也能在复杂任务中激活深度推理模式,以…...
Python os.path.join()路径拼接异常
问题 在使用os.path.join()对两个路径进行拼接,如:/University/School/和/Department/Class/进行拼接,最终的结果为/Department/Class/,而/University/School/却不知所踪。 import osos.path.join(“/University/School/”, “/…...
Flink之DataStream
Apache Flink 的 DataStream API 是用于 处理无限(流)或有限(批)数据流的核心编程模型,适用于事件驱动、实时分析、ETL 等场景。相比 Flink Table API,DataStream API 提供了更强的灵活性和底层控制能力。 …...
WHAT - Tailwind CSS + Antd = MetisUI组件库
文章目录 Tailwind 和 Antd 组件库MetisUI 组件库 Tailwind 和 Antd 组件库 在 WHAT - Tailwind 样式方案(不写任何自定义样式) 中我们介绍了 Tailwind,至于 Antd 组件库,我们应该都耳熟能详,官网地址:htt…...
【LLM】MOE混合专家大模型综述(重要模块原理)
note 当前的 MoE 架构就是一个用显存换训练时长/推理延迟的架构MoE 目前的架构基本集中在于将原先 GPT 每层的 FFN 复制多份作为 n 个 expert,并增加一个 router,用来计算每个 token 对应到哪个 FFN(一般采用每个 token 固定指派 n 个 exper…...
量子机器学习中的GPU加速实践:基于CUDA Quantum的混合编程模型探索
引言:量子机器学习的新范式 在量子计算与经典机器学习交叉融合的前沿领域,量子机器学习(Quantum Machine Learning, QML)正经历着革命性突破。然而,随着量子比特规模的增长和算法复杂度的提升,传统计算架构…...
CentOS Linux 环境二进制方式安装 MySQL 5.7.32
文章目录 安装依赖包新建用户解压初始化配置文件启动服务登录MySQL修改密码停止数据库 安装依赖包 yum -y install libaio perl perl-devel libncurses* autoconf numactl新建用户 useradd mysql解压 tar xf mysql-5.7.32-linux-glibc2.12-x86_64.tar.gz mv mysql-5.7.32-l…...
数学:拉马努金如何想出计算圆周率的公式?
拉马努金(Srinivasa Ramanujan)提出的圆周率(π)计算公式,源于他对数学模式的超凡直觉、对无穷级数和模形式的深刻洞察,以及独特的非传统数学思维方式。尽管他的思考过程带有强烈的个人色彩,甚至…...
Java 未来技术栈:从云原生到 AI 融合的企业级技术演进路线
一、云原生架构:重构 Java 应用的运行范式 1.1 微服务架构的深度进化 Java 在微服务领域的实践正从 Spring Cloud 向服务网格(Service Mesh)演进。以 Istio 为代表的服务网格技术,通过 Sidecar 模式实现服务间通信的透明化管理&…...
mid360驱动安装以及联合相机标定
1 mid360 安装 1.1 安装 一定要使用 SDK2和 ROS2驱动(livox_ros_driver2) 先安装SDK2,再安装livox_ros_driver2 GitHub - Livox-SDK/Livox-SDK2: Drivers for receiving LiDAR data and controlling lidar, support Lidar HAP and Mid-360. GitHub - Livox-SDK/l…...