打印
[疑难问答]

变量位操作

[复制链接]
2668|53
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
deliahouse887|  楼主 | 2024-8-24 13:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一位
整型变量a

unsigned int a;

a | = (0x1<<3);            //设置a的bit 3 置1
a & = ~ (0x1<<3);          //设置a的bit 3 置0

a = (b & (1 << 1)) >> 1;   //取b的 bit 1 数据值
a = (b & (1 << 3)) >> 3;   //取b的 bit 3 数据值
if((readbuffer & 0x08) == 0x00)    //Bit[3] 是否为 1



字符
求余、乘、除 (2,4,8,16.......)

a=a&7;          // 求余运算 相当于 a=a%8;

a=a<<2;          // 乘4            a=a*4;
a=(a<<3)+a       // 乘9            a=a*9


b=b>>2;          // 除4              b=b/4;




移位


uint8_t a,b;
uint16_t c;
c = ( (uint16_t) a << 8 ) | b ;            //两个8位字符变为一个16位
函数封装:

赋值
memset()
是计算机中C/C++语言初始化函数。

作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。

void *memset(void *s, int ch, size_t n);

函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。

memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法 。

memset()函数原型是extern void *memset(void *buffer, int c, int count) buffer:为指针或是数组,c:是赋给buffer的值,count:是buffer的长度.

memcpy()
指的是C和C++使用的内存拷贝函数,

函数原型为void *memcpy(void *destin, void *source, unsigned n);

函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,即从源source中拷贝n个字节到目标destin中。

函数原型

void *memcpy(void *destin, void *source, unsigned n);


参数

destin-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。

source-- 指向要复制的数据源,类型强制转换为 void* 指针。

n-- 要被复制的字节数。


返回值

该函数返回一个指向目标存储区destin的指针。


功能

从源source所指的内存地址的起始位置开始拷贝n个字节到目标destin所指的内存地址的起始位置中。

memcpy() 并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的使用带来了很大的灵活性,可以面向任何数据类型进行复制。

需要注意的是:

destin指针要分配足够的空间,也即大于等于 n 字节的空间。如果没有分配空间,会出现断错误。

destin和 source所指的内存空间不能重叠(如果发生了重叠,使用 memmove()会更加安全)。


所需头文件

C语言:#include<string.h>

C++:#include<cstring>

数据过滤:
中位值滤波

方法:连续采样N次(N取奇数)把N次采样值按大小排列取中间值为本次有效值
优点:能有效克服因偶然因素引起的波动干扰;对温度、液位等变化缓慢的被测参数有良好的滤波效果
缺点:对流量,速度等快速变化的参数不宜

//中值滤波算法
int middleValueFilter(int N)
{
    int value_buf[N];
    int i,j,k,temp;
    for( i = 0; i < N; ++i)
    {
        value_buf[i] = HAL_ADC_GetValue(&hadc1);   

    }
    for(j = 0 ; j < N-1; ++j)
    {
        for(k = 0; k < N-j-1; ++k)
        {
            //从小到大排序,冒泡法排序
            if(value_buf[k] > value_buf[k+1])
            {
                temp = value_buf[k];
                value_buf[k] = value_buf[k+1];
                value_buf[k+1] = temp;
            }
        }
    }
    return value_buf[(N-1)/2];
}
中值滤波对消除异常值和平稳化AD采样都具有十分有效的结果。

功能代码
PID
PID控制应该算是应用非常广泛的控制算法了。小到控制一个元件的温度,大到控制四轴飞行器的飞行姿态和飞行速度等等,都可以使用PID控制。这里我们从原理上来理解PID控制。PID(proportion integration differentiation)其实就是指比例,积分,微分控制。PID的公式和原理推导我就不多赘述了,大伙有兴趣的话可以去看看其他大佬们写的原理,这里只简单的说说给个参数的作用和如何调节三个参数!!!(重点)

P(比例系数):成比例的反应控制系统中输入与输出的偏差信号,只要偏差一旦产生,就立刻产生控制的作用来减少产生的误差。

I(Ti积分系数):在比例控制环节产生了静态误差,在积分环节中,主要作用就是消除静态误差来提高系统的稳定性。

D(Td微分系数):微分环节是反应系统偏差的一个变化趋势,可以在误差来临前提前引入一个有效的修正信号。

而常用的PID又分位置式PID和增量式PID:

位置式PID是一种非递推式算法,通过不断累加,可以直接控制执行机构(平衡小车),u(k)的值和执行机构的实际位置(如小车当前角度)是一一对应的,因此在执行机构中不带积分不见的对象中可以很好的应用。

增量式不需要不断累加,控制的增量△u(k)也只与最近3次的采样值有关。在速度闭环控制中有很好的实时性。

在进行PID控制时,位置式PID需要又积分限幅和输出限幅,而增量式PID只需要输出限幅。

重要的是PID参数的整定

这里我给大家推荐一个我常用的方法:一般调节法!!

一般调节法:在输出不振荡时,增大比例增益P。在输出不振荡时,减少积分常数Ti。

在输出不震荡时,增大微分时间常数Td。

