NXP公司LPC21XX+W25Q128实现外扩Flash

news2024/11/27 16:38:22

W25Q128FV串行Flash存储器由65536页组成,每一页256字节,总共128Mbit,相当于16M字节的存储空间。一次写入可操作高达256字节,擦除可以按16个页擦除(即一个Sector),128个页擦除(八个Sector),256个页擦除(16个Sector),或者整片擦除。标准SPI通信支持时钟频率高达104MHz,Dual SPI通信支持时钟频率高达208MHz,QSPI通信支持时钟频率高达416MHz。

本例使用NXP公司提供的LPC21XX平台的SPI控制器与串行Flash存储器W25Q128FV进行通信,实现对体量较大的数据进行存储。

概念说明

  • bit/Byte/Page/Sector:电脑是以二进制存储以及发送接收数据的。二进制的一位,就叫做 1 bit。也就是说 bit 的含义就是二进制数中的一个数位,即 “0” 或者 "1"。Byte 是字节的英文写法。它的简写为大写字母 “B",1 Byte = 8 bit。在本例中Page(页)是256个字节,Sector(扇区)是16个页。
  • SPI是一个同步的数据总线,也就是说它是用单独的数据线和一个单独的时钟信号来保证发送端和接收端的完美同步。产生时钟的一侧称为主机,另一侧称为从机。总是只有一个主机(一般来说可以是微控制器/MCU),但是可以有多个从机,W25Q128FV在本实现中即为从机。具体的通信时序如下:

  • 芯片命名规则:华邦的 SPI flash 型号(丝印)一般格式为(只看当前最新的 W25Q 系列):{[W25Q] [xxx] [y] [z] [XX] [Y] [Z]},
    • xxx表示容量(单位 bit),比如 16表示 16Mbit(2Mbyte),256表示 256Mbit (32Mbyte)。
    • y 表示第几代,按字母表顺序排列,比如 J 比 F的肯定要新,一般情况下,越新的支持的速度越高
    • z表示器件的电压范围:
      • L:2.3V - 3.6V

      • V:2,7V - 3.6V

      • W:1.65/1,7V - 1.95V

    • XX表示 封装类型:

      • SS = 8-pin SOIC 208-mil

      • ZP = WSON8 6x5-mm

      • XG = XSON 4x4x0.45-mm

      • SF = 16-pin SOIC 300-mil

      • TB = TFBGA 8x6-mm (5x5 ball array)

      • TC = TFBGA 8x6-mm (6x4 ball array)

    • Y 表示温度范围:

      • I = Industrial (-40°C to +85°C)

      • J = Industrial Plus (-40°C to +105°C)


实现原理

嵌入式代码运行在LPC21xx平台上,使用SPI控制器与Flash存储器进行通信,未使用芯片提供的写保护功能,原理示意图如下:


嵌入式代码

嵌入式代码由两部分构成:

  1. LPC21XX平台SPI控制器初始化
  2. W25Q128FV芯片Flash操作接口封装

如上所述,我们第一步的工作需要将SPI控制器按照正确的通信速率进行初始化,并为后边Flash的读写操作提供SPI收发接口,代码如下:

#include <lpc213x.h>
#include "spi.h"
#include "serial.h"

#define SPI_DEBUG (1)

#if 0
void spi0_isr(void) __irq
{
    unsigned char status;
    unsigned char recv_byte;

    if ((VICIRQStatus & 0x400) && (S0SPINT & 0x1))
    {
        /* Interrupt Occurs */
        status = S0SPSR;

        if (status & 0x78)
        {
            /* ABRT/MODF/ROVR/WCOL exceptions */
            sendstr("spi bus 0 exception, status=");
            sendhex(status);
            sendstr("\n");
        }
        else if (status == 0x80)
        {
            /* SPIF indicates SPI Transfer Completed,
            ** read or write SPI Data Reg clear SPIF
            */
            recv_byte = S0SPDR;
            sendstr("spi bus 0 recv ");
            sendhex(recv_byte);
            sendstr("\n");
        }

        /* Clear Interrupt */
        S0SPINT = 0x1;
    }

}
#endif

