【GD32】06 - SPI (含ST7735S TFT-LCD屏幕驱动)

这篇文章我们看看GD32中如何实现SPI,软件SPI的话可以参考我之前的文章,把对应操作GPIO口的代码从STM32改成GD32就可以使用了。

【快速上手STM32】SPI通信协议&&1.8寸TFT-LCD(ST7735S)_tftlcdst7735和stm32-CSDN博客文章浏览阅读3.7k次,点赞46次,收藏60次。SPI,英文全称Serial Peripheral Interface,即串行外围设备接口,是一种高速、全双工、同步的串行通信总线。我们之前说过I2C,那么我们就拿I2C和SPI做个对比。SPI和I2C对比,优势在于SPI的传输速率比I2C快得多,劣势在于SPI需要用的通信线比较多。_tftlcdst7735和stm32https://blog.csdn.net/m0_63235356/article/details/136977377?spm=1001.2014.3001.5501这边就来看看硬件SPI如何使用。

和之前不一样,我这篇文章使用的GD32是GD32F407VET6,其实大体上没差别,因为我们使用的是固件库。要注意的就是两种型号的单片机的引脚SPI资源不一样,不同的SPI对应的引脚是不一样的,这个要查手册去对应上,不过相同的SPI资源好像引脚是一样的,比如说GD32E230的SPI0和GD32F407的引脚是一样的。那么我们接下来就使用SPI0来做示范,这样不管是哪个型号的板子都可以兼容。

 

流程上都是先配置好GPIO为复用模式,接着是初始化SPI,然后就直接可以用了,GD32的硬件SPI还是非常方便的。

第一步先配置时钟。

要配置的有硬件SPI0,以及对应的引脚所在的GPIO端口,因为SPI0对应的引脚都在GPIOA,因此我们只需要使能GPIOA的时钟,如果是其他的SPI资源的话可能就要使能多个端口了。

rcu_periph_clock_enable(RCU_GPIOA);    // 使能GPIOA
rcu_periph_clock_enable(RCU_SPI0);     // 使能SPI0

接下来我们要开启引脚复用,SPI一共是四个引脚,MISO,MOSI,SS,SCK,其中SS一般来说我们不让他硬件控制,通常我们会另外软件控制,因为硬件SPI的SS是固定死的,这样可能会和我们其他要用的引脚冲突,而且使用硬件SPI就是为了速度更快,而SS软件另外控制并不会影响多少速度,因此我们就算使用硬件SPI,也会让SS引脚使用软件控制。

所以开启引脚复用只需要开启另外三个即可。

#define Z_SPI_PORT  GPIOA
#define Z_SPI_SS    GPIO_PIN_4
#define Z_SPI_SCK   GPIO_PIN_5
#define Z_SPI_MISO  GPIO_PIN_6
#define Z_SPI_MOSI  GPIO_PIN_7

上面是宏定义,但是其实好像没什么必要,因为硬件SPI的引脚是固定死的,留着宏定义是因为代码是之前软件SPI的代码,懒得改了就留下来了。大家看下面示例代码的时候看见“Z_”开头的知道是SPI引脚的宏定义就可以了。 

    //开启引脚复用gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_SCK);gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_MISO);gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_MOSI);

接下来就是配置GPIO口的模式了。

SS引脚我们不用硬件SPI的,我们单独控制,直接配置为输出模式即可,因为默认我们不选中,所以加个上拉电阻。

其他三个引脚我们选择复用模式(GPIO_MODE_AF),因为是交给硬件SPI了,所以我们不加电阻。

    gpio_mode_set(Z_SPI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, Z_SPI_SS);gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_SCK);gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_MISO);gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_MOSI);

接下来就是配置输出模式了。

都配置为输出模式即可,速度选择50MHz就够用了,一般用于通信的引脚的输出频率为两倍传输速率就可以了。

    gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_SS);gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_SCK);gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_MISO);gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_MOSI);

配置完引脚,接下来就可以配置SPI了。

这是从GD32F407固件库手册里截取的,如果是GD32E230的话SPI就只有0和1,没有2345了,其他是一样的。

device_mode :一般我们就选择主机模式SPI_MASTER

