bits的妙用

bits的妙用

本文主要讲解变成过程中可能用到的一些位运算以及位运算符使用的技巧

对于整型的操作

第n位置位

x | (1<<n)

第n位置0

x & ~(1<<n)

翻转第n位

x ^ (1<<n)

获取大于等于此数的最小的2次幂数

unsigned int v; //只有当v是 32 bit才奏效
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
比如:当v是63那么转换之后,v-->64
当v是64,那么转换之后,v不变

获取最大整数

int maxInt = ~(1 << 31);
int maxInt = (1 << 31) - 1;
int maxInt = (1 << -1) - 1;

获取最小整数

int minInt = 1 << 31;
int minInt = 1 << -1;

获取最大的长整型数

long maxLong = ((long)1 << 127) - 1;

乘2

n << 1; // n*2

除2

n >> 1; // n/2

乘2的n次幂

n << m;

除2的n次幂

n >> m;

判断两个数是否相等

此方法比普通的比较速率快35%

(a^b) == 0; // a == b
!(a^b) // 在判断语句中使用

检查是否为奇数

(n & 1) == 1;

交换两个数字

//版本 1
a ^= b;
b ^= a;
a ^= b;

//版本 2
a = a ^ b ^ (b = a)

获取绝对值

//版本 1
x < 0 ? -x : x;

//版本 2
(x ^ (x >> 31)) - (x >> 31);

得到两个数的最大值

b & ((a-b) >> 31) | a & (~(a-b) >> 31);

得到两个数的最小值

a & ((a-b) >> 31) | b & (~(a-b) >> 31);

检查两个数字是否有相同的符号

(x ^ y) >= 0;

反转一个数的符号

i = ~i + 1; // or
i = (i ^ -1) + 1; // i = -i

计算2的n次幂

2 << (n-1);

判断一个数是不是2的次幂

n > 0 && (n & (n - 1)) == 0;

m对2的n次幂取余

m & (n - 1);

计算两个数的平均数

(x + y) >> 1;
((x ^ y) >> 1) + (x & y);

获取n的第m位 (从低到高)

(n >> (m-1)) & 1;

n的第m位置为0 (从低到高)

n & ~(1 << (m-1));

检查x的第n位是否被置位

if (x & (1<<n)) {
 // 第n位被置位
} else {
  //第n位没有被置位
}

提取最右边的为1的位

x & (-x)
例如:70000 0000 0000 0000 0000 0000 0000 0111
经过运算之后 变为
0000 0000 0000 0000 0000 0000 0000 0001
640000 0000 0000 0000 0000 0000 0100 0000
经过运算之后:
0000 0000 0000 0000 0000 0000 0100 0000

提取最右边的为0的位(类比于上一个)

~x & (x+1)

使最右边的为0的位置为1

x | (x+1)

n + 1

-~n

n - 1

~-n

得到一个数的负数

~n + 1;
(n ^ -1) + 1;

if (x == a) x = b; if (x == b) x = a;

x = a ^ b ^ x;

浮点数

此部分大多数都来源于 fast inverse square root method.

把一个浮点数转化为一个bits数组 (unsigned uint32_t)

#include <stdint.h>
typedef union {float flt; uint32_t bits} lens_t;
uint32_t f2i(float x) {
  return ((lens_t) {.flt = x}).bits;
}

把一个bits数组转化为浮点数

float i2f(uint32_t x) {
  return ((lens_t) {.bits = x}).flt;
}

Approximate the bit-array of a positive float using frexp

frexp gives the 2n decomposition of a number, so that man, exp = frexp(x) means that man 2exp = x and 0.5 <= man < 1.*

man, exp = frexp(x);//or man= frexp(x,&exp);
return (uint32_t)((2 * man + exp + 125) * 0x800000);

------------------------------
double x = 666.400000;
    double man = 0;
    int exp = 0;
    //sprintf(x&(-x),"%d");
    //cout << (x&(-x)) << endl;
    man= frexp(x,&exp);
    printf("frexp(%f,&n)=%f,n=%d\n", x, man, exp)
---------------------------------
运行结果:
frexp(666.400000,&n)=0.650781,n=10
---------------------------------

Caveat: This will have at most 2-16 relative error, since man + 125 clobbers the last 8 bits, saving the first 16 bits of your mantissa.

字符串

转换为小写字母

OR by space => (x | ' ')
Result is always lowercase even if letter is already lowercase
eg. ('a' | ' ') => 'a' ; ('A' | ' ') => 'a'

转换为大写字母

