STM32---SPI通信协议(小白入、含源码)

写在前面:在单片机的学习过程中,各种通信协议的学习是必不可少的,在前面我们学习了串口通信、IIC通信,本节我们来认识一下SPI通信协议。包括其SPI基本概念、NORFLASH芯片的介绍以及相关的例程实验。

目录

一、SPI介绍

1.1什么是SPI?

1.2SPI结构框图

1.3SPI工作模式

 1.4SPI工作寄存器

二、NORFLASH介绍

2.1NOR FLASH简介

2.2NM25Q128简介

2.3NOR FLASH的工作时序

 三、硬件设计

四、程序设计

4.1SPI配置步骤

4.2NM25Q128配置步骤 

4.3相关代码

五、现象

一、SPI介绍

1.1什么是SPI?

        SPI全称为: Serial Peripheral interface;其中文翻译为:串行外设设备接口,是一种高速的、全双工的、同步的通信总线;

        我们前面学习了IIC通信,STM32---IIC通信协议(含源码,小白进)_stm32 iic-CSDN博客再此,将SPI同IIC做出对比:

SPIIIC
通信方式

同步、串行、全双工

同步、串行、半双工
总线接口MOSI、MISO、SCL、CSSDA、SCL
拓扑结构一主多从、一主一从多主从
从机选择片选引脚SDA设备地址片选
通信速率一般500MHz以下100KHz、400KHz、3.4MHz
数据格式8/16位8位
传输顺序MSB/LSBMSB

1.2SPI结构框图

相关引脚:

 MOSI:输出数据线;

 MISO:输入数据线;

 SCK:时钟线,由主设备产生。

 NSS/CS:从设备片选信号,由主设备产生。

STM32F103引脚对应SPI:

引脚SPI1SPI2SPI3
NSSPA4PB12PA15
CLKPA5PB13PB3
MISOPA6PB14PB4
MOSIPA7PB15PB5

SPI工作原理:

        在从机与主机内部都含有一个移位寄存器,主机通过它的SPI串行寄存器写入一个字节来发起一次传输。串行移位寄存器通过MOSI将字节按位进行传输给从机,从机也将自己的串行移位寄存器的内容通过MISO信号线返回给主机。这样,两个移位寄存器中的内容就能够发生交换。

        外设的写与读操作时同步进行的,如果只是写操作,主机可以忽略接受到的数据;如果只是读操作,则需要发送一个空字节引发进行从机传输。   

 SPI具有三种传输方式:全双工、半双工以及单工;

全双工通信,就是在任何时刻,主机与从机之间都可以同时进行数据的发送和接收。
单工通信,就是在同一时刻,只有一个传输的方向,发送或者是接收。
半双工通信,就是在同一时刻,只能为一个方向传输数据 。

1.3SPI工作模式

        在前面学习IIC通信时,STM32与具有IIC接口的设备进行通信时,必须遵循IIC的通信协议。那同理我们使用SPI接口进行通信时,也需要遵循对应的通信协议,也就是对应的读与写时序。SPI通信协议具有4种工作模式。

        首先,在学习4种工作模式之前,先了解两个概念:时钟极性(CPOL)与时钟相位(CPHA);

时钟极性:是指当主机没有数据传输时即空闲状态下,SCL线的电平状态;若空闲状态为高电平 ,CPOL为1;若空闲状态为低电平,则CPOL为0;

时钟相位:在同步通信时,数据的采集与变化都是在时钟边沿进行的,也称为边沿协议(了解边沿协议与电平协议的区别),那每个时钟周期具有两个边沿,分别为上升沿与下降沿,那么数据的变化与采样就安排在两个不同的边沿,由于数据的产生和采样需要一定的时间,那么如果我们在第一个边沿把数据输出了,从机只能在第二个边沿进行采样。

CPHA的实质是指:采样时刻,如果CPHA=0就表示采样是从第一个边沿信号进行采样的;如果是CPHA=1,则表示采样是在第2个边沿信号进行的。

        由于CPOL与CPHA都有两种状态,所以SPI分为4中工作模式:

SPI工作模式CPOLCPHASCL空闲状态采样边沿采样时刻
000低电平上升沿奇数边沿
101低电平下降沿偶数边沿
210高电平下降沿奇数边沿
311高电平上升沿偶数边沿

工作模式1时序图:

工作模式2时序图:

