单片机编程常用位运算

2019-04-15 17:43发布


位定义  - 参考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_0     oDat = 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 LSB     oDat >>= 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 LSB     oDat |= ibit << cnt; }
2,高位先入 int oDat = 0; for(int cnt=0; cnt<8; cnt++) {     // get ibit     // ibit = ibit > 0; // if ibit is not the LSB     oDat <<= 1;     oDat |= ibit; } 或者 int oDat = 0; for(int cnt=0; cnt<8; cnt++) {     // get ibit     // ibit = ibit > 0; // if ibit is not the LSB     oDat |= ibit << (7 - cnt); } 循环移位(走马灯) 高往低每次只移动一位 int ibit = Dat & 0x01; Dat >>= 1; Dat |= ibit << 7; 高往低每次移动N位,N>0,数据有效长度为8位 #define MaxBitNum 8 //数据最大有效位数为8 N = N % MaxBitNum; int bitSel = (1 << N) - 1; // 2^-1, for example, N = 4 generate 00001111 with 4 1bits int ibit = 0; ibit = Dat & bitSel; Dat >>= N; Dat |= ibit << (MaxBitNum-N); 附上一个软件延时函数,应该可以避免空操作可能引起的编译器优化 int UserDelay(int cnt) {     int a=0;     while(cnt--)     {         a++;     }     return a; }   欢迎添加和指出错误,非常感谢。