ADBMS1818驱动程序解析

.H文件解析

#ifndef _ADBMS1818_
#define _ADBMS1818_
#include "M_SPI.h"        //引入SIP底层收发
#include "CRC_Pec15.h"    //引入计算crc的算法
#include "temperature.h"  //引入温度转换
#include "string.h"
/*注:目前版本0.0.1 仅支持一片1818,后续按需增加*/
#define WRCFGA  0x01   //写配置寄存器A
#define WRCFGB  0x24   //写配置寄存器B
#define RDCFGA  0x02   //读配置寄存器A
#define RDCFGB  0x26   //读配置寄存器B/*读取电压寄存器使用ADBMS181x_rdcv_reg*/
//也可使用下边的快速读取
#define RDCVA   0x04   //读取电压寄存器组A
#define RDCVB   0x06   //读取电压寄存器组B
#define RDCVC   0x08   //读取电压寄存器组C
#define RDCVD   0x0A   //读取电压寄存器组D
#define RDCVE   0x09   //读取电压寄存器组E
#define RDCVF   0x0B   //读取电压寄存器组F#define RDAUXA  0x0C   //读取辅助寄存器A
#define RDAUXB  0x0E   //读取辅助寄存器B
#define RDAUXC  0x0D   //读取辅助寄存器C
#define RDAUXD  0x0F   //读取辅助寄存器D#define RDSTATA 0x10   //读取状态寄存器A
#define RDSTATB 0x12   //读取状态寄存器B#define WRSCTRL 0x14   //写s控制寄存器组
#define RDSCTRL 0x16   //读s控制寄存器组//comm命令
#define WRCOMM  0x0721  // 写comm寄存器组
#define STCOMM  0x0723  // 启动IIC/SPI通讯
#define RDCOMM  0x0722  // 读取comm寄存器组
//IIC_CMD 寄存器内数据用
#define IW_Start  0x06  //开始
#define IW_Stop   0x01  //停止
#define IW_Null   0x00  //空
#define IW_Nsend  0x07  //不发送 释放总线并忽略之后的数据
#define IR_Start  0x06  //从主机开始
#define IR_Stop   0x01  //从主机停止
#define IR_LOW    0x00  //字节之间SDA为低电平
#define IR_High   0x07  //字节之间SDA为高电平#define FW_Ack    0x00  //主机写入ACK
#define FW_Nack   0x08  //主机写入NACK
#define FW_NaS    0x09  //主机写入NACK+停止
#define FR_MAck   0x00  //主机读取ACK
#define FR_SAck   0x07  //从机读取ACK
#define FR_SNAck  0x08  //从机读取NAck
#define FR_SAckS  0x01  //从机ACK+主机停止
#define FR_SNAckS 0x09  //从机NACK+主机停止#define BMS1818_GPIO1     0x0002   // 0x08
#define BMS1818_GPIO2     0x0004   // 0x08<<1
#define BMS1818_GPIO3     0x0008   // 0x08<<2
#define BMS1818_GPIO4   	0x0010	 // 0x08<<3
#define BMS1818_GPIO5  		0x0020   // 0x08<<4
#define BMS1818_GPIO6   	0x0040	 // 0x01
#define BMS1818_GPIO7   	0x0080	 // 0x01<<1
#define BMS1818_GPIO8   	0x0100	 // 0x01<<2
#define BMS1818_GPIO9  		0x0200   // 0x01<<3#define MD_422HZ_1KHZ   0
#define MD_27KHZ_14KHZ  1
#define MD_7KHZ_3KHZ    2
#define MD_26HZ_2KHZ    3/*CHG低三位有效*/
#define CHG_ALL            0x00      //GPIO1至GPIO5,第二基准电压,GPIO6至GPIO9
#define CHG_G1G6           0x01      //GPIO1、GPIO6
#define CHG_G2G7           0x02      //....
#define CHG_G3G8           0x03
#define CHG_G4G9           0x04
#define CHG_G5             0x05
#define CHG_VREF2          0x06/*CH低三位有效*/
#define CH_ALL             0x00      //所有电池
#define CH_V1_7_13         0x01      //电池 1 7 13
#define CH_V2_8_14         0x02      //....
#define CH_V3_9_15         0x03
#define CH_V4_10_16        0x04
#define CH_V5_11_17        0x05
#define CH_V6_12_18        0x06#define ADCVAX            0x046F   // 0100 0110 1111  //所有电池和GPIO1 GPIO2   (这俩是掩码不能直接使用)
#define ADAX              0x0460   // 0100 0110 0000  //GPIO ADC转换
#define ADCV              0x0260   // 0010 0110 0000  //启动对18节电池的转换
typedef struct{uint8_t CFGARx[8];uint8_t CFGBRx[8];uint16_t VREF2;//第二基准电压值uint8_t COMM[8];/*................*/
}ADBMS1818_Reg;//测试案例
void Bms1818_tset(void);
#endif