void spi_init(void)
{
    /* Configure P0.4~7 as SPI bus 0 */
    PINSEL0 &= ~0x0000FF00;
    PINSEL0 |= 0x00005500;

    /* PCLK is 30MHz, SPI Clock Frequency is 5MHz */
    S0SPCCR = 0x6;

    /* Master mode, 8 bits per transfer(MSB first),
    ** disable interrupt, CPOL=0, CPHA=0
    */
    S0SPCR = 0x20;

#if 0
    /* SPI Bus 0 ISR */
    VICVectCntl2 = 0x20 | 10;
    VICVectAddr2 = (unsigned int)spi0_isr;
    VICIntEnable = 1 << 10;
#endif

}

int spi_write_byte(unsigned char byte)
{
    unsigned char recv_byte;

    if (SPI_DEBUG)
    {
        sendstr("spi bus 0 send ");
        sendhex(byte);
        sendstr("\n");
    }

    S0SPDR = byte;

    /* Check SPIF bit, Wait for Data Transfer Complete */
    while (!(S0SPSR & 0x80));
    recv_byte = S0SPDR;
    if (SPI_DEBUG)
    {
        sendstr("spi bus 0 recv ");
        sendhex(recv_byte);
        sendstr("\n");
    }

    return recv_byte;
}

int spi_read_byte(unsigned char *byte)
{
    if (0 == byte)
    {
        sendstr("spi_read_byte byte is NULL\n");
        return -1;
    }

    /* Only Write S0SPDR generate SPI Clock for receive data */
    *byte = spi_write_byte(0xFF);

    return 0;
}

int spi_write(unsigned char *data, int len)
{
    int i = 0;

    if (0 == data)
    {
        sendstr("spi_write data is NULL\n");
        return -1;
    }

    for (i = 0; i < len; i++)
    {
        spi_write_byte(data[i]);
    }

    return 0;
}

int spi_read(unsigned char *data, int len)
{
    int i = 0;

    if (0 == data)
    {
        sendstr("spi_read data is NULL\n");
        return -1;
    }

    for (i = 0; i < len; i++)
    {
        spi_read_byte(&data[len - 1 -i]);
    }

    return 0;
}