trans_mode : 选择全双工模式SPI_TRANSMODE_FULLDUPLEX,说实话,除了仅接受之外的其他两个选项没看懂。

frame_size : 数据帧格式我们都是选择8bit的SPI_FRAMESIZE_8BIT,如果要发送16bit的时候发送两次8bit就行了。

nss : 前面说了,我们SS就软件控制就行了SPI_NSS_SOFT,因此这边选择软件控制。

endian : 大端小端就是高位在前在后的区别,我们SPI基本上都是高位在前,因此选择大端模式SPI_ENDIAN_MSB

spi_init_struct.clock_polarity_phase : 相位和极性配置,说通俗一点就是选择SPI的模式。

一般来说有四种模式。

时序图可以参考下面的。

不懂要通信的模块支持哪种模式的话就默认选模式0就行SPI_CK_PL_LOW_PH_1EDGE,一般来说模式0是都支持的,实在不行就四种模式都试一遍(但是得保证其他环节不出错)。

prescale : 这是预分频器,这就要看看SPI的速率以及时钟频率了。

我们先来看看SPI的时钟频率。

SPI0挂载在APB2上,频率是84MHz。那么我们分频可以分个8,也就是差不多10MHz的速率。

因为我问的科大讯飞的大模型,它说ST7735S支持的速率是12MHz,当然了,仅供参考。因为我2分频之后也是可以正常使用ST7735S的。

综上,我们安装下面这样配置就可以了。

    spi_parameter_struct spi_init_struct;spi_init_struct.trans_mode        		= SPI_TRANSMODE_FULLDUPLEX;  // 传输模式全双工spi_init_struct.device_mode       		= SPI_MASTER;                // 配置为主机spi_init_struct.frame_size         		= SPI_FRAMESIZE_8BIT;        // 8位数据spi_init_struct.clock_polarity_phase 	= SPI_CK_PL_LOW_PH_1EDGE;    // 模式0  spi_init_struct.nss               		= SPI_NSS_SOFT;              // 软件csspi_init_struct.prescale           		= SPI_PSC_8;                 // 8分频spi_init_struct.endian            		= SPI_ENDIAN_MSB;            // 高位在前spi_init(SPI0, &spi_init_struct);

接下来就是使能。

spi_enable(SPI0);

配置完上面之后我们就可以直接发送数据了。

因为我们之前配置的是8bit,因此第二个参数传入8位的数据就可以了,这边形参类型是16bit是为了兼容两种传输格式。

spi_i2s_data_transmit(SPI0, data);

然后我们注意到了函数的名称是SPI_i2s开头的,因此i2s发送数据的函数也是用的这个。

接收数据的话我们用另外一个函数。

在发送和接收之前,我们需要检查缓冲区是否满足要求——发送的时候缓冲区是否为空,接收的时候缓冲区是否有数据。

常用的标志我用红框框出来了,完整的标志可以到固件库手册里查看。

因此我们发送一次数据可以封装起来。也就是在发送数据之前先检测发送缓冲区为空,在接收之前检测接收缓冲区非空。而且SPI它通信是类似于交换的,所以我们发送和接收放在一起。

uint8_t Z_SPI_SwapByte(uint8_t data){//等待发送缓冲区为空while(RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE)); spi_i2s_data_transmit(SPI0, data);//等待接收缓冲区不空while(RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_RBNE));return spi_i2s_data_receive(SPI0);
}

有了上面这些函数,我们就可以使用硬件SPI了,完整的配置代码可以参考下面。

