STM32基础--位带操作
位带简介
位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见。51 单片机中通过关键字 sbit 来实现位定义,STM32 没有这样的关键字,而是通过访问位带别名区来实现。
在 STM32 中,有两个地方实现了位带,一个是 SRAM 区的最低 1MB 空间,另一个是外设区最低 1MB 空间。这两个 1MB 的空间除了可以像正常的 RAM 一样操作外,他们还有自己的位带别名区,位带别名区把这 1MB 的空间的每一个位膨胀成一个 32 位的字,当访问位带别名区的这些字时,就可以达到访问位带区某个比特位的目的。

外设位带区
外 设 外 带 区 的 地 址 为:0X40000000~0X40100000, 大 小 为1MB, 这1MB的 大 小 在103系 列 大/中/小 容 量 型 号 的 单 片 机 中 包 含 了 片 上 外 设 的 全 部 寄 存 器, 这 些 寄 存 器的 地 址 为:0X40000000~0X40029FFF。 外 设 位 带 区 经 过 膨 胀 后 的 位 带 别 名 区 地 址 为:0X42000000~0X43FFFFFF,这个地址仍然在 CM3 片上外设的地址空间中。在 103 系列大/中小容量型号的单片机里面,0X40030000~0X4FFFFFFF 属于保留地址,膨胀后的 32MB 位带别名区刚好就落到这个地址范围内,不会跟片上外设的其他寄存器地址重合。
STM32 的全部寄存器都可以通过访问位带别名区的方式来达到访问原始寄存器比特位的效果,这比 51 单片机强大很多。因为 51 单片机里面并不是所有的寄存器都是可以比特位操作,有些寄存器还是得字节操作,比如 SBUF。
虽然说全部寄存器都可以实现比特操作,但我们在实际项目中并不会这么做,甚至不会这么做。有时候为了特定的项目需要,比如需要频繁的操作很多 IO 口,这个时候我们可以考虑把 IO 相关的寄存器实现比特操作。
SRAM 位带区
SRAM 的位带区的地址为:0X2000 0000~X2010 0000,大小为 1MB,经过膨胀后的位带别名区地址为:0X2200 0000~0X23FF FFFF,大小为 32MB。操作 SRAM 的比特位这个用得很少。
位带区和位带别名区地址转换
位带区的一个比特位经过膨胀之后,虽然变大到 4 个字节,但是还是 LSB 才有效。有人会问这不是浪费空间吗,要知道 STM32 的系统总线是 32 位的,按照 4 个字节访问的时候是最快的,所以膨胀成 4 个字节来访问是最高效的。
我们可以通过指针的形式访问位带别名区地址从而达到操作位带区比特位的效果。那这两个地址直接如何转换,我们简单介绍一下。
外设位带别名区地址
对于片上外设位带区的某个比特,记它所在字节的地址为 A, 位序号为 n(0<=n<=31)(n 的范围根据具体寄存器能控制的位决定),则该比特在别名区的地址为:
AliasAddr = 0x42000000+ (A-0x40000000)*8*4 +n*4
0X42000000 是外设位带别名区的起始地址,0x40000000 是外设位带区的起始地址, (A-0x40000000)表示该比特前面有多少个字节,一个字节有 8 位,所以 *8,一个位膨胀后是 4 个字节,所以 *4,n 表示该比特在 A 地址的序号,因为一个位经过膨胀后是四个字节,所以也 *4。
SRAM 位带别名区地址
对于 SRAM 位带区的某个比特,记它所在字节的地址为 A, 位序号为 n(0<=n<=31)(n 的范围根据具体寄存器能控制的位决定),则该比特在别名区的地址为:
AliasAddr = 0x22000000+ (A-0x20000000)*8*4 +n*4
公式原理则与上面一样。
统一公式
为了方便操作,我们可以把这两个公式合并成一个公式,把“位带地址 + 位序号”转换成别名区地址统一成一个宏。
// 把“位带地址 + 位序号”转换成别名地址的宏
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))
addr & 0xF0000000 是为了区别 SRAM 还是外设,实际效果就是取出 4 或者 2,如果是外设,则取出的是 4,+0X02000000 之后就等于 0X42000000,0X42000000 是外设别名区的起始地址。如果是 SRAM,则取出的是 2,+0X02000000 之后就等于 0X22000000,0X22000000 是 SRAM 别名区的起始地址。
addr & 0x00FFFFFF 屏蔽了高三位,相当于减去 0X20000000 或者 0X40000000,但是为什么是屏蔽高三位?因为外设的最高地址是:0X20100000,跟起始地址 0X20000000 相减的时候,总是低5 位才有效,所以干脆就把高三位屏蔽掉来达到减去起始地址的效果,具体屏蔽掉多少位跟最高地址有关。SRAM 同理分析即可。«5 相当于 84,«2 相当于 *4,这两个我们在上面分析过。最后我们就可以通过指针的形式操作这些位带别名区地址,最终实现位带区的比特位操作。
// 把一个地址转换成一个指针
#define MEM_ADDR(addr) *((volatile unsigned long*)(addr))
// 把位带别名区地址转换成指针
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
GPIO 位带操作
外设的位带区,覆盖了全部的片上外设的寄存器,我们可以通过宏为每个寄存器的位都定义一个位带别名地址,从而实现位操作。但这个在实际项目中不是很现实,也很少人会这么做,我们在这里仅仅演示下 GPIO 中 ODR 和 IDR 这两个寄存器的位操作。
从手册中我们可以知道 ODR 和 IDR 这两个寄存器对应 GPIO 基址的偏移是 12 和 8,我们先实现这两个寄存器的地址映射,其中 GPIOx_BASE 在库函数里面有定义。
别忘了的事
添加bsp_led_bitbang.c文件和bsp_led_bitbang.h文件
别忘了添加文件的时候,在魔术棒的地方加路径。(加上bsp_led_bitbang.h存放的路径)
GPIO 寄存器映射(bsp_led_bitbang.h中)
// 这里只定义了 GPIO ODR和IDR这两个寄存器的位带别名区地址,其他寄存器的没有定义//SRAM 位带区: 0X2000 0000~0X2010 0000
//SRAM 位带别名区:0X2200 0000~0X23FF FFFF//外设 位带区: 0X4000 0000~0X4010 0000
//外设 位带别名区:0X4200 0000~0X43FF FFFF// 把“位带地址+位序号”转换成别名地址的宏
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))
/**addr & 0xF0000000,取地址的高4位,看看是2还是4,用于区分SRAM和外设地址,*如果是2,+0x02000000则=0X2200 0000,即是SRAM,如果是4,+0x02000000则=0X4200 0000,即是外设**addr & 0x000FFFFFF,屏蔽掉高两位,相当于-0X2000 0000或者-0X4000 0000,结果表示偏移位带区多少个字节*<<5 等于*8*4,因为位带区一个地址表示一个字节,一个字节有8个bit,一个bit可以膨胀成一个字,即4个字节*<<2 等于*4,因为一个位可以膨胀成一个字,即4个字节**分解成两条公式应该就是这样:*SRAM位带别名地址*AliasAddr= 0x22000000+((A-0x20000000)*8+n)*4 =0x22000000+ (A-0x20000000)*8*4 +n*4*外设位带别名地址*AliasAddr= 0x22000000+((A-0x20000000)*8+n)*4 =0x22000000+ (A-0x20000000)*8*4 +n*4*/// 把一个地址转换成一个指针
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) // 把位带别名区地址转换成指针
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) // GPIO ODR 和 IDR 寄存器地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
现在我们就可以用位操作的方法来控制 GPIO 的输入和输出了,其中宏参数 n 表示具体是哪一个IO 口,n(0,1,2⋯15)。这里面包含了端口 A~G ,并不是每个单片机型号都有这么多端口,使用这部分代码时,要查看你的单片机型号,如果是 64pin 的则最多只能使用到 C 端口。
GPIO 位操作(bsp_led_bitbang.h中)
// 单独操作 GPIO的某一个IO口,n(0,1,2...15),n表示具体是哪一个IO口
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
就是分别使用别名操作每个I/O口的ODR寄存器和IDR寄存器实现输入和输出。
GPIO测试(bsp_led_bitbang.c中)
有关 LED GPIO 初始化和软件延时等函数我们直接用(以前写过的bsp_led.c和bsp_key.c文件里面的函数),修改的是控制 GPIO 输出的部分改成了位操作。该实验我们让 按键控制IO 口输出高低电平来控制LED 的亮灭,负逻辑点亮。具体使用哪一个 IO 和点亮方式由硬件平台决定。
void Led_Bitbang_GPIO_Test(void)
{//LED灯初始化LED_GPIO_Config();//按键初始化Key_GPIO_Config();//红灯亮PBout(5) = 0;/* 轮询按键状态,若按键按下则反转 LED(还没学到DMA或者中断呢) */while(1){if(Key_Scan_Bitbang('A',0) == KEY_ON){/*LED1 开启 */PBout(5) = 0;}if(Key_Scan_Bitbang('C',13) == KEY_ON){/*LED1 关闭 */PBout(5) = 1;} } }
代码
bsp_led_bitbang.c
/*** ****************************************************************************** @file bsp_led_bitbang.c* @brief 使用位带操作点亮或者熄灭LED灯* @author (六千里)* @date 2024-03-09* @copyright 无* ******************************************************************************/#include "bsp_led_bitbang.h"/*** @brief检测是否有按键按下* @paramGPIOX: 具体的端口, GPIOX 可以是(A...G)* @paramGPIO_PIN: 具体的端口位, 可以是 x(x 可以是 0...15)* @retval 按键的状态* @arg KEY_ON: 按键按下* @arg KEY_OFF: 按键没按下
**/
static uint8_t Key_Scan_Bitbang(uint8_t GPIOX,uint8_t GPIO_Pin)
{switch (GPIOX) {case 'A': {/* 检测是否有按键按下 */if((PAin(GPIO_Pin)) == KEY_ON){//因为有硬件消抖,故不写软件消抖/* 等待按键释放 */while(PAin(GPIO_Pin) == KEY_ON); return KEY_ON;}else{return KEY_OFF;} }case 'B':{/* 检测是否有按键按下 */if((PBin(GPIO_Pin)) == KEY_ON){//因为有硬件消抖,故不写软件消抖/* 等待按键释放 */while(PBin(GPIO_Pin) == KEY_ON); return KEY_ON;}else{return KEY_OFF;} } case 'C':{/* 检测是否有按键按下 */if((PCin(GPIO_Pin)) == KEY_ON){//因为有硬件消抖,故不写软件消抖/* 等待按键释放 */while(PCin(GPIO_Pin) == KEY_ON); return KEY_ON;}else{return KEY_OFF;} } case 'D':{/* 检测是否有按键按下 */if((PDin(GPIO_Pin)) == KEY_ON){//因为有硬件消抖,故不写软件消抖/* 等待按键释放 */while(PDin(GPIO_Pin) == KEY_ON); return KEY_ON;}else{return KEY_OFF;} } case 'E':{/* 检测是否有按键按下 */if((PEin(GPIO_Pin)) == KEY_ON){//因为有硬件消抖,故不写软件消抖/* 等待按键释放 */while(PEin(GPIO_Pin) == KEY_ON); return KEY_ON;}else{return KEY_OFF;} } case 'F':{/* 检测是否有按键按下 */if((PFin(GPIO_Pin)) == KEY_ON){//因为有硬件消抖,故不写软件消抖/* 等待按键释放 */while(PFin(GPIO_Pin) == KEY_ON); return KEY_ON;}else{return KEY_OFF;} } case 'G':{/* 检测是否有按键按下 */if((PGin(GPIO_Pin)) == KEY_ON){//因为有硬件消抖,故不写软件消抖/* 等待按键释放 */while(PGin(GPIO_Pin) == KEY_ON); return KEY_ON;}else{return KEY_OFF;} } default: return KEY_OFF;}}void Led_Bitbang_GPIO_Test(void)
{//LED灯初始化LED_GPIO_Config();//按键初始化Key_GPIO_Config();//红灯亮PBout(5) = 0;/* 轮询按键状态,若按键按下则反转 LED(还没学到DMA或者中断呢) */while(1){if(Key_Scan_Bitbang('A',0) == KEY_ON){/*LED1 开启 */PBout(5) = 0;}if(Key_Scan_Bitbang('C',13) == KEY_ON){/*LED1 关闭 */PBout(5) = 1;} } }
bsp_led_bitbang.h
#ifndef __BSP_LED_BITBANG_H
#define __BSP_LED_BITBANG_H/*** ****************************************************************************** 包含的头文件* ******************************************************************************/
#include "bsp_led.h"
#include "bsp_key.h"/*** ****************************************************************************** 宏定义* ******************************************************************************/// 这里只定义了 GPIO ODR和IDR这两个寄存器的位带别名区地址,其他寄存器的没有定义//SRAM 位带区: 0X2000 0000~0X2010 0000
//SRAM 位带别名区:0X2200 0000~0X23FF FFFF//外设 位带区: 0X4000 0000~0X4010 0000
//外设 位带别名区:0X4200 0000~0X43FF FFFF// 把“位带地址+位序号”转换成别名地址的宏
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))
/**addr & 0xF0000000,取地址的高4位,看看是2还是4,用于区分SRAM和外设地址,*如果是2,+0x02000000则=0X2200 0000,即是SRAM,如果是4,+0x02000000则=0X4200 0000,即是外设**addr & 0x000FFFFFF,屏蔽掉高两位,相当于-0X2000 0000或者-0X4000 0000,结果表示偏移位带区多少个字节*<<5 等于*8*4,因为位带区一个地址表示一个字节,一个字节有8个bit,一个bit可以膨胀成一个字,即4个字节*<<2 等于*4,因为一个位可以膨胀成一个字,即4个字节**分解成两条公式应该就是这样:*SRAM位带别名地址*AliasAddr= 0x22000000+((A-0x20000000)*8+n)*4 =0x22000000+ (A-0x20000000)*8*4 +n*4*外设位带别名地址*AliasAddr= 0x22000000+((A-0x20000000)*8+n)*4 =0x22000000+ (A-0x20000000)*8*4 +n*4*/// 把一个地址转换成一个指针
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) // 把位带别名区地址转换成指针
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) // GPIO ODR 和 IDR 寄存器地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08 // 单独操作 GPIO的某一个IO口,n(0,1,2...15),n表示具体是哪一个IO口
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入 /*** ****************************************************************************** .c文件中包含的函数* ******************************************************************************/static uint8_t Key_Scan_Bitbang(uint8_t GPIOX,uint8_t GPIO_Pin);
void Led_Bitbang_GPIO_Test(void);
#endif /*__BSP_LED_BITBANG_H*/
stm32f10x_conf.h
/********************************************************************************* @file Project/STM32F10x_StdPeriph_Template/stm32f10x_conf.h * @author MCD Application Team* @version V3.5.0* @date 08-April-2011* @brief Library configuration file.******************************************************************************* @attention** THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.** <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>*******************************************************************************//* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_CONF_H
#define __STM32F10x_CONF_H/* Includes ------------------------------------------------------------------*/
/* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */
#include "stm32f10x_adc.h"
#include "stm32f10x_bkp.h"
#include "stm32f10x_can.h"
#include "stm32f10x_cec.h"
#include "stm32f10x_crc.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_dbgmcu.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_fsmc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_iwdg.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_sdio.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_wwdg.h"
#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
/***自己书写文件的头文件**/
#include "bsp_led.h"
#include "bsp_key.h"
#include "bsp_led_bitbang.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Uncomment the line below to expanse the "assert_param" macro in the Standard Peripheral Library drivers code */
/* #define USE_FULL_ASSERT 1 *//* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT/*** @brief The assert_param macro is used for function's parameters check.* @param expr: If expr is false, it calls assert_failed function which reports * the name of the source file and the source line number of the call * that failed. If expr is true, it returns no value.* @retval None*/#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */void assert_failed(uint8_t* file, uint32_t line);
#else#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */#endif /* __STM32F10x_CONF_H *//******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
main.c
/*** ****************************************************************************** @file main.c* @brief 主函数* @author (六千里)* @date 2024-03-09* @copyright 无* ******************************************************************************/
#include "stm32f10x.h" int main(void)
{// 来到这里的时候,系统的时钟已经被配置成72M。Led_Bitbang_GPIO_Test();}
相关文章:
STM32基础--位带操作
位带简介 位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见。51 单片机中通过关键字 sbit 来实现位定义,STM32 没有这样的关键字,而是通过访问位带别名区来实现。 在 STM32 中,有两个地方实现了位带ÿ…...
C# winform 重启电脑
一、重启电脑指令 windows7系统的启动文件夹为“开始菜单”——“所有程序”里面就有“启动”文件夹,其位置是 “C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup” 如果没有,则需要将其中的"administrator…...
波奇学Linux: 信号捕捉
sigaction:修改信号对应的handler方法 act输入型参数,oldact输出型参数 void (*sa_handler) (int) //修改的自定义函数 sigset_t sa_mask // void handler(int signo) {cout<<"catch a signal, signal number: "<<signo<<endl; } int …...
Flink hello world
下载并且解压Flink Downloads | Apache Flink 启动Flink. $ ./bin/start-cluster.sh Starting cluster. Starting standalonesession daemon on host harrydeMacBook-Pro.local. Starting taskexecutor daemon on host harrydeMacBook-Pro.local. 访问localhost:8081 Flin…...
STL之map容器代码详解
基础概念 简介: map中所有元素都是pair。pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)。所有元素都会根据元素的键值自动排序。 本质: map/multimap属于关…...
使用GRU进行天气变化的时间序列预测
本文基于最适合入门的100个深度学习项目的学习记录,同时在Google clolab上面是实现,文末有资源连接 天气变化的时间序列的难点 天气变化的时间序列预测涉及到了一系列复杂的挑战,主要是因为天气系统的高度动态性和非线性特征。以下是几个主…...
uniapp 小程序AP配网
一、TCPSocket.js 封装TCP协议 class socket {constructor() {this.connection {};}// 创建一个TCP实例establish(monitor) {this.connection wx.createTCPSocket();this.connection.connect({ address: "000.000.0.0", port: 6800 });}// 发送消息connect(messag…...
Stable Diffusion ———LDM、SD 1.0, 1.5, 2.0、SDXL、SDXL-Turbo等版本之间关系现原理详解
一、简介 2021年5月,OpenAI发表了《扩散模型超越GANs》的文章,标志着扩散模型(Diffusion Models,DM)在图像生成领域开始超越传统的GAN模型,进一步推动了DM的应用。 然而,早期的DM直接作用于像…...
GESP5级T1真题 [202309] 因数分解——O(sqrt(n))的时间复杂度,值得一看
描述 每个正整数都可以分解成素数的乘积,例如:62*3、2022 *5 现在,给定一个正整数N,请按要求输出它的因数分解式。 输入描述 输入第一行,包含一个正整数N。约定2<N<10^12 输出描述 输出一行,为N…...
Stable Diffusion 3报告
报告链接:https://stability.ai/news/stable-diffusion-3-research-paper 文章目录 要点表现架构细节通过重新加权改善整流流量Scaling Rectified Flow Transformer Models灵活的文本编码器RF相关论文 要点 发布研究论文,深入探讨Stable Diffuison 3的…...
一个足球粉丝该怎么建个个人博客?
做一个个人博客第一步该怎么做? 好多零基础的同学们不知道怎么迈出第一步。 那么,就找一个现成的模板学一学呗,毕竟我们是高贵的Ctrl c v 工程师。 但是这样也有个问题,那就是,那些模板都,太!…...
缩放算法优化步骤详解
添加链接描述 背景 假设数据存放在在unsigned char* m_pData 里面,宽和高分别是:m_nDataWidth m_nDataHeight 给定缩放比例:fXZoom fYZoom,返回缩放后的unsigned char* dataZoom 这里采用最简单的缩放算法即: 根据比…...
[axios]使用指南
axios使用指南 Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。 axios 安装 npm安装 $ npm install axios 使用cdn <script src"https://unpkg.com/axios/dist/axios.min.js"></script> axios API axios(config)…...
HTML5基础2
drag 可以把拖放事件拆分成4个步骤 设置元素为可拖放。为了使元素可拖动,把 draggable 属性设置为 true 。 <img draggable"true"> 拖动什么。ondragstart 和 setData() const dragestart (ev)>{ev.dataTransfer.setData(play,ev.target.id)} …...
数据结构与算法-希尔排序
引言 在计算机科学中,数据结构和算法是构建高效软件系统的基石。而排序算法作为算法领域的重要组成部分,一直在各种应用场景中发挥着关键作用。今天我们将聚焦于一种基于插入排序的改进版本——希尔排序(Shell Sort),深…...
蓝桥杯算法错题记录
这里写目录标题 本文还在跟新,最新更新时间24/3/91. nextInt () next() nextLine() 的注意事项2 . 转换数据类型int ,string,charint -> string , charstring -> int ,charchar -> int , string 进制转换十六进制转化为10 进制 最大公约数 本文还在跟新&am…...
【Python 图像处理 PIL 系列 13 -- PIL 及 Image.convert 函数介绍】
文章目录 Python PIL 介绍PIL 使用介绍PIL convert 介绍PIL convert 使用示例 Python PIL 介绍 PIL 是 Python Image Library 的简称。PIL 库中提供了诸多用来处理图片的模块,可以对图片做类似于 PS(Photoshop) 的编辑。比如:改变…...
使用docker datascience-notebook进行数据分析
Jupyter/datascience-notebook 简介 jupyter/datascience-notebook 是 Docker Hub 上可用的 Docker 镜像:https://hub.docker.com/。该镜像提供了一个开箱即用的环境,用于数据科学任务,包括: Jupyter Notebook: 一个基于 Web 的…...
VR全景技术在VR看房中有哪些应用,能带来哪些好处
引言: 随着科技的不断发展,虚拟现实(VR)技术在房地产行业中的应用也越来越广泛。其中,VR全景技术在VR看房中的运用尤为突出。今天,让我们一起深入探讨VR全景技术在VR看房中的应用及其带来的种种好处。 一、…...
Winform窗体随着屏幕的DPI缩放,会引起窗体变形及字体变形,superTabControl标签字体大小不匹配
一、前言 superTabControl做的浏览器标签(cefsharp)在缩放比例(125%,150%时字体不协调) 物联网浏览器,定制浏览器,多媒体浏览器(支持H264)参考栏目文章即可 二、配置参数 app.manifest参数 dpiAware =true <application xmlns="urn:schemas-microsoft-c…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