1:确认比例增益P时,首先去掉PID中的积分Ti和微分Td,一般让Ti=0和Td=0,让其PID变为纯比例P调节。输入设定为系统允许的最大值的60%~70%,由0逐渐增大增益P,直到系统出现振荡;然后再反过来,逐渐将p减小,直至振荡消失,记录此时的比例增益P,设定为PID的比例增益P为当前的60%~70%,。

2:确定积分时间常数Ti:设定一个较大的积分时间常数Ti的初值,然后逐渐减小Ti,直至系统出现振荡,在翻过来逐渐加大Ti,直至系统振荡小时。记录此时的Ti,设定PID积分时间常数Ti为当前的150%~180%。

3:确认微分时间常数Td:积分时间常数Td一般不用设定,若要设定则与P和Ti方式相同,取不震荡的30%。

使用特权

评论回复
沙发
abotomson| | 2024-9-3 15:57 | 只看该作者
这种操作在嵌入式系统和硬件编程中尤为重要,因为它们允许开发者直接控制硬件的底层行为

使用特权

评论回复
板凳
adolphcocker| | 2024-9-3 16:45 | 只看该作者
位操作通常比算术操作更快,但可读性较差。因此,在使用位操作时,应确保代码的可读性和可维护性。

使用特权

评论回复
地板
pmp| | 2024-9-3 20:31 | 只看该作者
按位取反运算符用于反转一个表达式的每一个二进制位。1变成0,0变成1。

使用特权

评论回复
5
albertaabbot| | 2024-9-3 22:54 | 只看该作者
这些操作可以在不使用高级数学或逻辑函数的情况下,快速地进行数据的编码、解码、加密、压缩等任务。位操作包括位与(AND)、位或(OR)、位异或(XOR)、位非(NOT)、左移(Shift Left)和右移(Shift Right)等。

使用特权

评论回复
6
bestwell| | 2024-9-5 08:34 | 只看该作者
右移运算符用于将一个表达式的二进制位向右移动指定的位数。对于有符号整数,空出的高位通常用符号位填充(算术右移),对于无符号整数则用0填充(逻辑右移)。

使用特权

评论回复
7
jtracy3| | 2024-9-5 08:56 | 只看该作者
位操作只能用于整型数据类型(如char、int、long等)。

使用特权

评论回复
8
febgxu| | 2024-9-5 09:37 | 只看该作者
位操作通常用于整数类型,包括char、short、int、long等。

使用特权

评论回复
9
sesefadou| | 2024-9-5 13:16 | 只看该作者
位操作的结果可能因编译器和硬件平台的不同而有所差异。为了提高代码的可移植性,应尽量避免依赖特定平台的位操作行为。

使用特权

评论回复
10
sdCAD| | 2024-9-5 14:48 | 只看该作者
位操作在嵌入式系统、优化算法性能以及处理硬件接口时非常有用。它们可以提供比传统的算术和逻辑操作更精细的控制,并且通常更快。

使用特权

评论回复
11
jimmhu| | 2024-9-6 16:55 | 只看该作者
位操作可以用来实现掩码、标志位、位字段等高级技术。

使用特权

评论回复
12
linfelix| | 2024-9-6 18:36 | 只看该作者
C语言中的变量位操作是指直接对变量的二进制位进行操作的过程。

使用特权

评论回复
13
jackcat| | 2024-9-6 19:56 | 只看该作者
位操作代码可能比较难以理解和维护。在使用位操作时,应添加适当的注释来解释代码的意图,提高代码的可读性。

使用特权

评论回复
14
uytyu| | 2024-9-7 10:19 | 只看该作者
左移(<<):
左移运算符用于将一个表达式的二进制位向左移动指定的位数。新的高位被填入0。

使用特权

评论回复
15
qiufengsd| | 2024-9-7 11:19 | 只看该作者
按位与操作符 & 对两个操作数的每一位执行逻辑与操作。如果两个相应的二进制位都为1,则结果为1,否则为0。

使用特权

评论回复
16
wilhelmina2| | 2024-9-7 11:37 | 只看该作者
可以使用标准的位操作符和明确的数据类型来提高可移植性。

使用特权

评论回复
17
pl202| | 2024-9-7 15:14 | 只看该作者
按位异或操作符 ^ 对两个操作数的每一位执行逻辑异或操作。如果两个相应的二进制位不同,则结果为1,否则为0。

使用特权

评论回复
18
iyoum| | 2024-9-7 17:54 | 只看该作者
位操作在C语言编程中是一种非常强大的工具,尤其是在需要直接与硬件接口打交道时。正确使用位操作可以优化程序性能并减少内存使用。

使用特权

评论回复
19
sheflynn| | 2024-9-7 18:54 | 只看该作者
C语言中的位操作是一种直接对整数类型变量中的位(bit)进行操作的手段。

使用特权

评论回复
20
pl202| | 2024-9-7 20:54 | 只看该作者
可以使用位操作来设置和检查变量中的标志位。例如,可以定义一个整数变量来表示多个状态标志,通过位操作来设置和检查特定的标志。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

1178

帖子

0

粉丝