工作模式3时序图:

工作模式4时序图:

 1.4SPI工作寄存器

 在使用SPI时,我们所涉及的相关寄存器主要包括:

SPI_CR1(SPI控制寄存器):用于配置SPI工作参数;

SPI_SR(SPI状态寄存器):用于查询当前SPI传输状态;

SPI_DR(SPI数据寄存器):用于存放待发送的数据或者是接受到的数据;

1.SPI_CR1控制寄存器

CPHA:时钟相位——1;SCL空闲时刻为高电平;

CPOL:时钟极性——1;采样时刻为偶数边沿;

MSTR:主从设备选择——1;设置为主设备;

BR:波特率控制——111;速度设置为最低;

SPE:SPI使能——1;开启SPI设备;

LSBFIRST:帧格式——0;MSB先传输,高位在前,低位在后;

SMM:软件从设备管理——1:软件片选从设备;

RXONLY:只接受——0;全双工通信;

DFF:数据帧格式——0;采用8位数据帧格式;

2.SPI_SR状态寄存器

 该寄存器的主要作用:用于查询SPI状态,TXE与RXNE即发送完成和接收完成是否标记;

3.SPI数据寄存器

        该寄存器为SPI的数据寄存器,是一个双寄存器,包括了发送缓存与接受缓存。

二、NORFLASH介绍

2.1NOR FLASH简介

        FLASH是一种常见的用于存储数据的半导体器件,特点:容量大、可重复擦写、按“扇区/块”擦除、掉点后数据继续保存;分类:NOR FLASH与NAND FLASH;

特性NOR FLASHNAND FLASH
容量较小较大
成本较贵较便宜
擦除单元按扇区/块擦除按扇区/块擦除
读取速度较高较低
读写单元基于字节读写基于块读写
写入速度较低较高
集成度较低较高
介质类型随机存储连续存储
地址线与数据线独立分开公用
坏块较少较多
是否支持XIP支持不支持

NOR与NAND在数据写入之前都需要进行擦除操作

NOR FLASH的物理特性:只能由1写为0,不能由0写为1;所以写之前需要进行擦除,即使只写一个字节,也需要对整个扇区/块进行擦除;

NAND FLASH 对于由1写为0,由0写为1都需要进行擦除,此处不详细说明;

缺陷:FLASH也有对应的缺点:寿命短以及位翻转;

寿命短:FLASH的擦除次数是有限(10万次左右),当接近时,可能会出现写操作失败;

位翻转:数据位写入时为 1,但经过一定时间的环境变化后可能实际变为 0 的情况。

NOR FLASH芯片具有多种:W25Q128、BY25Q128、NM25Q128等等,内存都是128M即16M字节,他们的很多参数、操作都是一样的。其实验也是兼容;

2.2NM25Q128简介

NM25Q128是一款大容量的SPIFLASH产品,其容量为16M,它将16M字节的容量分为256块,每个块大小为64K字节,每个块又分为16个扇区,每个扇区16页,每页256个字节,即每个扇区4K字节。NM25Q128的最小擦除单位为扇区,也就是每次最少擦出4K字节。

         NM25Q128 的擦写周期多达 10W 次,具有 20 年的数据保存期限,支持电压为 2.7~3.6V,NM25Q128 支持标准的 SPI,还支持双输出/四输出的 SPI,最大 SPI 时钟可以到 104Mhz(双输
出时相当于 208Mhz,四输出时相当于 416Mhz)。其主要工作在SPI的模式0和模式3;

 引脚连接:

CS:片选信号输入,低电平有效;

DO:MISO数据输出信号线;

WP:写保护——高电平可读可写,低电平仅仅可读;

HOLD:保持管脚,低电平有效;

CLK:时钟输入;

DI:MOSI数据输入信号线;

2.3NOR FLASH的工作时序

在介绍工作时序之前,我们需要先对基本操作的指令做出了解:

0x06:写使能,写数据与擦除之前,必须先发送该指令;

0x05:读SR1,判断FLASH是否处于空闲状态,擦除用;

0x03:读数据,用于读取NOR FLASH;

0x02:页写:用于写入NOR FLASH;

0x20:扇区擦除:用于扇区擦除指令;

1.读时序

2.写时序 

3.擦除扇区 

 三、硬件设计