我们第二步需要将对外扩的Flash芯片读写等操作接口封装好供上层应用使用,下面是它的.c以及对应的.h文件,代码中由相关注释帮助理解。

  • W25Q12xx.c:
    #include "w25qxx.h" 
    #include "spi.h"
    #include "delay.h"	   
    #include "usart.h"	
     
    u16 W25QXX_TYPE=W25Q128;	//默认是W25Q128
     
    //4Kbytes为一个Sector
    //16个扇区为1个Block
    //W25Q128
    //容量为16M字节,共有128个Block,4096个Sector 
    													 
    //初始化SPI FLASH的IO口
    void W25QXX_Init(void)
    { 
        spi_init();		   			//初始化SPI
    	W25QXX_TYPE=W25QXX_ReadID();	//读取FLASH ID.
    }  
     
    //读取W25QXX的状态寄存器
    //BIT7  6   5   4   3   2   1   0
    //SPR   RV  TB BP2 BP1 BP0 WEL BUSY
    //SPR:默认0,状态寄存器保护位,配合WP使用
    //TB,BP2,BP1,BP0:FLASH区域写保护设置
    //WEL:写使能锁定
    //BUSY:忙标记位(1,忙;0,空闲)
    //默认:0x00
    u8 W25QXX_ReadSR(void)   
    {  
    	u8 byte=0;   
    	W25QXX_CS=0;                            //使能器件   
    	spi_write(W25X_ReadStatusReg,1);    //发送读取状态寄存器命令    
    	spi_read(&byte,1);             //读取一个字节  
    	W25QXX_CS=1;                            //取消片选     
    	return byte;   
    } 
    //写W25QXX状态寄存器
    //只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!!
    void W25QXX_Write_SR(u8 sr)   
    {   
    	W25QXX_CS=0;                            //使能器件   
    	spi_write(W25X_WriteStatusReg,1);   //发送写取状态寄存器命令    
    	spi_write(sr,1);               //写入一个字节  
    	W25QXX_CS=1;                            //取消片选     	      
    }   
    //W25QXX写使能	
    //将WEL置位   
    void W25QXX_Write_Enable(void)   
    {
    	W25QXX_CS=0;                            //使能器件   
        spi_write(W25X_WriteEnable,1);      //发送写使能  
    	W25QXX_CS=1;                            //取消片选     	      
    } 
    //W25QXX写禁止	
    //将WEL清零  
    void W25QXX_Write_Disable(void)   
    {  
    	W25QXX_CS=0;                            //使能器件   
        spi_write(W25X_WriteDisable,1);     //发送写禁止指令    
    	W25QXX_CS=1;                            //取消片选     	      
    } 		
    //读取芯片ID
    //返回值如下:				   
    //0XEF13,表示芯片型号为W25Q80  
    //0XEF14,表示芯片型号为W25Q16    
    //0XEF15,表示芯片型号为W25Q32  
    //0XEF16,表示芯片型号为W25Q64 
    //0XEF17,表示芯片型号为W25Q128 	  
    u16 W25QXX_ReadID(void)
    {
    	u16 Temp = 0;	  
    	W25QXX_CS=0;				    
    	spi_write(0x90,1);//发送读取ID命令	    
    	spi_write(0x00,1); 	    
    	spi_write(0x00,1); 	    
    	spi_write(0x00,1); 	 			   
    	spi_read(&Temp,2);   
    	W25QXX_CS=1;				    
    	return Temp;
    }   		    
    //读取SPI FLASH  
    //在指定地址开始读取指定长度的数据
    //pBuffer:数据存储区
    //ReadAddr:开始读取的地址(24bit)
    //NumByteToRead:要读取的字节数(最大65535)
    void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)   
    { 
     	u16 i;   										    
    	W25QXX_CS=0;                            //使能器件   
        spi_write(W25X_ReadData,1);         //发送读取命令   
        spi_write((u8)((ReadAddr)>>16),1);  //发送24bit地址    
        spi_write((u8)((ReadAddr)>>8),1);   
        spi_write((u8)ReadAddr,1);   
        spi_read(pBuffer,NumByteToRead);
    	W25QXX_CS=1;  				    	      
    }  
    //SPI在一页(0~65535)内写入少于256个字节的数据
    //在指定地址开始写入最大256字节的数据
    //pBuffer:数据存储区
    //WriteAddr:开始写入的地址(24bit)
    //NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!	 
    void W25QXX_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
    {
     	u16 i;  
        W25QXX_Write_Enable();                  //SET WEL 
    	W25QXX_CS=0;                            //使能器件   
        spi_write(W25X_PageProgram,1);      //发送写页命令   
        spi_write((u8)((WriteAddr)>>16),1); //发送24bit地址    
        spi_write((u8)((WriteAddr)>>8),1);   
        spi_write((u8)WriteAddr,1);   
        spi_write(pBuffer,NumByteToWrite);  
    	W25QXX_CS=1;                            //取消片选 
    	W25QXX_Wait_Busy();					   //等待写入结束
    } 
    //无检验写SPI FLASH 
    //必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
    //具有自动换页功能 
    //在指定地址开始写入指定长度的数据,但是要确保地址不越界!
    //pBuffer:数据存储区
    //WriteAddr:开始写入的地址(24bit)
    //NumByteToWrite:要写入的字节数(最大65535)
    //CHECK OK
    void W25QXX_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)   
    { 			 		 
    	u16 pageremain;	   
    	pageremain=256-WriteAddr%256; //单页剩余的字节数		 	    
    	if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
    	while(1)
    	{	   
    		W25QXX_Write_Page(pBuffer,WriteAddr,pageremain);
    		if(NumByteToWrite==pageremain)break;//写入结束了
    	 	else //NumByteToWrite>pageremain
    		{
    			pBuffer+=pageremain;
    			WriteAddr+=pageremain;	
     
    			NumByteToWrite-=pageremain;			  //减去已经写入了的字节数
    			if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
    			else pageremain=NumByteToWrite; 	  //不够256个字节了
    		}
    	};	    
    } 
    //写SPI FLASH  
    //在指定地址开始写入指定长度的数据
    //该函数带擦除操作!
    //pBuffer:数据存储区
    //WriteAddr:开始写入的地址(24bit)						
    //NumByteToWrite:要写入的字节数(最大65535)   
    u8 W25QXX_BUFFER[4096];		 
    void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)   
    { 
    	u32 secpos;
    	u16 secoff;
    	u16 secremain;	   
     	u16 i;    
    	u8 * W25QXX_BUF;	  
       	W25QXX_BUF=W25QXX_BUFFER;	     
     	secpos=WriteAddr/4096;//扇区地址  
    	secoff=WriteAddr%4096;//在扇区内的偏移
    	secremain=4096-secoff;//扇区剩余空间大小   
     	//printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
     	if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节
    	while(1) 
    	{	
    		W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容
    		for(i=0;i<secremain;i++)//校验数据
    		{
    			if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除  	  
    		}
    		if(i<secremain)//需要擦除
    		{
    			W25QXX_Erase_Sector(secpos);//擦除这个扇区
    			for(i=0;i<secremain;i++)	   //复制
    			{
    				W25QXX_BUF[i+secoff]=pBuffer[i];	  
    			}
    			W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区  
     
    		}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间. 				   
    		if(NumByteToWrite==secremain)break;//写入结束了
    		else//写入未结束
    		{
    			secpos++;//扇区地址增1
    			secoff=0;//偏移位置为0 	 
     
    		   	pBuffer+=secremain;  //指针偏移
    			WriteAddr+=secremain;//写地址偏移	   
    		   	NumByteToWrite-=secremain;				//字节数递减
    			if(NumByteToWrite>4096)secremain=4096;	//下一个扇区还是写不完
    			else secremain=NumByteToWrite;			//下一个扇区可以写完了
    		}	 
    	};	 
    }
    //擦除整个芯片		  
    //等待时间超长...
    void W25QXX_Erase_Chip(void)   
    {                                   
        W25QXX_Write_Enable();                  //SET WEL 
        W25QXX_Wait_Busy();   
      	W25QXX_CS=0;                            //使能器件   
        spi_write(W25X_ChipErase,1);        //发送片擦除命令  
    	W25QXX_CS=1;                            //取消片选     	      
    	W25QXX_Wait_Busy();   				   //等待芯片擦除结束
    }   
    //擦除一个扇区
    //Dst_Addr:扇区地址 根据实际容量设置
    //擦除一个山区的最少时间:150ms
    void W25QXX_Erase_Sector(u32 Dst_Addr)   
    {  
    	//监视falsh擦除情况,测试用   
     	printf("fe:%x\r\n",Dst_Addr);	  
     	Dst_Addr*=4096;
        W25QXX_Write_Enable();                  //SET WEL 	 
        W25QXX_Wait_Busy();   
      	W25QXX_CS=0;                            //使能器件   
        spi_write(W25X_SectorErase,1);      //发送扇区擦除指令 
        spi_write((u8)((Dst_Addr)>>16),1);  //发送24bit地址    
        spi_write((u8)((Dst_Addr)>>8),1);   
        spi_write((u8)Dst_Addr);  
    	W25QXX_CS=1;                            //取消片选     	      
        W25QXX_Wait_Busy();   				   //等待擦除完成
    }  
    //等待空闲
    void W25QXX_Wait_Busy(void)   
    {   
    	while((W25QXX_ReadSR()&0x01)==0x01);   // 等待BUSY位清空
    }  
    //进入掉电模式
    void W25QXX_PowerDown(void)   
    { 
      	W25QXX_CS=0;                            //使能器件   
        spi_write(W25X_PowerDown,1);        //发送掉电命令  
    	W25QXX_CS=1;                            //取消片选     	      
        delay_us(3);                               //等待TPD  
    }   
    //唤醒
    void W25QXX_WAKEUP(void)   
    {  
      	W25QXX_CS=0;                            //使能器件   
        spi_write(W25X_ReleasePowerDown,1);   //  send W25X_PowerDown command 0xAB    
    	W25QXX_CS=1;                            //取消片选     	      
        delay_us(3);                               //等待TRES1
    }   
  •  W25Q12xx.h:
     
    W25Q12xx.h:
     
    #ifndef __W25QXX_H
    #define __W25QXX_H			    
    #include "sys.h"  
     
    //W25X系列/Q系列芯片列表	   
    //W25Q80  ID  0XEF13
    //W25Q16  ID  0XEF14
    //W25Q32  ID  0XEF15
    //W25Q64  ID  0XEF16	
    //W25Q128 ID  0XEF17	
    #define W25Q80 	0XEF13 	
    #define W25Q16 	0XEF14
    #define W25Q32 	0XEF15
    #define W25Q64 	0XEF16
    #define W25Q128	0XEF17
     
    extern u16 W25QXX_TYPE;					//定义W25QXX芯片型号		   
     
    #define	W25QXX_CS 		PBout(14)  		//W25QXX的片选信号
    // 
    //指令表
    #define W25X_WriteEnable		0x06 
    #define W25X_WriteDisable		0x04 
    #define W25X_ReadStatusReg		0x05 
    #define W25X_WriteStatusReg		0x01 
    #define W25X_ReadData			0x03 
    #define W25X_FastReadData		0x0B 
    #define W25X_FastReadDual		0x3B 
    #define W25X_PageProgram		0x02 
    #define W25X_BlockErase			0xD8 
    #define W25X_SectorErase		0x20 
    #define W25X_ChipErase			0xC7 
    #define W25X_PowerDown			0xB9 
    #define W25X_ReleasePowerDown	0xAB 
    #define W25X_DeviceID			0xAB 
    #define W25X_ManufactDeviceID	0x90 
    #define W25X_JedecDeviceID		0x9F 
     
    void W25QXX_Init(void);
    u16  W25QXX_ReadID(void);  	    		//读取FLASH ID
    u8	 W25QXX_ReadSR(void);        		//读取状态寄存器 
    void W25QXX_Write_SR(u8 sr);  			//写状态寄存器
    void W25QXX_Write_Enable(void);  		//写使能 
    void W25QXX_Write_Disable(void);		//写保护
    void W25QXX_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite);
    void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead);   //读取flash
    void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite);//写入flash
    void W25QXX_Erase_Chip(void);    	  	//整片擦除
    void W25QXX_Erase_Sector(u32 Dst_Addr);	//扇区擦除
    void W25QXX_Wait_Busy(void);           	//等待空闲
    void W25QXX_PowerDown(void);        	//进入掉电模式
    void W25QXX_WAKEUP(void);				//唤醒
     
    #endif

 十六宿舍 原创作品,转载必须标注原文链接。