#define Z_SPI_PORT  GPIOA
#define Z_SPI_SS    GPIO_PIN_4
#define Z_SPI_SCK   GPIO_PIN_5
#define Z_SPI_MISO  GPIO_PIN_6
#define Z_SPI_MOSI  GPIO_PIN_7void Z_SPI_SetSS(uint8_t val){        //封装一下选中SSgpio_bit_write(Z_SPI_PORT, Z_SPI_SS,val);
}void Z_SPI_Init(void){rcu_periph_clock_enable(RCU_GPIOA);    // 使能GPIOA外设时钟rcu_periph_clock_enable(RCU_SPI0);     // 使能SPI0外设时钟//配置引脚复用gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_SCK);gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_MISO);gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_MOSI);//配置引脚模式gpio_mode_set(Z_SPI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, Z_SPI_SS);gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_SCK);gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_MISO);gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_MOSI);//配置输出模式gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_SS);gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_SCK);gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_MISO);gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_MOSI);Z_SPI_SetSS(1);        //默认不选中spi_parameter_struct spi_init_struct;spi_init_struct.trans_mode        		= SPI_TRANSMODE_FULLDUPLEX;  // 传输模式全双工spi_init_struct.device_mode       		= SPI_MASTER;                // 配置为主机spi_init_struct.frame_size         		= SPI_FRAMESIZE_8BIT;        // 8位数据spi_init_struct.clock_polarity_phase 	= SPI_CK_PL_LOW_PH_1EDGE;    // SPI模式0  spi_init_struct.nss               		= SPI_NSS_SOFT;              // 软件SSspi_init_struct.prescale           		= SPI_PSC_8;                 // 8分频spi_init_struct.endian            		= SPI_ENDIAN_MSB;            // 高位在前spi_init(SPI0, &spi_init_struct);//使能SPIspi_enable(SPI0);}uint8_t Z_SPI_SwapByte(uint8_t data){//等待发送缓冲区为空while(RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE)); spi_i2s_data_transmit(SPI0, data);//等待接收缓冲区非空while(RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_RBNE));return spi_i2s_data_receive(SPI0);
}

有了SPI,我们就可以直接封装ST7735S的驱动了,具体ST7735S的指令什么的我就不在这边啰嗦了,之前的文章有小小地介绍一下,文章链接在本文的开头。下面就直接把驱动代码贴出来了(需要包含上面的示例代码)。