实现功能:

        通过KEY0按键控制NOR FLASH的写入,通过控制KEY1按键控制NOR  FLASH的读取,并将读取到的的数据通过串口显示调试助手。

原理图:

由上图可知:NM25Q128的引脚:

        CS--PB12; CLK--PB13;MISO--PB14;MOSI--PB15;

四、程序设计

4.1SPI配置步骤

1、SPI工作参数配置以及初始化

        包括:工作模式、时钟极性、时钟相位;

        涉及的函数HAL_SPI_Init();

2、使能SPI时钟和初始化相关引脚

        包括:时钟配置、GPIO模式配置;

        涉及的函数HAL_SPIMspinit();

3、使能SPI

    涉及的宏定义:  __HAL_SPI_ENABLE(__HANDLE__) 实际操作位CR1控制寄存器中的位6SPE;

4、数据的传输

        通过 HAL_SPI_Transmit 函数进行发送数据。
        通过 HAL_SPI_Receive 函数进行接收数据。
        也可以通过 HAL_SPI_TransmitReceive 函数进行发送与接收操作。

5、设置SPI传输速度

        SPI 初始化结构体 SPI_InitTypeDef 有一个成员变量是 BaudRatePrescaler,该成员变量用来设置 SPI 的预分频系数,从而决定了 SPI 的传输速度。但是 HAL 库并没有提供单独的 SPI 分频系数修改函数,如果我们需要在程序中偶尔修改速度,那么我们就要通过设置 SPI_CR1 寄存器来修改。

4.2NM25Q128配置步骤 

        在前面我们已经对于SPI通信所需要的协议都已经封装好了,接着我们只需要在SPI通信的基础上,通过对NM24Q128的工作时序进行拟定即可。

1、初始化片选引脚与SPI接口

        包括相关GPIO初始化与SPI初始化;

2、NM24Q128读取

        包括读时序。

3、NM24Q128扇区擦除

        包括等待函数。

4、NM24Q128写入

        包括:是否需要擦除、是否需要换页、遵循读、改、写。

4.3相关代码

程序源码:

链接:https://pan.baidu.com/s/1Mzfl_LS1ou4BmAbxX11hxA 
提取码:1022

spi.c

#include "./BSP/SPI/spi.h"

SPI_HandleTypeDef spi_handle;
void spi_init(void)
{
   spi_handle.Instance=SPI2;    // 基地址;
   spi_handle.Init.Mode=SPI_MODE_MASTER;    //模式:主从模式,主模式(SPI_MODE_MASTER),从模式(SPI_MODE_SLAVE);
   spi_handle.Init.Direction=SPI_DIRECTION_2LINES;  //方式:1、只接受模式;2、单线双向通信数据模式;3、全双工模式;    
   spi_handle.Init.DataSize=SPI_DATASIZE_8BIT;   //数据帧格式:8位/16位;
   spi_handle.Init.CLKPolarity=SPI_POLARITY_HIGH;   //时钟极性;
   spi_handle.Init.CLKPhase=SPI_PHASE_2EDGE;    //时钟相位;
   spi_handle.Init.NSS = SPI_NSS_SOFT;  //SS信号由硬件还是软件控制;
   spi_handle.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256; //设置SPI波特率预分频;
   spi_handle.Init.FirstBit=SPI_FIRSTBIT_MSB;   //起始位是MSB还是LSB;
   spi_handle.Init.TIMode=SPI_TIMODE_DISABLE;   //帧格式 SPImotorla模式还是TI模式;
   spi_handle.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE; //硬件CRC是否使能;
   spi_handle.Init.CRCPolynomial=7; //CRC多项式;
     HAL_SPI_Init(&spi_handle); //初始化;
     __HAL_SPI_ENABLE(&spi_handle);//使能SPI2
}
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) 
{
        __HAL_RCC_SPI2_CLK_ENABLE();//使能SPI2时钟;
        __HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟;
    
        GPIO_InitTypeDef gpio_init_struct;
    
        gpio_init_struct.Mode=GPIO_MODE_AF_PP;//复用推挽输出;
        gpio_init_struct.Pull=GPIO_PULLUP;//上拉;
        gpio_init_struct.Pin=GPIO_PIN_13 |GPIO_PIN_14 |GPIO_PIN_15;//引脚;
        gpio_init_struct.Speed=GPIO_SPEED_FREQ_HIGH ;//高速;
        HAL_GPIO_Init(GPIOB, &gpio_init_struct);     
}