©2023 Yang Li. All rights reserved.

欢迎关注 『十六宿舍』,大家喜欢的话,给个👍,更多关于嵌入式相关技术的内容持续更新中。

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

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

相关文章

元宇宙营销策略、玩法与案例

“元宇宙”依旧是当下品牌创新营销的重要形式&#xff0c;从时趣的行业观察来看&#xff0c;大量品牌方都有着元宇宙的营销意向&#xff0c;但在营销落地上存在不同的进度。一个显而易见的事实是&#xff0c;元宇宙不仅仅是一个虚拟的游戏空间&#xff0c;更是一个未来人人都会…

泛型编程 之模板(template)

C另一种编程思想称为 泛型编程&#xff0c;主要利用的技术就是模板 目录 C另一种编程思想称为 泛型编程&#xff0c;主要利用的技术就是模板 一、概念 二、函数模板 1、语法与使用&#xff1a; 2、函数模板注意事项 3、普通函数与函数模板的区别 4、普通函数与函数模板的调用规…

“探究二叉搜索树:从原理到实现“

&#x1f4d6;作者介绍&#xff1a;22级树莓人&#xff08;计算机专业&#xff09;&#xff0c;热爱编程&#xff1c;目前在c&#xff0b;&#xff0b;阶段>——目标Windows&#xff0c;MySQL&#xff0c;Qt&#xff0c;数据结构与算法&#xff0c;Linux&#xff0c;多线程&…