/*
ST7725S驱动代码
*/
#define Z_ST7735S_RST_GPIO  GPIO_PIN_0
#define Z_ST7735S_DC_GPIO   GPIO_PIN_1
#define Z_ST7735S_PORT      GPIOA
#define Z_ST7735S_WIDTH     128
#define Z_ST7735S_HIGH      160void Z_ST7735S_SetRST(uint8_t val){gpio_bit_write(Z_ST7735S_PORT,Z_ST7735S_RST_GPIO,val);
}void Z_ST7735S_SetDC(uint8_t val){gpio_bit_write(Z_ST7735S_PORT,Z_ST7735S_DC_GPIO,val);
}//发送指令,需要把DC拉低
void Z_ST7735S_SendCommand(uint8_t command){Z_SPI_SetSS(0);Z_ST7735S_SetDC(0);Z_SPI_SwapByte(command);Z_SPI_SetSS(1);
}//发送数据,需要把DC拉高
void Z_ST7735S_SendData(uint8_t data){Z_SPI_SetSS(0);Z_ST7735S_SetDC(1);Z_SPI_SwapByte(data);Z_SPI_SetSS(1);
}//发送16位的数据
void Z_ST7735S_Send16bitsRGB(uint16_t rgb)
{Z_ST7735S_SendData(rgb >> 8);Z_ST7735S_SendData(rgb);
}//初始化ST7735S,其中一段初始化序列厂家会提供
void Z_ST7735S_Init(void){Z_SPI_Init();// 除了上面SPI初始化的GPIO口,还需要额外初始化RST和DCif(Z_ST7735S_PORT==GPIOA)  rcu_periph_clock_enable(RCU_GPIOA);else if(Z_ST7735S_PORT==GPIOB) rcu_periph_clock_enable(RCU_GPIOB);else if(Z_ST7735S_PORT==GPIOC) rcu_periph_clock_enable(RCU_GPIOC);gpio_mode_set(Z_ST7735S_PORT,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,Z_ST7735S_RST_GPIO);gpio_output_options_set(Z_ST7735S_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,Z_ST7735S_RST_GPIO);gpio_mode_set(Z_ST7735S_PORT,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,Z_ST7735S_DC_GPIO);gpio_output_options_set(Z_ST7735S_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,Z_ST7735S_DC_GPIO);Z_ST7735S_SetRST(0);delay_ms(1);Z_ST7735S_SetRST(1);delay_ms(120);// 厂家提供的固定的初始化代码Z_ST7735S_SendCommand(0x11); // Sleep outdelay_ms(120);               // Delay 120ms//------------------------------------ST7735S Frame Rate-----------------------------------------//Z_ST7735S_SendCommand(0xB1);Z_ST7735S_SendData(0x05);Z_ST7735S_SendData(0x3C);Z_ST7735S_SendData(0x3C);Z_ST7735S_SendCommand(0xB2);Z_ST7735S_SendData(0x05);Z_ST7735S_SendData(0x3C);Z_ST7735S_SendData(0x3C);Z_ST7735S_SendCommand(0xB3);Z_ST7735S_SendData(0x05);Z_ST7735S_SendData(0x3C);Z_ST7735S_SendData(0x3C);Z_ST7735S_SendData(0x05);Z_ST7735S_SendData(0x3C);Z_ST7735S_SendData(0x3C);//------------------------------------End ST7735S Frame Rate---------------------------------//Z_ST7735S_SendCommand(0xB4); // Dot inversionZ_ST7735S_SendData(0x03);//------------------------------------ST7735S Power Sequence---------------------------------//Z_ST7735S_SendCommand(0xC0);Z_ST7735S_SendData(0x28);Z_ST7735S_SendData(0x08);Z_ST7735S_SendData(0x04);Z_ST7735S_SendCommand(0xC1);Z_ST7735S_SendData(0XC0);Z_ST7735S_SendCommand(0xC2);Z_ST7735S_SendData(0x0D);Z_ST7735S_SendData(0x00);Z_ST7735S_SendCommand(0xC3);Z_ST7735S_SendData(0x8D);Z_ST7735S_SendData(0x2A);Z_ST7735S_SendCommand(0xC4);Z_ST7735S_SendData(0x8D);Z_ST7735S_SendData(0xEE);//---------------------------------End ST7735S Power Sequence-------------------------------------//Z_ST7735S_SendCommand(0xC5); // VCOMZ_ST7735S_SendData(0x1A);Z_ST7735S_SendCommand(0x36); // MX, MY, RGB modeZ_ST7735S_SendData(0xC0);//------------------------------------ST7735S Gamma Sequence---------------------------------//Z_ST7735S_SendCommand(0xE0);Z_ST7735S_SendData(0x04);Z_ST7735S_SendData(0x22);Z_ST7735S_SendData(0x07);Z_ST7735S_SendData(0x0A);Z_ST7735S_SendData(0x2E);Z_ST7735S_SendData(0x30);Z_ST7735S_SendData(0x25);Z_ST7735S_SendData(0x2A);Z_ST7735S_SendData(0x28);Z_ST7735S_SendData(0x26);Z_ST7735S_SendData(0x2E);Z_ST7735S_SendData(0x3A);Z_ST7735S_SendData(0x00);Z_ST7735S_SendData(0x01);Z_ST7735S_SendData(0x03);Z_ST7735S_SendData(0x13);Z_ST7735S_SendCommand(0xE1);Z_ST7735S_SendData(0x04);Z_ST7735S_SendData(0x16);Z_ST7735S_SendData(0x06);Z_ST7735S_SendData(0x0D);Z_ST7735S_SendData(0x2D);Z_ST7735S_SendData(0x26);Z_ST7735S_SendData(0x23);Z_ST7735S_SendData(0x27);Z_ST7735S_SendData(0x27);Z_ST7735S_SendData(0x25);Z_ST7735S_SendData(0x2D);Z_ST7735S_SendData(0x3B);Z_ST7735S_SendData(0x00);Z_ST7735S_SendData(0x01);Z_ST7735S_SendData(0x04);Z_ST7735S_SendData(0x13);//------------------------------------End ST7735S Gamma Sequence-----------------------------//Z_ST7735S_SendCommand(0x3A); // 65k modeZ_ST7735S_SendData(0x05);Z_ST7735S_SendCommand(0x29); // Display on
}// 指定范围
void Z_ST7735S_SpecifyScope(uint8_t xs, uint8_t xe, uint8_t ys, uint8_t ye)
{Z_ST7735S_SendCommand(0x2A); // 指定列范围Z_ST7735S_SendData(0x00);Z_ST7735S_SendData(xs);Z_ST7735S_SendData(0x00);Z_ST7735S_SendData(xe);Z_ST7735S_SendCommand(0x2B); // 指定行范围Z_ST7735S_SendData(0x00);Z_ST7735S_SendData(ys);Z_ST7735S_SendData(0x00);Z_ST7735S_SendData(ye);Z_ST7735S_SendCommand(0x2C); // 开始内存写入
}//将整个屏幕都填充上相同的颜色
void Z_ST7735S_RefreshAll(uint16_t rgb)
{Z_ST7735S_SpecifyScope(0, Z_ST7735S_WIDTH, 0, Z_ST7735S_HIGH);for (uint16_t j = 0; j < Z_ST7735S_HIGH; ++j){for (uint16_t i = 0; i < Z_ST7735S_WIDTH; ++i){Z_ST7735S_Send16bitsRGB(rgb);}}
}//将指定区域的屏幕填充上相同的颜色
void Z_ST7735S_RefreshArea(uint8_t start_x,uint8_t end_x,uint8_t start_y,uint8_t end_y,uint16_t rgb){if(start_x>Z_ST7735S_WIDTH||start_y>Z_ST7735S_HIGH||end_x>Z_ST7735S_WIDTH||end_y>Z_ST7735S_HIGH)    return ;Z_ST7735S_SpecifyScope(start_x,end_x,start_y,end_y);for (uint16_t j = start_y; j <= end_y; ++j){for (uint16_t i = start_x; i <= end_x; ++i){Z_ST7735S_Send16bitsRGB(rgb);}}
}//将指定区域填充上颜色数组(可以不同)
void Z_ST7735S_DrawArea(uint8_t start_x,uint8_t end_x,uint8_t start_y,uint8_t end_y,uint16_t* rgb){if(start_x>Z_ST7735S_WIDTH||start_y>Z_ST7735S_HIGH||end_x>Z_ST7735S_WIDTH||end_y>Z_ST7735S_HIGH)    return ;Z_ST7735S_SpecifyScope(start_x,end_x,start_y,end_y);for (uint16_t j = start_y; j <= end_y; ++j){for (uint16_t i = start_x; i <= end_x; ++i){Z_ST7735S_Send16bitsRGB(*rgb);rgb++;}}
}//const unsigned char number[10][10] = {
//    {0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00}, /*"0",0*/
//    {0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00}, /*"1",1*/
//    {0x00, 0x00, 0x3C, 0x42, 0x02, 0x0C, 0x10, 0x20, 0x7E, 0x00}, /*"2",2*/
//    {0x00, 0x00, 0x3C, 0x46, 0x04, 0x0C, 0x02, 0x42, 0x3C, 0x00}, /*"3",3*/
//    {0x00, 0x00, 0x0C, 0x14, 0x24, 0x44, 0x7C, 0x04, 0x0C, 0x00}, /*"4",4*/
//    {0x00, 0x00, 0x3E, 0x40, 0x58, 0x66, 0x02, 0x42, 0x3C, 0x00}, /*"5",5*/
//    {0x00, 0x00, 0x3C, 0x40, 0x58, 0x66, 0x42, 0x42, 0x3C, 0x00}, /*"6",6*/
//    {0x00, 0x00, 0x7E, 0x44, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00}, /*"7",7*/
//    {0x00, 0x00, 0x3C, 0x42, 0x62, 0x3C, 0x42, 0x42, 0x3C, 0x00}, /*"8",8*/
//    {0x00, 0x00, 0x3C, 0x42, 0x42, 0x66, 0x1A, 0x04, 0x78, 0x00}, /*"9",9*/
//};//void Z_ST7735S_ShowChar(uint8_t x, uint8_t y, uint8_t ch, uint16_t rgb)
//{
//    if (ch >= 10)
//        return;
//    Z_ST7735S_SpecifyScope(x, x + 7, y, y + 9);
//    for (uint8_t i = 0; i < 10; ++i)
//    {
//        uint8_t temp = number[ch][i];
//        for (uint8_t j = 0; j < 8; ++j)
//        {
//            if ((temp & 0x80) != 0)
//                Z_ST7735S_Send16bitsRGB(rgb);
//            else
//                Z_ST7735S_Send16bitsRGB(0x0000);
//            temp <<= 1;
//        }
//    }
//}

