C语言位移操作

//==========================STM32不完全手册   C语言复习部分================================//

移位操作提高代码的可读性
移位操作在单片机开发中也非常重要,下面让我们看看固件库的 GPIO 初始化的函数里
面的一行代码

//=====================================================================================//

//0x01=0000 0001(B),左移4位,变为0001 0000;    因为移走后补零,相当于只有1在移动,相当于只把pinpos位设为1

GPIOx->BSRR = (((uint32_t)0x01) << pinpos);


这个操作就是将 BSRR 寄存器的第 pinpos 位设置为 1,为什么要通过左移而不是直接设
置一个固定的值呢?其实,这是为了提高代码的可读性以及可重用性。这行代码可以
很直观明了的知道,是将第 pinpos 位设置为 1。如果你写成

GPIOx->BSRR =0x0030;


这样的代码就不好看也不好重用了。
类似这样的代码很多:

GPIOA->ODR|=1<<5; //PA.5 输出高,不改变其他位


这样我们一目了然,5 告诉我们是第 5 位也就是第 6 个端口,1 告诉我们是设置为 1 了。

 

 

//==============================CAN通信代码==================================//
 

/********************************************************************************
   给底盘电调发送指令
*********************************************************************************/
void Set_CM_Speed(CAN_TypeDef *CANx, int16_t cm1_iq, int16_t cm2_iq, int16_t cm3_iq, int16_t cm4_iq)
{
    CanTxMsg tx_message;
    tx_message.StdId = 0x200;
    tx_message.IDE = CAN_Id_Standard;
    tx_message.RTR = CAN_RTR_Data;
    tx_message.DLC = 0x08;
    
    tx_message.Data[0] = (uint8_t)(cm1_iq >> 8);
    tx_message.Data[1] = (uint8_t)cm1_iq;
    tx_message.Data[2] = (uint8_t)(cm2_iq >> 8);
    tx_message.Data[3] = (uint8_t)cm2_iq;
    tx_message.Data[4] = (uint8_t)(cm3_iq >> 8);
    tx_message.Data[5] = (uint8_t)cm3_iq;
    tx_message.Data[6] = (uint8_t)(cm4_iq >> 8);
    tx_message.Data[7] = (uint8_t)cm4_iq;
    CAN_Transmit(CANx,&tx_message);
}

代码中cm1_iq为16位变量,而Data[ ]储存8位变量

//假设cm1_iq=12345678 11112222,左移8位(12345678原来位置补零,11112222移没了),变为00000000 12345678

 tx_message.Data[0] = (uint8_t)(cm1_iq >> 8);

//u16型变量强制转换为u8型变量,只保留低8位
 

 tx_message.Data[1] = (uint8_t)cm1_iq;

也就是说u16型变量cm1_iq储存到u8型数组Data[ ]中,高8位储存到Data[1]中,底8位储存到Data[2]中

 

//======================正点原子关于u16转u8的问答===============================//

问题

u8 a;
u16 b=0x1234;
a=b;

a的值应该是多少 ,这种写法有语法错误吗

 

回答1

得赋值给2个u8
u8 a=u16>>8;
u8 b=u16&0XFF;//0xff=1111 1111(B)=0000 0000 11111 1111;      相与后,只保留低八位

回答2

可以采用强制转换a=(u8)b取低8位,没有警告

 

问答链接:http://www.openedv.com/forum.php?mod=viewthread&tid=233661

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中,寄存器位移运算是通过操作符来实现的。操作符在操作寄存器时具有特殊作用。寄存器是按进行规划和使用的,读写时是以32整体进行操作的。在操作寄存器时,可以改变某一特定,而不影响其他。例如,可以通过操作符"&"来改变寄存器中的某些。 举个例子,假设有两个无符号整数变量a和b,分别为0xa12aaaa7和0xFFFF00FF。要将a和b的对应进行与运算,可以使用操作符"&",并将结果赋值给另一个变量c。具体代码如下: unsigned int a = 0xa12aaaa7; unsigned int b = 0xFFFF00FF; unsigned int c; c = a & b; 上述代码将a和b进行与运算,并将结果保存在变量c中。可以使用打印语句输出c的值。 printf("a & b = %#X.\n", c); printf("a & b = 0x%x.\n", c) 这样就可以打印出c的值。在这个例子中,与运算会将a和b的对应进行逐比较,只有在对应都为1时,结果才为1,否则为0。 除了寄存器位移运算,还可以使用位移操作符来构建特殊的二进制数。通过位移操作符可以获取特定为1或0的二进制数。例如,可以使用位移操作符来获取bit3-bit7为1,同时bit23-bit25为1,其余都为0的数,代码如下: unsigned int num = (0x1F << 3) | (0x7 << 23); 这样就可以得到一个特殊的二进制数。通过位移操作符和按操作符,可以灵活地构建需要的二进制数。 总结起来,寄存器位移运算是通过操作符来实现的。操作符可以用来改变寄存器中的某一特定,同时可以用来构建特殊的二进制数。在C语言中,操作符有不同的作用,可以对进行逐个取反,也可以进行逻辑运算。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [C语言对寄存器的操作](https://blog.csdn.net/qixjocd12345/article/details/108304967)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [逻辑运算之寄存器移运算](https://blog.csdn.net/weixin_38066782/article/details/129373220)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值