AND by underline => (x & '_')
Result is always uppercase even if letter is already uppercase
eg. ('a' & '_') => 'A' ; ('A' & '_') => 'A'

反转大小写

XOR by space => (x ^ ' ')
eg. ('a' ^ ' ') => 'A' ; ('A' ^ ' ') => 'a'

返回在字母表中的位置

AND by chr(31)/binary('11111')/(hex('1F') => (x & "\x1F")
Result is in 1..26 range, letter case is not important
eg. ('a' & "\x1F") => 1 ; ('B' & "\x1F") => 2

返回在字母表中的位置 (只对大写字母有效):

AND by ? => (x & '?') or XOR by @ => (x ^ '@')
eg. ('C' & '?') => 3 ; ('Z' ^ '@') => 26

返回在字母表中的位置 (只对小写字母有效):

XOR by backtick/chr(96)/binary('1100000')/hex('60') => (x ^ '`')
eg. ('d' ^ '`') => 4 ; ('x' ^ '`') => 25

杂项

从R5G5B5 to R8G8B8 的快速像素转换

R8 = (R5 << 3) | (R5 >> 2)
G8 = (R5 << 3) | (R5 >> 2)
B8 = (R5 << 3) | (R5 >> 2)

Note: 使用其他字母会产生严重错误

参考文献

### 达妙 H7 开发板接收 DBus 信号并控制灯的操作 #### 1. DBus 协议简介 DBus 是一种轻量级的消息传递协议,广泛应用于嵌入式设备通信中。它支持多种消息类型和方法调用机制,适用于实时性和可靠性较高的场景[^1]。 对于达妙 H7 开发板而言,其硬件设计兼容 DBus 数据传输标准。为了实现对大疆 DT7 遥控器的数据接收功能,需特别注意串口配置参数的设置。根据已知信息,该开发板需要将数据长度设为 **9 位** 并启用 **2 位停止位** 才能正常解析遥控器发送的数据流[^3]。 --- #### 2. 硬件连接与初始化 在物理层面上,确保达妙 H7 的 SBUS 接口正确连接到大疆 DT7 遥控器的输出端。尽管标注为 SBUS,但实际上可能遵循 DBus 或类似的二进制编码方式。因此,建议按照以下步骤完成初始化: - 使用 STM32CubeMX 工具创建项目框架。 - 将 USART 外设配置为异步模式 (Asynchronous),波特率设定为 `100,000 bps`。 - 设置帧格式如下: - 字长:9 bits - 停止位:2 bits - 流控制:无校验 以下是部分代码示例用于配置 UART 参数: ```c void MX_USART_Init(void) { huart.Instance = USARTx; // 替换为实际使用的USART外设编号 huart.Init.BaudRate = 100000; huart.Init.WordLength = UART_WORDLENGTH_9B; huart.Init.StopBits = UART_STOPBITS_2; huart.Init.Parity = UART_PARITY_NONE; HAL_UART_Init(&huart); } ``` --- #### 3. 数据处理逻辑 当接收到完整的 DBus 数据包后,程序应对其进行解码以提取有效载荷。通常情况下,DBus 数据结构包含多个字节的信息字段,其中某些特定位置可用于指示当前状态或触发事件。 例如,在 SBus 中第 24 字节 (`Sbus_Buff[24]`) 被用来标记是否存在信号丢失现象[^4]。如果此标志被置高,则表明远程控制器处于断开状态;反之则表示链路稳定运行。 针对灯光效果的应用需求,可以通过读取上述状态变量决定 LED 行为动作。下面展示了一种简单的实现方案: ```c if ((Sbus_Buff[24] & 0x0C) != 0) { // 当检测到信号丢失时关闭所有LEDs GPIOA->ODR &= ~(GPIO_ODR_RESET << LED_PIN); // 关闭指定引脚上的发光二极管 } else { // 否则点亮对应颜色组合 GPIOA->ODR |= (GPIO_ODR_SET << RED_LED_PIN); // 红色亮起 GPIOA->ODR |= (GPIO_ODR_SET << GREEN_LED_PIN); // 绿色亮起 } ``` > 注明:以上伪代码片段仅作为示范用途,请依据具体电路布局调整相应的寄存器地址及掩码定义。 --- #### 4. 实现注意事项 由于不同版本固件之间可能存在差异性表现,所以在移植过程中务必仔细核对接线关系及其关联驱动库文件内容的一致性。另外考虑到电磁干扰等因素的影响,推荐采用屏蔽双绞线来增强抗噪能力从而保障通讯质量。 最后提醒一点就是关于电源管理方面的问题——确保给定电压范围满足规格书规定的要求以免损坏敏感元件。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值