数量形状遗传率及计算方法

数量性状的遗传率/遗传力(heritability) (1)表型值及其方差的分量 1. 表型值及其剖分 某数量性状的表型值就是实际所度量或观察到的数值。表型值受许多外界因素如士壤、肥力、水分、光照、温度等的改变而发生变异&#xff0c;这种变异归因于环境因素。任何一个数量性状的表现…

SentiBank Dector上手指南

​ 官网链接&#xff1a;https://www.ee.columbia.edu/ln/dvmm/vso/download/sentibank.html SentiBank Detector可以抽取图片中的形容词-名词对&#xff0c;之前一直看到&#xff0c;这次复现模型才第一次用到&#xff0c;上手的时候有点手足无措&#xff0c;因为官网在如何使…

傅里叶变换解析

p.s.本文无论是cos还是sin&#xff0c;都统一用“正弦波”(Sine Wave)一词来代表简谐波。 一、什么是频域 从我们出生&#xff0c;我们看到的世界都以时间贯穿&#xff0c;股票的走势、人的身高、汽车的轨迹都会随着时间发生改变。这种以时间作为参照来观察动态世界的方法我们称…

自动驾驶技术的优势、局限性及未来发展趋势

自动驾驶技术是当前汽车行业的热门话题之一。该技术的发展&#xff0c;不仅可以提高车辆的安全性和行驶效率&#xff0c;还可以为人们的出行带来更多便利。但与此同时&#xff0c;自动驾驶技术也存在着许多争议和挑战。接下来从以下四个方面谈一下我对自动驾驶技术的看法。 一…