接下来小小演示一下。

#include "board.h"
#include "Z_TFT.h"int main(void){board_init();Z_ST7735S_Init();while (1){for(uint16_t i=0;i<0xFFFF;i+=50){Z_ST7735S_RefreshAll(i);delay_ms(20);}}
}

board.h是立创开发板提供的模板,board_init里面是进行一些初始化。

然后我把上面ST7735S的驱动代码封装成Z_TFT.h了,这个代码就是每隔20ms刷新一次屏幕,就是看看能不能正常驱动屏幕的。

可以看的出来是可以正常驱动的。

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

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

相关文章

攻防世界maze做法(迷宫题)

首先查壳64bit&#xff0c;直接丢进ida64中进行反编译就完事儿了&#xff0c;然后直接进入main函数打注释分析首先&#xff0c;题目已经提示了这是个迷宫题&#xff0c;我们抓住做迷宫题的两个要点&#xff0c;一找玩法&#xff0c;二找地图&#xff0c; 玩法在主函数中&#…

Linux防火墙入门——iptables、firewalld配置详解

合理的防火墙是你的计算机防止网络入侵的第一道屏障。你在家里上网&#xff0c;通常互联网服务提供会在路由中搭建一层防火墙。当你离开家时&#xff0c;那么你计算机上的那层防火墙就是仅有的一层&#xff0c;所以配置和控制好你 Linux 电脑上的防火墙很重要。 很多 Linux 发…