.c代码解析

#include "ADBMS1818.h"
ADBMS1818_Reg bms1818_Reg={0};
void BMS1818_Delay_us(uint16_t nus){uint8_t i;while(nus --){for(i =0;i<0x16;i++);}
}/*spi读写接口 读写长度可变
tx_Data[] 发送缓冲区指针
rx_data   接受缓冲区指针
rx_len    长度
*/
void spi_WR_byte(uint8_t tx_Data[],uint8_t *rx_data,uint8_t len){Mspi_RT_byte(tx_Data,rx_data,len);
}
/*
第二个spi读写接口 读写一个字节
data 发送的数据
返回同时读取的数据
*/
uint8_t spi_WR_byte2(uint8_t data){uint8_t re;Mspi_RT_byte(&data,&re,1);return re;
}
//计算crc校验码的接口
uint16_t pec15_calc(int len,uint8_t* data){return pec15(data,len);
}//extern void delay_1ms(uint32_t count);
/* 从IDlE状态唤醒isoSPI并进入READY状态*/
void wakeup_sleep_cmd(uint8_t chain_N)
{uint8_t cmd[2],status[2];cmd[0]=0xff;SET_SPI0_NSS_LOW;BMS1818_Delay_us(10);spi_WR_byte(cmd,status,1);if(chain_N>200)BMS1818_Delay_us(300*chain_N/1000);else	{BMS1818_Delay_us(80*chain_N);}SET_SPI0_NSS_HIGH;SET_SPI0_NSS_LOW;spi_WR_byte(cmd,status,1);BMS1818_Delay_us(10*chain_N);spi_WR_byte(cmd,status,1);BMS1818_Delay_us(10*chain_N);SET_SPI0_NSS_HIGH;			
}
/*传入原始数据,(注:只处理一个寄存器组也就是)将数据进行校验然后传入目标指针,如果校验失败返回0*/
uint8_t ADBMS1818_RC_Check(uint8_t* original,uint16_t* target){uint16_t CRC_code;CRC_code = pec15_calc(6,original);if(CRC_code!=(original[6]<<8|original[7]))return 0;for(int i=0;i<3;i++){target[i]=original[i*2]|(original[i*2+1]<<8);}return 1;
}
//===============================================================================================================
/* 菊花链中的IC数量写入命令并读取原始单元电压寄存器数据
reg 1: RDCVA2: RDCVB3: RDCVC4: RDCVD5: RDCVE6: RDCVF
total_ic 菊花链中IC的数量
data 放数据的数组
*/
void ADBMS181x_rdcv_reg(uint8_t reg, uint8_t total_ic, uint8_t *data){const uint8_t REG_LEN = 8; //Number of bytes in each ICs register + 2 bytes for the PECuint8_t cmd[40];uint16_t cmd_pec;//00 04 07 c2if (reg == 1)     //1: RDCVA{cmd[1] = 0x04;cmd[0] = 0x00;}else if (reg == 2) //2: RDCVB{cmd[1] = 0x06;cmd[0] = 0x00;}else if (reg == 3) //3: RDCVC{cmd[1] = 0x08;cmd[0] = 0x00;}else if (reg == 4) //4: RDCVD{cmd[1] = 0x0A;cmd[0] = 0x00;}else if (reg == 5) //5: RDCVE{cmd[1] = 0x09;cmd[0] = 0x00;}else if (reg == 6) //6: RDCVF{cmd[1] = 0x0B;cmd[0] = 0x00;}cmd_pec = pec15_calc(2, cmd);cmd[2] = (uint8_t)(cmd_pec >> 8);cmd[3] = (uint8_t)(cmd_pec);wakeup_sleep_cmd(total_ic);SET_SPI0_NSS_LOW;spi_WR_byte(cmd,data,4);memset(cmd, 0xff, 8);spi_WR_byte(cmd,data,REG_LEN*total_ic);SET_SPI0_NSS_HIGH;
}
/*
cmd 命令
wakeup 是否唤醒
*/
void ADBMS181x_write_cmd(uint16_t cmd,uint8_t wakeup){uint8_t Mcmd[8];uint8_t databuf[4];uint16_t cmd_pec;Mcmd[0]=(uint8_t)(cmd>>8);Mcmd[1]=(uint8_t)cmd;cmd_pec = pec15_calc(2, Mcmd);Mcmd[2] = (uint8_t)(cmd_pec >> 8);Mcmd[3] = (uint8_t)(cmd_pec);if(wakeup) wakeup_sleep_cmd(1);SET_SPI0_NSS_LOW;spi_WR_byte(Mcmd,databuf,4);SET_SPI0_NSS_HIGH;
}
/*读1818寄存器*/
void ADBMS181x_read_reg(uint16_t cmd,uint8_t *databuf,uint8_t wakeup){uint8_t Mcmd[8];uint16_t cmd_pec;Mcmd[0]=(uint8_t)(cmd>>8);Mcmd[1]=(uint8_t)cmd;cmd_pec = pec15_calc(2, Mcmd);Mcmd[2] = (uint8_t)(cmd_pec >> 8);Mcmd[3] = (uint8_t)(cmd_pec);if(wakeup) wakeup_sleep_cmd(1);SET_SPI0_NSS_LOW;spi_WR_byte(Mcmd,databuf,4);memset(Mcmd, 0xff, 8);spi_WR_byte(Mcmd,databuf,8);SET_SPI0_NSS_HIGH;
}
/*写1818寄存器*/
void ADBMS181x_write_reg(uint16_t cmd,uint8_t *databuf,uint8_t wakeup){uint8_t Mcmd[8+4];uint8_t buf[8];uint16_t cmd_pec;Mcmd[0]=(uint8_t)(cmd>>8);Mcmd[1]=(uint8_t)cmd;cmd_pec = pec15_calc(2, Mcmd);Mcmd[2] = (uint8_t)(cmd_pec >> 8);Mcmd[3] = (uint8_t)(cmd_pec);for(int i=0;i<6;i++){Mcmd[4+i] = databuf[i];//写入数据}cmd_pec = pec15_calc(6, &Mcmd[4]);Mcmd[10] = (uint8_t)(cmd_pec >> 8);Mcmd[11] = (uint8_t)(cmd_pec);if(wakeup) wakeup_sleep_cmd(1);SET_SPI0_NSS_LOW;spi_WR_byte(Mcmd,buf,4+8);SET_SPI0_NSS_HIGH;
}/*
转换所有电池和GPIO1 GPIO2 的电压 建议在7K赫兹延迟8ms后读取
MD   ADC模式
DCP  允许放电? 0不允许放电  1允许放电
*/
void ADBMS1818_ADCVAX(uint8_t MD,uint8_t DCP){uint16_t cmd=0;cmd|=(MD<<7);cmd|=(DCP<<4);cmd|=ADCVAX;ADBMS181x_write_cmd(cmd,1);
}
/*
转换GPIO_ADC 转换的项目根据CHG的值来确定
在7k赫兹的情况下
转换所有GPIO 需要3.9ms 建议等待 8ms以上
转换两个GPIO 需要1ms   建议等待 2ms以上
*/
void ADBMS1818_ADAX(uint8_t MD,uint8_t CHG){uint16_t cmd=0;cmd|=CHG;cmd|=(MD<<7);cmd|=ADAX;ADBMS181x_write_cmd(cmd,1);
}
/*转换所有电池电压
在7Khz下需要 3ms 建议等待6ms以上
MD ADC模式
CHG */
void ADBMS1818_ADCV(uint8_t MD,uint8_t CH,uint8_t DCP){uint16_t cmd=0;cmd|=(DCP<<4);cmd|=(MD<<7);cmd|=(CH);	cmd|=ADCV;ADBMS181x_write_cmd(cmd,1);
}//读取18个电池电压
void ADBMS181x_read_18V(uint16_t *bufdata){uint8_t Mcmd[8];ADBMS1818_ADCV(MD_7KHZ_3KHZ,CH_ALL,0);BMS1818_Delay_us(10000);ADBMS181x_read_reg(RDCVA,Mcmd,1);ADBMS1818_RC_Check(Mcmd,bufdata);ADBMS181x_read_reg(RDCVB,Mcmd,0);ADBMS1818_RC_Check(Mcmd,bufdata+3);ADBMS181x_read_reg(RDCVC,Mcmd,0);ADBMS1818_RC_Check(Mcmd,bufdata+6);ADBMS181x_read_reg(RDCVD,Mcmd,0);ADBMS1818_RC_Check(Mcmd,bufdata+9);ADBMS181x_read_reg(RDCVE,Mcmd,0);ADBMS1818_RC_Check(Mcmd,bufdata+12);ADBMS181x_read_reg(RDCVF,Mcmd,0);ADBMS1818_RC_Check(Mcmd,bufdata+15);
}
//暂不支持多个位同时配置
uint8_t ADBMS181x_Config_GPIO(uint16_t gpio,uint8_t state){switch(gpio){case BMS1818_GPIO1: (state==1)? (bms1818_Reg.CFGARx[0]|=0x08):(bms1818_Reg.CFGARx[0]&=0xF7);break;case BMS1818_GPIO2: (state==1)? (bms1818_Reg.CFGARx[0]|=0x10):(bms1818_Reg.CFGARx[0]&=0xEF);break;case BMS1818_GPIO3: (state==1)? (bms1818_Reg.CFGARx[0]|=0x20):(bms1818_Reg.CFGARx[0]&=0xDF);break;case BMS1818_GPIO4: (state==1)? (bms1818_Reg.CFGARx[0]|=0x40):(bms1818_Reg.CFGARx[0]&=0xBF);break;case BMS1818_GPIO5: (state==1)? (bms1818_Reg.CFGARx[0]|=0x80):(bms1818_Reg.CFGARx[0]&=0x7F);break;case BMS1818_GPIO6: (state==1)? (bms1818_Reg.CFGBRx[0]|=0x01):(bms1818_Reg.CFGBRx[0]&=0xFE);break;case BMS1818_GPIO7: (state==1)? (bms1818_Reg.CFGBRx[0]|=0x02):(bms1818_Reg.CFGBRx[0]&=0xFD);break;case BMS1818_GPIO8: (state==1)? (bms1818_Reg.CFGBRx[0]|=0x04):(bms1818_Reg.CFGBRx[0]&=0xFB);break;case BMS1818_GPIO9: (state==1)? (bms1818_Reg.CFGBRx[0]|=0x08):(bms1818_Reg.CFGBRx[0]&=0xF7);break;default:return 0;}return 1;
}//读取16个温度
void ADBMS181x_read_16T(uint16_t *Tdata){//依次读取uint8_t bufdata[8]={0};//存接收的数据uint16_t Vdata[3]={0};//存校验后的数据//uint8_t i=0;for(uint8_t i=0;i<8;i++){//切译码器ADBMS181x_Config_GPIO(BMS1818_GPIO7,(i&0x04)? 1:0);ADBMS181x_Config_GPIO(BMS1818_GPIO6,(i&0x02)? 1:0);ADBMS181x_Config_GPIO(BMS1818_GPIO3,(i&0x01)? 1:0);bms1818_Reg.CFGARx[0]|=0x00;ADBMS181x_write_reg(WRCFGA,bms1818_Reg.CFGARx,1);ADBMS181x_write_reg(WRCFGB,bms1818_Reg.CFGBRx,0);BMS1818_Delay_us(20000);//切换完成等待20msADBMS1818_ADAX(MD_7KHZ_3KHZ,CHG_ALL);//转换通道1BMS1818_Delay_us(8000);ADBMS181x_read_reg(RDAUXA,bufdata,1);if(ADBMS1818_RC_Check(bufdata,Vdata)){//检查读出数据是否合法Tdata[0+i]=Vdata[0];Tdata[8+i]=Vdata[1];}}
}
/*IIC主机写
SlaveAddress  从机地址  一个字节
cmd           命令字    一个字节
data          数据      固定两个字节
*/ 
void ADBMS1818_IIC_Write(uint8_t SlaveAddress,uint8_t cmdbyte,uint8_t* data){bms1818_Reg.COMM[0]=((IW_Start<<4)|(SlaveAddress>>4)); //起始地址bms1818_Reg.COMM[1]=(SlaveAddress<<4) | FW_Nack;       bms1818_Reg.COMM[2]=(IW_Null<<4) | (cmdbyte>>4);       //cmdbms1818_Reg.COMM[3]=(cmdbyte<<4) | FW_Nack;bms1818_Reg.COMM[4]=(IW_Null<<4) | (data[0]>>4);       //数据0bms1818_Reg.COMM[5]=(data[0]<<4) | FW_Nack;  ADBMS181x_write_reg(WRCOMM,bms1818_Reg.COMM,1);  //将数据装入comm寄存器ADBMS181x_write_cmd(STCOMM,0);	//启动iic数据传输SET_SPI0_NSS_LOW;for(int i=0;i<9;i++)//在发送72个时钟spi_WR_byte2(0xff);SET_SPI0_NSS_HIGH;//memset(bms1818_Reg.COMM,0,6);//清除数据bms1818_Reg.COMM[0]=(IW_Null<<4) | (data[1]>>4);bms1818_Reg.COMM[1]=(data[1]<<4) | FW_NaS; //Nack信号和停止位bms1818_Reg.COMM[2]=(IW_Nsend<<4); //释放总线ADBMS181x_write_reg(WRCOMM,bms1818_Reg.COMM,1);  //第二次装入comm寄存器ADBMS181x_write_cmd(STCOMM,0);	//启动iic数据传输SET_SPI0_NSS_LOW;for(int i=0;i<9;i++)//在发送72个时钟spi_WR_byte2(0xff);SET_SPI0_NSS_HIGH;
}
/*IIC主机读
SlaveAddress   从机地址  一个字节
cmd            命令字(寄存器地址)    一个字节
data           数据      固定两个字节
*/ void ADBMS1818_IIC_Read(uint8_t SlaveAddress,uint8_t cmdbyte,uint8_t* data){bms1818_Reg.COMM[0]=((IW_Start<<4)|(SlaveAddress>>4)); //起始地址bms1818_Reg.COMM[1]=(SlaveAddress<<4) | FW_Nack;       bms1818_Reg.COMM[2]=(IW_Null<<4) | (cmdbyte>>4);       //cmdbms1818_Reg.COMM[3]=(cmdbyte<<4) | FW_NaS;bms1818_Reg.COMM[4]=((IR_Start<<4)|((SlaveAddress)>>4)); //发送从机地址 改为读bms1818_Reg.COMM[5]=((SlaveAddress|0x01)<<4) | FW_Nack; ADBMS181x_write_reg(WRCOMM,bms1818_Reg.COMM,1);  //将数据装入comm寄存器ADBMS181x_write_cmd(STCOMM,0);                   //启动iic数据传输SET_SPI0_NSS_LOW;for(int i=0;i<9;i++)//在发送72个时钟spi_WR_byte2(0xff);SET_SPI0_NSS_HIGH;bms1818_Reg.COMM[0]=((IW_Null<<4)|0x0f);  //接取两个字节bms1818_Reg.COMM[1]=(0xf0) | FW_Ack;       bms1818_Reg.COMM[2]=(IW_Null<<4) |0x0f;       bms1818_Reg.COMM[3]= 0xf0 | FW_NaS;bms1818_Reg.COMM[4]=(IW_Nsend<<4); //释放总线ADBMS181x_write_reg(WRCOMM,bms1818_Reg.COMM,1);  //将数据装入comm寄存器ADBMS181x_write_cmd(STCOMM,0);  SET_SPI0_NSS_LOW;for(int i=0;i<9;i++)//在发送72个时钟spi_WR_byte2(0xff);SET_SPI0_NSS_HIGH;ADBMS181x_read_reg(RDCOMM,bms1818_Reg.COMM,1);  //读取comm返回数据data[0]=(bms1818_Reg.COMM[0]<<4)|(bms1818_Reg.COMM[1]>>4);data[1]=(bms1818_Reg.COMM[2]<<4)|(bms1818_Reg.COMM[3]>>4);
}//测试定义数据
uint8_t BMS1818[18]={0};
uint16_t Vdata[18];
uint16_t TVdata[16];
int16_t  TP[16];
uint8_t data[8]={0xa0,0x0a};
void Bms1818_tset(void){//==========================读取温度示例=======================uint64_t temp;ADBMS181x_Config_GPIO(BMS1818_GPIO1,1);//输入引脚禁用下拉ADBMS181x_Config_GPIO(BMS1818_GPIO2,1);ADBMS181x_Config_GPIO(BMS1818_GPIO8,1);ADBMS181x_Config_GPIO(BMS1818_GPIO9,1);ADBMS181x_Config_GPIO(BMS1818_GPIO4,1);ADBMS181x_Config_GPIO(BMS1818_GPIO5,1);bms1818_Reg.CFGARx[0]|=0x04;//基准电压保持到看门狗超时ADBMS181x_write_reg(WRCFGA,bms1818_Reg.CFGARx,1);//配置io口ADBMS181x_write_reg(WRCFGB,bms1818_Reg.CFGBRx,0);ADBMS181x_read_16T(TVdata);//读取温度for(int i=0;i<16;i++){//温度转换temp=(33*TVdata[i])*1000/(30000-TVdata[i]);//将ad值计算出电阻值TP[i]=GetTempChangeVol(temp/10,Rtc_50to125,Rtc_50to125_Size,50);//根据电阻值查表得出实际温度}//======================读取电压示例============================
//  ADBMS181x_Config_GPIO(BMS1818_GPIO1,1);//输入引脚禁用下拉
//  ADBMS181x_Config_GPIO(BMS1818_GPIO2,1);
//  ADBMS181x_Config_GPIO(BMS1818_GPIO8,1);
//	ADBMS181x_Config_GPIO(BMS1818_GPIO9,1);
//	bms1818_Reg.CFGARx[0]|=0x04;//基准电压保持到看门狗超时
//	ADBMS181x_write_reg(WRCFGA,bms1818_Reg.CFGARx,1);//配置io口
//	ADBMS181x_write_reg(WRCFGB,bms1818_Reg.CFGBRx,0);ADBMS181x_read_18V(Vdata);//为直接读出的ad值//========================iic读写示例============================//	ADBMS181x_Config_GPIO(BMS1818_GPIO1,1);//输入引脚禁用下拉
//  ADBMS181x_Config_GPIO(BMS1818_GPIO2,1);
//  ADBMS181x_Config_GPIO(BMS1818_GPIO8,1);
//	ADBMS181x_Config_GPIO(BMS1818_GPIO9,1);
//	ADBMS181x_Config_GPIO(BMS1818_GPIO4,1);
//	ADBMS181x_Config_GPIO(BMS1818_GPIO5,1);
//	bms1818_Reg.CFGARx[0]|=0x04;//基准电压保持到看门狗超时
//	ADBMS181x_write_reg(WRCFGA,bms1818_Reg.CFGARx,1);//配置io口
//	ADBMS181x_write_reg(WRCFGB,bms1818_Reg.CFGBRx,0);
//	ADBMS1818_IIC_Write(0x48,0x02,data);data[0]=0x00; data[1]=0x00; BMS1818_Delay_us(20000);//等待20msADBMS1818_IIC_Read(0x48,0x02,data);
//	//========================结束====================================
}

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

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

相关文章

C++初学者指南第一步---4.基本类型

C初学者指南第一步—4.基本类型 文章目录 C初学者指南第一步---4.基本类型1.变量声明2.快速概览Booleans 布尔型Characters 字符型Signed Integers 有符号整数Unsigned Integers 无符号整数Floating Point Types 浮点数类型 3.Common Number Representations 常用的数字表示常用…

【数据结构】——常见排序

文章目录 一、 冒泡排序二、 选择排序三、插入排序四、 快速排序1. hoare版本2. 优化版本3. 前后指针法4. 非递归版本 五、 堆排序六、 希尔排序七、 归并排序1. 递归版本2. 非递归版本 八、 计数排序 在开始之前先准备一个交换数据的函数&#xff0c;排序会经常用到 //交换位置…

银河麒麟系统安装

新建虚拟机 选择典型下一步&#xff1a; 稍后安装操作系统 下一步 &#xff1a; 选择Linux Ubuntu 64位 下一步&#xff1a; 设置名称 选择一个虚拟机的位置进行下一步&#xff1a; 磁盘大小默认给20G 下一步&#xff1a; 点击完成 编辑虚拟机设置 点击CD/DVD(SATA) 使用IS…

Mysql数据库的锁机制

MySQL 中的锁可以按照粒度分为锁定整个表的表级锁&#xff08;table-level locking&#xff09;和锁定数据行的行级锁&#xff08;row-level locking&#xff09;表级锁开销小&#xff0c;加锁快&#xff0c;但是支持的并发度低&#xff0c;行级锁相反。 行锁 Innodb实现了以…

如何在小程序中实现页面之间的返回

在小程序中实现页面之间的返回&#xff0c;通常有以下几种方法&#xff0c;这些方法各有特点&#xff0c;适用于不同的场景&#xff1a; 1. 使用wx.navigateBack方法 描述&#xff1a;wx.navigateBack是微信小程序中用于关闭当前页面&#xff0c;返回上一页面或多级页面的API…

java技术专家面试指南80问【java学习+面试宝典】(九)

队列和栈是什么&#xff0c;列出它们的区别&#xff1f; 栈和队列两者都被用来预存储数据。java.util.Queue是一个接口&#xff0c;它的实现类在Java并发包中。队列允许先进先出&#xff08;FIFO&#xff09;检索元素&#xff0c;但并非总是这样。Deque接口允许从两端检索元素…

聊聊对Andorid的FileProvider的理解

最近在项目中遇到一个有关FileProvider的问题&#xff0c;由此来学习了一下FileProvider&#xff0c;有关笔记记录如下。 FileProvider是 Android 系统中一个特殊的内容提供者(ContentProvider), 它主要用于应用之间安全的共享文件。通过 FileProvider,应用可以生成一个 conte…

C#医院体检系统源码 PEIS源码 系统核心功能、特点、类型、设备对接-PACS放射科设备对接:DR、CT、MRI、钼靶。

C#医院体检系统源码 PEIS源码 系统核心功能、特点、类型、设备对接-PACS放射科设备对接:DR、CT、MRI、钼靶。 体检系统是为体检中心、医院体检科等体检机构专门开发的全流程管理系统。该系统通过软件实现检测仪器数据的自动提取&#xff0c;内置多级医生工作台&#xff0c;旨在…

每日一练:攻防世界:ewm

这道题我尝试了使用montagegaps解题&#xff0c;但是没有解出来&#xff0c;图片数量不是很多&#xff0c;可以尝试用PS直接拼图&#xff0c;但是这样学不到东西&#xff0c;我也就没尝试&#xff0c;直接看的官方WP 这段代码应该是改变工作目录到small&#xff0c;并且变量当…

基于springboot的宠物商城网站

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于springboot的宠物商城网站,java项目…

软件复盘的目的及作用

一、软件复盘的目的 软件复盘是一种在软件开发完成后、通过整理软件开发工作中的经验和教训以及对软件缺陷、进度、质量等问题的反思&#xff0c;识别和总结出开发团队应该坚持和改进的软件开发过程和技术的工作方式。软件复盘的主要目的是&#xff1a; 识别和总结软件开发过…

【Ubuntu20.04】安装XRDP远程桌面服务

【Ubuntu20.04】安装XRDP远程桌面服务 安装xrdp sudo apt install xrdp sudo adduser xrdp ssl-cert sudo systemctl restart xrdp黑屏解决 修改startwm.sh文件 sudo gedit /etc/xrdp/startwm.sh在test -x /etc/X11/Xsession上一行添加 unset DBUS_SESSION_BUS_ADDRESS un…

Linux C编译器从零开发二

自定义分词器 test.c #include <ctype.h> #include <stdarg.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h>typedef enum {TK_PUNCT, // PunctuatorsTK_NUM, // Numeric literalsTK_EOF, // …

基于carsim的线控转向仿真(1)--carsim车辆模型目标角度跟踪

一、Rwa转向执行总成建模 Rwa包括齿轮齿条机构、转向组件以及转向执行电机&#xff1b;如下图&#xff0c;电机输出轴通过齿轮减速增扭后&#xff0c;再经过一个半径为rp的小齿轮&#xff0c;直接带动齿条左右移动。齿条的移动通过转向摇臂&#xff0c;带动车轮转动&#xff0c…

使用 Apache SkyWalking 进行 Spring Cloud 应用的分布式追踪与监控:完整教程

使用 Apache SkyWalking 进行 Spring Cloud 应用的分布式追踪与监控&#xff1a;完整教程 SkyWalking 是一款开源的分布式追踪、性能监控和诊断平台&#xff0c;适用于微服务、云原生和容器化应用。它能够在分布式系统中收集和分析各个服务之间的调用关系和性能数据&#xff0…

PySide(PyQt)实现鼠标画框局部放大

按住鼠标左键画框&#xff0c;裁切画面并局部放大&#xff0c;可以用来生成ROI 1、在QtDesigner中创建ui文件&#xff0c;命名为crop.ui&#xff1a; 2、自定义脚本ImageLabel.py &#xff1a; from PySide6.QtCore import Qt, QRect, Signal, QPoint from PySide6.QtGui impo…

Redis高并发高可用

1. 复制机制 在分布式系统中&#xff0c;为了解决单点问题&#xff0c;通常会将数据复制多个副本部署到其他机器&#xff0c;以满足故障恢复和负载均衡等需求。Redis提供了复制功能&#xff0c;实现了相同数据的多个Redis副本。复制功能是高可用Redis的基础&#xff0c;后面的…

Unity 6预览版即将增加对visionOS 2的支持

Unity表示&#xff0c;届时将能帮助你创建更为身临其境的体验&#xff0c;并通过以下主要功能实现更大的视觉多样性&#xff1a; 支持混合形状&#xff0c;以实现更广泛的几何应用&#xff0c;包括变形和平滑&#xff0c;自然的动画。 立体渲染目标&#xff0c;帮助用户实现广…

长亭网络通信基础

长亭笔试之前就已经学过一遍了 这算温故而知新吧 TCP/IP 首先我在这里默写一下之前的7层和4层 应用层 应 【表示层 数据格式转换 传 【会话层 …

Vue 3 的常用响应式 API 总结

在vue3.x版本中&#xff0c;setup函数就是vue3 组合式API的入口&#xff0c;换句话说就是在setup中的写的代码&#xff0c;就是组合式API 的写法。下面总结常用的与响应式相关的api, 帮助您在 Vue 3 中创建响应式应用程序。 reactive() 和 ref()&#xff1a; 创建响应式对象和…