uint8_t spi_readwrite_byte(uint8_t txdata)
{
    uint8_t rxdata;
    HAL_SPI_TransmitReceive(&spi_handle, &txdata, &rxdata, 1,  1000);
    return rxdata;
}

key.c

#include "./BSP/KEY1/key.h"

void key_init(void)
{ 
   GPIO_InitTypeDef  gpio_init_struct;
    
    __HAL_RCC_GPIOE_CLK_ENABLE();
    gpio_init_struct.Pin=GPIO_PIN_4;
    gpio_init_struct.Mode=GPIO_MODE_INPUT;
    gpio_init_struct.Pull=GPIO_PULLUP; 
    HAL_GPIO_Init(GPIOE,&gpio_init_struct);
    
    __HAL_RCC_GPIOE_CLK_ENABLE();
    gpio_init_struct.Pin=GPIO_PIN_3;
    gpio_init_struct.Mode=GPIO_MODE_INPUT;
    gpio_init_struct.Pull=GPIO_PULLUP; 
    HAL_GPIO_Init(GPIOE,&gpio_init_struct);
}

uint32_t key_scan()
{
    if( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)   
    {
        delay_ms(10);
        if( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)
        {
            while( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0);
            return 1;
        }  
    }    
    return 0;    
}
uint32_t key_scan1()
{
    if( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)   
    {
        delay_ms(10);
        if( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)
        {
            while( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0);
            return 2;
        }     
    }    
    return 0;    
} 
   

nm24q128.c

#include "./BSP/SPI/nm25q128.h"

void norflash_init(void)
{
     __HAL_RCC_GPIOB_CLK_ENABLE();/*片选引脚时钟*/
    GPIO_InitTypeDef gpiob_init_struct;
    gpiob_init_struct.Mode=GPIO_MODE_OUTPUT_PP;
    gpiob_init_struct.Pin=GPIO_PIN_12;
    gpiob_init_struct.Speed= GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &gpiob_init_struct);/*片选引脚初始化*/
    spi_init();/*SPI初始化*/
    spi_readwrite_byte(0Xff);//清空数据寄存器DR作用;
    NORFLASH_CS(1); /*拉高片选*/
}

uint8_t nm25q128_read_data(uint32_t address)
{
    uint8_t data=0;
    NORFLASH_CS(0);/*拉低片选*/
    
    /*1、发送读命令*/
    spi_readwrite_byte(0X03);
    
    /*2、发送地址,分三次发送,高位在前*/
    spi_readwrite_byte(address >> 16);
    spi_readwrite_byte(address >> 8);
    spi_readwrite_byte(address);
    
    /*3、读取数据*/
    data = spi_readwrite_byte(0xff);
    
    NORFLASH_CS(1);/*拉高片选*/
    return data;

}
uint8_t  norflash_wait(void)
{
    uint8_t rec_data=0;
    NORFLASH_CS(0);/*拉低片选*/
    spi_readwrite_byte(0X05);
    rec_data=spi_readwrite_byte(0Xff);
    NORFLASH_CS(1);/*拉高片选*/
    return  rec_data;
}

void norflash_erase_sector(uint32_t addr)
{
   
    /*1、写使能*/
    NORFLASH_CS(0);
    spi_readwrite_byte(0X06);
    NORFLASH_CS(1);/*拉高片选*/
    
    /*2、等待空闲*/
    while(norflash_wait() & 0x01) ;
    
    /*3、发送擦除扇区命令*/
     NORFLASH_CS(0);/*拉低片选*/
    spi_readwrite_byte(0X20);
    
     /*4、发送地址*/
    spi_readwrite_byte(addr >> 16);
    spi_readwrite_byte(addr >> 8);
    spi_readwrite_byte(addr);
     NORFLASH_CS(1);/*拉高片选*/
    
     /*5、等待空闲*/
    while(norflash_wait() & 0x01);
    

}