微信视频号上是怎么开店铺的?从入驻到发货,具体流程来了!

这两年&#xff0c;视频号逐渐走入大家视野 单价高&#xff0c;商家又少&#xff0c;很多类目都属于空白无商家入驻阶段&#xff0c;于是好多商家&#xff0c;都准备去视频号小店这个新“黑马”发展发展 那视频号是怎么开店卖东西的&#xff1f;今天我就来给大家分享一下&…

外汇天眼:总是权衡利弊,投资注定失败

投资股票的人往往会频繁地评估自己的投资结果&#xff0c;尤其是在信息时代&#xff0c;手机上随时可以查看股票行情&#xff0c;导致很多人时不时地打开行情软件&#xff0c;看一看自己的股票是涨了还是跌了&#xff0c;盈利了还是亏损了。 频繁评估结果的弊端 一、引发急躁…

导入和使用标准模块

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;自带了很多实用的模块&#xff0c;称为标准模块&#xff08;也可以称为标准库&#xff09;&#xff0c;对于标准模块&#xf…

每日一练——分糖果2

1103. 分糖果 II - 力扣&#xff08;LeetCode&#xff09; /*** Note: The returned array must be malloced, assume caller calls free().*/ int* distributeCandies(int candies, int num_people, int* returnSize) {int num 0;int* arr (int*)malloc(sizeof(int)*num_peo…

学习小心意——简单的循坏语句

for循坏 基本语法格式 for 变量 in 序列:代码块 示例代码如下 for i in range(10):print(i)#输出结果:0 1 2 3 4 5 6 7 8 9 简单案例代码如下 利用for语句遍历序列 # 遍历字符串打印每个字母 for letter in "python":print(letter)# 遍历列表并打印每个元素 a …

软件功能测试内容简析,第三方软件测试机构进行功能测试的好处

软件功能测试是指对软件产品的各项功能进行验证和确认的过程。它是软件开发过程中非常重要的一环&#xff0c;通过对软件的功能进行全面测试&#xff0c;可以确保软件在交付给用户之前达到预期的质量要求。 在进行功能测试时&#xff0c;需要包括以下几个方面的测试内容&#…

索尼CEO宣布全力推进AI电影制作,《蜘蛛侠》制片人坚称不用AI

原标题&#xff1a;索尼互娱制片人与CEO唱反调 易采游戏网6月3日消息&#xff1a;在最近的一次行业会议上&#xff0c;索尼影业高层首席执行官托尼文西奎拉向媒体透露&#xff0c;索尼正在全力推进人工智能(AI)技术的研发与应用&#xff0c;特别是在电影制作流程中。这一策略旨…

React@16.x(17)Portals