贝叶斯决策理论

贝叶斯决策理论的相关知识 贝叶斯的思想&#xff1a;顾名思义&#xff0c;贝叶斯决策论是利用概率来进行决策&#xff0c;是概率框架下的方法。贝叶斯决策论是利用概率的不同分类决策与相应的决策代价之间的平衡&#xff0c;核心思想是决策问题可以通过概率的形式来描述。 1.…

数量性状基因座QTL及其作图

数量性状基因座作图原理与步骤 经典的数量遗传分析方法 ->只能分析控制数量性状表现的众多基因的综合遗传效应,无法准确鉴别基因的数目、单个基因在染色体上的位置和遗传效应 (1)数量性状基因座(QTL) Quantitative trait loci: QTL 数量性状位点(基因座) 所谓QTL是指通过…

基于TCP的C/S模型代码实现

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

自学C#,要懂得善用MSDN

很多初学者学习编程&#xff0c;都会通过看别人写的教程、或者录制的视频&#xff0c;来学习。 这是一个非常好的途径&#xff0c;因为这个是非常高效的。 但是这样&#xff0c;存在两个问题&#xff1a; 1、教程不够全面&#xff1a;任何再好的教程&#xff0c;都无法囊括所…

Java 输出机制 数据类型 基本数据类型转换 基本数据类型和String类型的转换

