数组中按起始位进行读写值

最近在搞一个项目,对接设备;发现设备的串口协议相当坑爹; 上行和下行的功能不能对起来,而且相对的功能位置也是不对称,每个功能占据的bit位不同,可能一bit或者多bit;而应用层却是json 格式;在百度上搜了n遍也没有发现类似的,或者可以参考的demo;没办法自己动手做个转换层吧;自己动手,丰衣足食;

废话少说,上代码;

#include <string.h>
#include <time.h>
#include <stdint.h>
#include <stdlib.h>

#define DEF_VAL     0xFFFFFF  // 为什么是 FFFFFF, 不是 FFFFFFFF
#define RD_MAX      3  


#define SHORT_BIT_LEN 16
#define CHAR_BIT_LEN  8

//测试的 buf  

uint8_t key_val[] = {
    0x01,0x02,0x05,0xf8,0x67,0x88,0x98,0xa8,
    0xaa,0x87,0xcd,0xff,0xca,0xcd,0xda,0xdc,
    0x01,0x02,0x05,0xf8,0xaa,0x87,0xcd,0xca};


typedef struct
{
    uint16_t start_bit;
    uint16_t end_bit;
}key_site_t;


typedef struct
{
uint8_t index;
uint8_t start_mask;
uint8_t end_mask;
uint8_t optlen;
uint32_t opt_val;
}conver_info_t;


void debug_key(uint8_t *buf, uint16_t len)
{
    int i;
    printf("\r\n------------------------\r\n");
    for(i = 0; i < len; i++){
        if(i > 0 && (i & 7) == 0)
            printf("\r\n");
        printf("%02x ",buf[i]);
    }
    printf("\r\n------------------------\r\n");
}


int dev_cnv_info_get(conver_info_t *info, key_site_t *site)
{
uint32_t a = DEF_VAL,b= DEF_VAL;
/* first get the start index */
    info->index = site->start_bit >> 3;
    info->start_mask = site->start_bit & 7;
// 根据 起始位,得到需要操作的 byte 长度;
    info->optlen = site->end_bit + 1 - (site->start_bit - info->start_mask);
   

    if(info->optlen & 7)
        info->optlen = (info->optlen >> 3) + 1;
    else
        info->optlen = (info->optlen >> 3);


    if(info->optlen > RD_MAX){
        printf("retln too large \r\n");
        return -1;
    }
   
    info->end_mask  = ((site->end_bit + 1) & 7);
printf("index:%d ,start_mask:%d ,end_mask:%d optlen:%d \r\n",
          info->index, info->start_mask, info->end_mask, info->optlen);
 
    a = DEF_VAL << info->start_mask; //通过左移 来清除低位bit 的值;左移,低位补0; 
    if(info->end_mask != 0)
        b = DEF_VAL >> (CHAR_BIT_LEN - info->end_mask); // 右移,清除end_bit 对应byte 的高bit的值 ,高bit 补0 
printf("a:%08x, b:%08x \r\n",a, b);
    b >>= ((RD_MAX - info->optlen) << 3); // 右移 几个字节对应的bit; val,每次读3byte
printf("after move , b:%08x \r\n", b);
info->opt_val = (a & b);//  a & b 后, 相当于把 低位和高位都清0了,只保留了 start_bit 和 end_bit 中间bit 全为1, 后面可进行 &操作 或者取反后,进行| 
printf("opt_val:%08x \r\n",info->opt_val);
return 0;
}
int dev_get_data_by_site(key_site_t *site, uint8_t *input, uint16_t maxsize, uint16_t *get_val)
{
    uint32_t val;
conver_info_t info;

dev_cnv_info_get(&info,site);
    if((site->start_bit > (maxsize << 3)) ||(site->end_bit > (maxsize << 3)) )
        printf("the start bit or end bit is invalid \r\n");
    if((site->end_bit + 1 - site->start_bit) > SHORT_BIT_LEN)
        printf("the start bit and end bit difference  too large \r\n");
    /* read the val form input buf */
    memcpy(&val, &input[info.index], RD_MAX );
printf("read val from buf :%08x \r\n",val);
    /* clear this bit except start_bit to end_bit */
val &= info.opt_val;
    printf("clr val  :%08x \r\n",val);
    /* then left the data ,conver to the correct  val */
    val >>= info.start_mask;
    printf("get val :%08x \r\n",val);
    *get_val = val;
    return 0;
}


int dev_set_data_by_site(key_site_t *site, uint8_t *input, uint16_t maxsize, uint16_t set_val)
{
    
    uint32_t c,d, val = 0;
    conver_info_t info;

dev_cnv_info_get(&info,site);
    if((site->start_bit > (maxsize *8)) ||(site->end_bit > (maxsize *8)) )
        printf("the start bit or end bit is invalid \r\n");
    if((site->end_bit + 1 - site->start_bit) > SHORT_BIT_LEN)
        printf("the start bit and end bit difference  too large \r\n");
    c = ~(info.opt_val);


    printf(" c:%08x \r\n",c);


    /* read the val from input ,just 3 byte */
    memcpy(&val, &input[info.index],RD_MAX);
    printf("read val from input :%08x \r\n", val);  // jsut read three byte ;
    /* clear this bit (from start_bit to end_bit which will set val  )*/
    val &= c;
    printf("val after clr the opt bit:%08x \r\n",val);
    /* conver the set val  */
    d = set_val << info.start_mask;   //clear the start_mask bit 
    printf("[0] d:%08x \r\n",d);
    d &= info.opt_val;                
    printf("[1] d :%08x \r\n",d);
    /* save this bit value  to the val  */
    val |= d; 
    printf("conver the set val : %08x \r\n",val);
    /* copy the val to the input buf  -- just three byte */
    memcpy(&input[info.index],&val, RD_MAX);
    return 0;
}


int main(int argc, char *argv[])
{
    uint16_t get_val, set_val;
    key_site_t site;


    if(argc < 3){
        printf("not inpt data \r\n");
        exit(1);
        return -1;
    }
    site.start_bit = atoi(argv[1]);
    printf("start_bit:%d \r\n",site.start_bit);
    site.end_bit = atoi(argv[2]);
    printf("end_bit:%d \r\n",site.end_bit);
    set_val = atoi(argv[3]);
    dev_get_data_by_site(&site, key_val, sizeof(key_val),&get_val);
    printf("get_the old val: %d \r\n",get_val);
    printf("set_val:%x \r\n",set_val);
    printf("******debug buf before set_val ******\r\n");    
    debug_key(key_val, sizeof(key_val));
    dev_set_data_by_site(&site, key_val, sizeof(key_val),set_val);
    printf("******debug buf after set_val ******\r\n");
    debug_key(key_val, sizeof(key_val)); 
    dev_get_data_by_site(&site, key_val, sizeof(key_val),&get_val);
    printf("get_val: %d \r\n",get_val);


    
    return 0;
}

/*********************************************************/

Makefile

 CC = cc
 AR = ar
 AR_FLAG = rcs 




SRCS = $(wildcard *.c)


TARGET = shift


all:$(TARGET)
@echo "build $(TARGET)"


$(TARGET):$(SRCS)
$(CC) -g -Wall -o $@ $(SRCS) 


clean:
@echo "clean $(TARGET)"
@rm -f $(TARGET)


至于测试。。。。,你懂得。。,不多说。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值