void norflash_write_page(uint8_t data,uint32_t addre)
{
    /*1、擦除扇区*/
    norflash_erase_sector(addre);
    
    /*2、写使能*/
    NORFLASH_CS(0);/*拉低片选*/
    spi_readwrite_byte(0X06);
    NORFLASH_CS(1);/*拉高片选*/
    
    /*3、页写使能*/
    NORFLASH_CS(0);/*拉低片选*/
    spi_readwrite_byte(0X02);
    
    
    /*4、发送地址,分三次发送,高位在前*/
    spi_readwrite_byte(addre >> 16);
    spi_readwrite_byte(addre >> 8);
    spi_readwrite_byte(addre);
    
    spi_readwrite_byte(data);
    
     NORFLASH_CS(1);/*拉高片选*/
      
     while(norflash_wait() & 0x01);
}

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/SPI/nm25q128.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY1/key.h"
    uint8_t data=0;
int main(void)
{
    HAL_Init();                              /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);      /* 设置时钟, 72Mhz */
    delay_init(72);                          /* 延时初始化 */
    LED_init();                              /* LED初始化 */
    usart_init(115200);                      /* 串口初始化 */
    key_init();                              /* 按键初始化 */
    norflash_init();                         /* NOR FLASH初始化 */
    while(1)
    { 
        if(key_scan()==1)                    /* K0按键按下 */
        {
            norflash_write_page('A',0X223236);
            printf("write finish\r\n");
        }
        
        if(key_scan1()==2)                  /* K1按键按下 */
        {
         data=nm25q128_read_data(0X223236);
            printf("DATA:%c\n",data);
        }     

    }
}

五、现象

KEY0与KEY1分别按下。

         总结:本节我们介绍了SPI的基本概念、使用,以及NOR FLASH 的基本概念,完成了利用NM24Q128芯片通过SPI与STM32进行通信,实现了数据的读取。

                创作不易,还请大家多多点赞支持!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

socket--IP端口爆破域名解析

免责声明:本文仅做技术交流与学习... 目录 IP端口爆破 域名解析爆破 IP端口爆破 #端口扫描: #获取扫描的 IP和端口 #连接 IP和端口(socket) #判断连接状态-开放和关闭# import socket # # 加入参数模式 # import os # ssocket.socket() # s.connect((…

3.1、前端异步编程(超详细手写实现Promise;实现all、race、allSettled、any;async/await的使用)

前端异步编程规范 Promise介绍手写Promise(resolve,reject)手写Promise(then)Promise相关 API实现allraceallSettledany async/await和Promise的关系async/await的使用 Promise介绍 Promise是一个类,可以翻…

图像分割(三)-RGB转HSV后图像分割方法

常用彩色模型有RGB和HSV模型,有时候在RGB颜色空间进行背景分割比较困难的问题,转换为HSV模型然后对色调和饱和度图像进行处理会得到比较理想的处理结果,下面通过一个实例讲解该方法的MATLAB实现,该方法对其他图像检测也具有一定的参考价值。 …

python19 异常处理

