单片机编程常用位运算
位定义 - 参考STM32 ST官方库
#define GPIO_PIN_0 ((uint16_t)0x0001) /* Pin 0 selected */
#define GPIO_PIN_1 ((uint16_t)0x0002) /* Pin 1 selected */
#define GPIO_PIN_2 ((uint16_t)0x0004) /* Pin 2 selected */
#define GPIO_PIN_3 ((uint16_t)0x0008) /* Pin 3 selected */
#define GPIO_PIN_4 ((uint16_t)0x0010) /* Pin 4 selected */
#define GPIO_PIN_5 ((uint16_t)0x0020) /* Pin 5 selected */
#define GPIO_PIN_6 ((uint16_t)0x0040) /* Pin 6 selected */
#define GPIO_PIN_7 ((uint16_t)0x0080) /* Pin 7 selected */
#define GPIO_PIN_8 ((uint16_t)0x0100) /* Pin 8 selected */
#define GPIO_PIN_9 ((uint16_t)0x0200) /* Pin 9 selected */
#define GPIO_PIN_10 ((uint16_t)0x0400) /* Pin 10 selected */
#define GPIO_PIN_11 ((uint16_t)0x0800) /* Pin 11 selected */
#define GPIO_PIN_12 ((uint16_t)0x1000) /* Pin 12 selected */
#define GPIO_PIN_13 ((uint16_t)0x2000) /* Pin 13 selected */
#define GPIO_PIN_14 ((uint16_t)0x4000) /* Pin 14 selected */
#define GPIO_PIN_15 ((uint16_t)0x8000) /* Pin 15 selected */
#define GPIO_PIN_All ((uint16_t)0xFFFF) /* All pins selected */
或者使用类似TI MSP430的BIT0 BIT1命名
从输入取出某一位或几位
oDat = iDat & GPIO_PIN_0oDat = iDat & (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3)oDat = iDat & 0x0f
置1 (这三种方式优势在于,仅仅有左侧数据在右边引导数据bit为1的位受影响,而其他位不受影响)
Dat |= 0x0f
置0
Dat &= ~0x0f
取反
Dat ^= 0x0f
将单片机非连续位IO输入转为连续的Byte位(有时候输入数据不能连接到一块连续的IO区域)
int dat1=GPIOD->IDR;int dat2=GPIOB->IDR;int oDat = 0;if(dat1 & GPIO_PIN_2) oDat |= GPIO_PIN_0;if(dat1 & GPIO_PIN_4) oDat |= GPIO_PIN_1;if(dat1 & GPIO_PIN_5) oDat |= GPIO_PIN_2;if(dat1 & GPIO_PIN_6) oDat |= GPIO_PIN_3;if(dat1 & GPIO_PIN_3) oDat |= GPIO_PIN_4;if(dat2 & GPIO_PIN_8) oDat |= GPIO_PIN_5;if(dat2 & GPIO_PIN_7) oDat |= GPIO_PIN_6;if(dat2 & GPIO_PIN_9) oDat |= GPIO_PIN_7;
将连续的Byte位转为单片机非连续位IO输出
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6 , iDat & GPIO_PIN_0);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7 , iDat & GPIO_PIN_1);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 , iDat & GPIO_PIN_2);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9 , iDat & GPIO_PIN_3);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8 , iDat & GPIO_PIN_4);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9 , iDat & GPIO_PIN_5);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10 , iDat & GPIO_PIN_6);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15 , iDat & GPIO_PIN_7);
串行通信输出 (第二种更为简洁,推荐)
1,低位先出
char obit;
for(int cnt=0; cnt<8; cnt++)
{obit = iDat & GPIO_PIN_0;iDat >>=1;// obit = obit > 0; // if necessary// write obit to pin
}
或者
char obit;
for(int cnt=0; cnt<8; cnt++)
{obit = iDat & (GPIO_PIN_0 << cnt);// obit = obit > 0; // if necessary// write obit to pin
}
2,高位先出
char obit;
for(int cnt=0; cnt<8; cnt++)
{obit = iDat & GPIO_PIN_7;iDat <<=1;// obit = obit > 0; // if necessary// write obit to pin
}
或者
char obit;
for(int cnt=0; cnt<8; cnt++)
{obit = iDat & (GPIO_PIN_7 >> cnt);// obit = obit > 0; // if necessary// write obit to pin
}
串行通信输入
1,低位先入
int oDat = 0;
for(int cnt=0; cnt<8; cnt++)
{// get ibit// ibit = ibit > 0; // if ibit is not the LSBoDat >>= 1;if(ibit){oDat |= GPIO_PIN_7;}
}或者
int oDat = 0;
for(int cnt=0; cnt<8; cnt++)
{// get ibit// ibit = ibit > 0; // if ibit is not the LSBoDat |= ibit << cnt;
}
2,高位先入
int oDat = 0;
for(int cnt=0; cnt<8; cnt++)
{// get ibit// ibit = ibit > 0; // if ibit is not the LSBoDat <<= 1;oDat |= ibit;
}
或者
int oDat = 0;
for(int cnt=0; cnt<8; cnt++)
{// get ibit// ibit = ibit > 0; // if ibit is not the LSBoDat |= ibit << (7 - cnt);
}
循环移位(走马灯)
高往低每次只移动一位
int ibit = Dat & 0x01;Dat >>= 1;Dat |= ibit << 7;
高往低每次移动N位,N>0,数据有效长度为8位
#define MaxBitNum 8 //数据最大有效位数为8N = N % MaxBitNum;int bitSel = (1 << N) - 1; // 2^-1, for example, N = 4 generate 00001111 with 4 1bitsint ibit = 0;ibit = Dat & bitSel;Dat >>= N;Dat |= ibit << (MaxBitNum-N);
附上一个软件延时函数,应该可以避免空操作可能引起的编译器优化
int UserDelay(int cnt)
{int a=0;while(cnt--){a++;}return a;
}
欢迎添加和指出错误,非常感谢。
单片机编程常用位运算相关推荐
- 单片机c语言位运算写法,单片机与嵌入式系统中C语言的位运算小记
原标题:单片机与嵌入式系统中C语言的位运算小记 编了个PIC的项目,对里的还是蛮有感悟的,特此记录一下. 譬如说,在程序中定义了一个char类型的变量, purge_short_enable_flag ...
- 47 - 算法 - 记住常用位运算-Leetcode-136-只出现一次的数字
// 位运算 相同的 a^a = 0 a^0 = a 其它 a&a = a a&0 = 0 class Solution {public:int singleNumber(vector ...
- 【编程】位运算(异或)
异或:相同为1,不同为0 交换律:a ^ b ^ c <=> a ^ c ^ b 任何数于0异或为任何数 0 ^ n => n 相同的数异或为0: n ^ n => 0 var ...
- c语言程序转换成单片机语言,单片机编程常用到的类型转换 C语言程序实现
用C语言演示如何执行下列类型转换: 1,获取字符串中每个字符的十六进制值. 2,获取与十六进制字符串中的每个值对应的字符. 3,将十六进制string转换为整型. 4,将十六进制string转换为浮点 ...
- c++ 输出二进制_【位运算与状态压缩】二进制的魅力
[引言] 今天讲讲位运算与状态压缩. 位运算涉及系统底层的运算,骚操作很多:状态压缩则是编程中空间优化的有效手段,应该说两者本身其实并没有太直接的联系,但是在实际使用时会有一定的结合, ...
- 全面解读Math对象及位运算
<p>本文转载自:<a href="https://segmentfault.com/a/1190000008786789" title="全面解读Ma ...
- JavaScript 位运算总结拾遗
最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识. 把一个数变为大于等于该数的最小的2的幂 一个 ...
- [编织消息框架][设计协议]位运算
常用位运算符号 上节介绍bit基础,这节课介绍bit常用基本运算 为什么要使用 | & % ~ 这几种常见的运算? 如果你理解需求是非常简单的 需求1:有八种状态可以叠加 那么每个状态占一个b ...
- 【位运算】系列题目合集
理论 位运算相关基础知识详见此篇 博客 例题 leetcode765. 情侣牵手 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. ...
最新文章
- 9.11排序与查找(三)——给定一个排序后的数组,包括n个整数,但这个数组已被旋转过多次,找出数组中的某个元素...
- 白话Elasticsearch29-IK中文分词之IK分词器配置文件+自定义词库
- Flink开发环境搭建(maven)
- 鸣人的影分身(信息学奥赛一本通-T1303)
- python变量的作用域及生命周期_Python——变量的作用域
- wap移动网页开发rem用法
- 使用U盘驱动器安装Linux,使用U盘安装Ubuntu的详细图文教程
- unix 获取程序占用内存_如何减少Docker和Kubernetes中的JVM应用程序内存占用
- 给angularJs grid列上添加自定义按钮
- tkmybatis开启二级缓存
- 深度学习自学(二十二):推理框架-MNN
- docker(4):docker的安装(centos7)和加速
- java实现继承的代码_纯作业代码——Java实现接口、继承
- 端到端车道线检测_弱监督对象检测-端到端培训管道
- 【收山之作】用yourdiary为例 学习KRKR2 XP3加密静态分析
- MySQL数据备份恢复太慢解决办法
- 搬运小视频为什么要修改MD5值?什么是MD5?
- 教你如何在Oracle官网免登陆下载oracle数据库以及相关工具
- 转自【MDCC技术大咖秀】Android内存优化之OOM
- Could not enlist in transaction on entering meta-aware object!”