目录 1&#xff0c;使用2&#xff0c;事件冒泡 一句话总结&#xff1a;和 Vue3 的 Teleport 一个效果。 1&#xff0c;使用 import React, { PureComponent } from "react"; import ReactDOM from "react-dom";// 返回一个 React 元素&#xff08;ReactNo…

如何快速的将Excel定义的表结构变成MySQL的建表语句

如何快速的将Excel定义的表结构变成MySQL的建表语句 最近需求有点多啊&#xff0c;做一个小需求就有一堆表结构&#xff0c;一个一个实行CV大法&#xff0c;实在太伤身体了&#xff0c;有没有能够快速便捷的方法将一大堆Excel表转换成MySQL的表结构建表语句呢&#xff0c;网上…

Kafka之Consumer原理

1. Kafka消息消费流程 kafka的消费流程&#xff0c;首先是producer生产消息经过处理后放入到Broker服务器中&#xff0c;然后进入到内存中&#xff0c;内存再进行刷盘到磁盘中&#xff0c;kafak提供了两种刷盘策略&#xff0c;同步刷盘(flush.message 一次IO刷盘多少消息)和异…

音频pop音的数学与物理解释

音频数据跳变太大的时候通常会有pop音&#xff0c;此时频谱上看pop音位置能量较高 音频中的“pop”音通常是由于信号的不连续性或瞬态变化造成的。这种不连续性的数学和物理原因可以从以下几个方面解释&#xff1a; 数学解释 信号不连续性 当音频信号发生突变时&#xff0c;…

jdk的组成和跨平台原理

为什么 1.笔试会用到 2. 方便理解程序的运行 java跨平台的原因&#xff1a; sun公司提供了各种平台可以使用的jvm,所以java将程序一次编译成字节码之后可以给各种平台运行。这也是java这么多年深受欢迎的原因

c++ lambda学习

一. 书写形式 [ capture clause ] (parameters) -> return-type { definition of method } [ 捕获 ] ( 参数列表 ) -> 返回类型 { 函数定义 } return-type返回值一般可以推导出来, 可以不用写, 所以可以简化为 [ capture clause ] (parameters) { definition of meth…

循环购模式!增加用户复购的不二之选!

大家好&#xff0c;我是吴军&#xff0c;来自一家专注于软件开发与商业模式设计的公司。我们主要业务是构建商城系统&#xff0c;并为各类企业提供全面的商业模式解决方案。目前&#xff0c;我们已经成功开发了超过200种独特的商业模式&#xff0c;帮助许多企业实现了他们的商业…

TCP协议的核心机制

TCP协议的核心机制 一:确认应答机制1.2:超时重传接收缓冲区 超时重传时间重置连接 一:确认应答机制 对于TCP协议来说,要解决的一个很重要的问题,就是可靠传输 可靠传输,不是指发送方能够100%的把数据发送给接收方,而是尽可能. 尤其是让发送方知道,接收方是否收到. 举个例子: …

详解:重庆耶非凡的选品师项目有哪些优势?

在竞争激烈的电商市场中&#xff0c;重庆耶非凡科技有限公司凭借其独特的选品师项目&#xff0c;成功地在众多企业中脱颖而出。这一项目不仅体现了公司对市场趋势的敏锐洞察力&#xff0c;更彰显了其专业的选品能力和对消费者需求的深刻理解。 首先&#xff0c;耶非凡的选品师项…

大模型时代的具身智能系列专题(七)

北大王鹤团队 王鹤&#xff0c;北京大学前沿计算研究中心助理教授&#xff0c;本科毕业于清华大学&#xff0c;博士毕业于斯坦福大学&#xff0c;师从美国三院院士Leonidas. J Guibas教授。他创立并领导了具身感知与交互实验室(EPIC Lab)&#xff0c;实验室立足三维视觉感知与…

MyBatis的各种查询功能

1、查询&#xff1a; 查询的标签select必须设置属性resultType或resultMap&#xff0c;用于设置实体类和数据库表的映射关系 resultType&#xff1a;自动映射&#xff0c;用于属性名和表中字段名一致的情况 resultMap&#xff1a;自定义映射&#xff0c;用于一对多或多对一或…