目录 一、输出机制 1.print和println的差别 2.可接收不同类型参数 3.输出函数中 符号的使用 二、数据类型 1.整型类型 2.浮点类型 3.字符类型 三、基本数据类型转换 1.自动类型转换 2.强制类型转换 3.练习题 四、基本数据类型和String类型的转换 1.基本类型转S…

论文写作精品课程

本文介绍了一些论文写作的在线课程&#xff0c;方便读者朋友们自学&#xff0c;提高论文写作的能力。论文写作的在线课程非常多&#xff0c;读者朋友们也可以在网上自行搜索&#xff0c;选择适合自己的在线课程进行学习。如需要打开课程的网站&#xff0c;请复制课程的网址到浏…

PostgreSQL16中pg_dump的LZ4和ZSTD压缩

PostgreSQL16中pg_dump的LZ4和ZSTD压缩 pg_dump压缩lz4和zstd LZ4和ZSTD压缩算法合入了PG16。LZ4补丁的作者是Georgios Kokolatos。由Tomas Vondra提交。由Michael Paquier、Rachel Heaton、Justin Pryzby、Shi Yu 和 Tomas Vondra 审阅。提交消息是&#xff1a; Expand pg_dum…

【Java EE初阶】计算机简介及多线程之创建线程

目录 1.计算机发展史 2.冯诺依曼体系 3.操作系统 操作系统的作用&#xff1a; 4.进程 1.PID&#xff08;进程编号&#xff09; 2.内存指针 应用程序申请到的内存中的首地址 3.文件描述符表 问&#xff1a;什么是并发&#xff1f;什么是并行&#xff1f; 4.进程的优先级&a…

Tomcat8和Tomcat9乱码问题

今天新开了一个小项目&#xff0c;我丢&#xff0c;乱码了&#xff0c;咋回事&#xff0c;好久没遇到过了&#xff0c;都忘了咋回事。今天必须记录下来&#xff0c;避免继续踩坑 Tomcat 8 不需要进行任何配置即可&#xff0c;它默认的是GBK&#xff0c;而win10 win7 默认的也是…

[Data structure]单链表 | 一文介绍线性数据结构之一的单链表(Java实现)

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;数据结构。数据结构专栏主要是在讲解原理的基础上拿Java实现 ⭐如果觉得文章写的不错&#xff0c;欢迎点个关注一…

R语言 | 数据框

目录 一、认识数据框 7.1 建立第一个数据框 7.2 验证与设定数据框的列名和行名 二、认识数据框的结构 三、获取数据框内容 3.1 一般获取 3.2 特殊字符$ 3.3 再看取得的数据 四、使用rbind()函数增加数据框的行数据 五、使用cbind()函数增加数据框的列数据 5.1 使用$符号…

《LearnUE——基础指南:开篇—3》——基础概念

目录 程序之祖——HellowWorld 0.3.1 创建HellowWorld工程 0.3.2编译类型 0.3.3 平台支持 0.3.4 命名约定 程序之祖——HellowWorld 0.3.1 创建HellowWorld工程 接上文准备工作完成之后&#xff0c;双击运行Unreal Engine快捷图标&#xff0c;或者双击生成的UE4Editor.exe…

【计算机图形学】图形变换(以任意直线为对称轴的对称变换)

模块3-2 图形变换 一 实验目的 编写图形各种变换的算法 二 实验内容 1&#xff1a;任意直线的对称变换。要求将变换矩阵写在实验报告中&#xff0c;并与代码匹配。求对任意直线AxByC0的对称变换矩阵。 实验结果如下图所示&#xff1a; 1&#xff1a;预设图形初始化 2&#…