python19 异常处理 代码 异常处理 result 0; try:num1 int(input(请输入一个整数:))num2 int(input(请输入一个整数:))result num1 / num2 except ZeroDivisionError:print(除数不能为0) except ValueError:print(不能将字符串转成整数) except BaseException:print(未知异…

【EndNote】EndNote进行文献管理可能遇到的问题和解决方案

一、安装GB/T7714-2015(numberic)文献style windows:https://blog.csdn.net/qq_36235935/article/details/115629694 mac os:Mac版Endnote 20导入中文参考格式Chinese Std GBT7714 (numeric)-CSDN博客 安装完之后需要调整Author Name格式:…

【ARMv8/ARMv9 硬件加速系列 3.3 -- SVE LD2D 和 ST2D 使用介绍】

文章目录 SVE 多向量操作LD2D(加载)LD2D 操作说明LD2D 使用举例ST2D(存储)ST2D 使用举例ST2D 存储示例代码ld2d 和 st2d 小结SVE 多向量操作 在ARMv8/9的SVE (Scalable Vector Extension) 指令集中,st2d和ld2d指令用于向量化的存储和加载操作,具体地,它们允许同时对两个…

【STM32入门学习】定时器与PWM的LED控制

目录 一、定时器与PWM介绍 1.1定时器 1.1.1定时器分类简介 1.1.2STM32定时器分类比较表 1.1.3定时器启动操作: 1.2 PWM 1.2.1 简介: 1.2.2PWM工作原理 1.2.3使用步骤: 二、定时器计数控制LED灯亮灭 2.1HAL库 2.1.1使用HAL库创建…

【背包题解】DP代表了走到阶段i 的所有路线的最优解

目录 1889:【提高】多重背包(2) 二维费用背包 2075 - 最大卡路里 1928 - 采购礼品 背包容量:(c) 6 重量 weight 2 2 4 6 2 1 2 3 4 5 价值 value 3 6 5 5 8 1 2 3 4 5 wvdp数组:记录有i件…

作业管理系统

摘 要 随着网络的发展,信息化时代的到来,在教学工作的过程中作用越来越明显,作业的及时发布,学生的及时提交,以及通过网上的批改和评分,都大大促进教学质量的发展,充分的利用网络来加强管理&am…

vue2动态横条图(横条图样式定时切换)

每次切换成新图后会清除定时器和图(重新加载,否则要么会重复加载定时器。清除定时器之后要先调用一次index为0的数据) 数据样例 acrossBarDatas:{data: ["80", "80"],sunffix: [单位, "单位"],title: "标…

可信启动Trusted Board Boot

TBB Trusted Board Boot(TBB)对所有固件镜像(包括普通世界的bootloader)进行身份验证,以防止恶意固件在平台上运行。TBB使用公钥加密标准 (PKCS)来建立信任链(Chain of Trust&#…

Log4j2异步打印可变对象的问题

现象 应用代码如下: Test test new Test();test.setA(1);test.setB("1");log.info("before modification: {} \t ",test);test.setA(2);test.setB("2");log.info("after modification: {} \t ",test);问题应用的日志控制…

怎么添加网页到桌面快捷方式?

推荐用过最棒的学习网站!https://offernow.cn 添加网页到桌面快捷方式? 很简单,仅需要两步,接下来以chrome浏览器为例。 第一步 在想要保存的网页右上角点击设置。 第二步 保存并分享-创建快捷方式,保存到桌面即可…

使用VisualBox+Vagrant搭建Centos虚拟机环境

1.下载并安装VisualBox; 2.下载并安装Vagrant; 3.打开cmd窗口,执行命令vagrant init centos/7,初始化centos环境,该步骤受网络带宽影响,可能挂级30分钟到1个小时; 4.启动虚拟机:vagrant up&…

C# yolov8 OpenVINO 同步、异步接口视频推理

C# yolov8 OpenVINO 同步、异步接口视频推理 目录 效果 项目 代码 下载 效果 同步推理效果 异步推理效果 项目 代码 using OpenCvSharp; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Windows.Form…

慢阻肺患者为何容易营养不良?朗格力教你轻松改善

#肺科营养#朗格力#班古营养#复合营养素#肺部营养#肺部健康# 慢阻肺是我国常见的、高患病率的慢性呼吸系统疾病,会对肺结构和功能产生影响,从而引起各种不良反应,其中营养不良是常见并发症之一。慢阻肺为什么会发生营养不良?营养不良又是怎么伤害慢阻肺的呢?为什么像班古精准…

鸿蒙 登录界面示例

1.b站登录界面 我的b站教学视频:https://www.bilibili.com/video/BV1LQgQexEGm/?spm_id_from333.999.0.0&vd_sourced0ea58f1127eed138a4ba5421c577eb1 最终实现效果: 需要准备2张图片,分别是向下和向右边的图标 代码: En…

(2024,Vision-RWKV,线性复杂度双向注意力,四向标记移位)通过类似 RWKV 的架构实现高效且可扩展的视觉感知

Vision-RWKV: Efficient and Scalable Visual Perception with RWKV-Like Architectures 公和众与号:EDPJ(进 Q 交流群:922230617 或加 VX:CV_EDPJ 进 V 交流群) 目录 0. 摘要 2. 特征聚合机制 3. Vision-RWKV 3.…

一问搞懂Linux信号【上】

Linux信号在Linux系统中的地位仅此于进程间通信,其重要程度不言而喻。本文我们将从信号产生,信号保存,信号处理三个方面来讲解信号。 🚩结合现实认识信号 在讲解信号产生之前,我们先做些预备的工作。 现实生活中信号…

2024.6最最新版MySQL数据库安装(保姆级教程,不懂你捶我)

1.MySQL数据库下载 1.打开MySQL官网 如下页面 2.下翻网页到最底部,找到Download,点击第一个MySQL Community Server 3.选择自己需要的版本以及系统的MySQL: 4.跳转页面会有一个登录/注册页面,这里我们不鸟他,直接开始下载 2.MySQL数据库安装 1.双击我们刚刚下载的安装包 2.勾…