• STM32H5移植zbar记录


    ZBar是一种流行的二维码扫描和解码工具,它在嵌入式系统中拥有广泛的应用。在嵌入式系统中,我们面临着有限的资源和更严格的性能要求,因此,选择适当的库来完成特定的任务非常重要。
    ZBar适用于各种嵌入式平台,包括ARM、x86和MIPS等处理器架构。它可以轻松地整合到各种嵌入式系统中,如智能家居设备、智能手机、平板电脑、远程控制设备、工业控制器等。
    ZBar使用C/C++编写,具有高度优化的算法,能够快速准确地读取各种二维码和条形码,包括QR码、Data Matrix码、PDF417码、EAN-13码等等。同时,ZBar还支持自定义解码器,开发者可以根据自己的需求配置扫描器以实现更好的解码效果。
    ZBar还具有非常灵活的API,可用于C/C++、Python、Java、Ruby等语言,开发人员可以根据自己的需求灵活选择相应的API。此外,ZBar还支持多种操作系统和平台,包括Linux、Windows、Mac OS X等。
    总之,ZBar是一种非常有用的嵌入式二维码和条形码扫描库,它提供了高效的解码算法、可定制的解码器和灵活的API,能够轻松地满足嵌入式设备的扫描和解码需求。

    这里感谢之前大佬移植zbar库到stm32,具体链接如下:https://www.cnblogs.com/greyorbit/p/8456814.html

    移植步骤也很简单,按照博文把对应文件和头文件路径加入到工程中,然后使用图片数组转成灰度数据,在调用zbar既可以识别。

    不过移植后会有一个问题,不能重复调用识别二维码,很容易内存就崩了。为了解决这个问题,让这个zbar库可以真正的用起来,不得不找到问题所在。

    这里直观的看就是内存问题,奈何如果从源码直接去查找malloc和free的匹配所需时间太大,只能动态调试查找原因,所以第一步,我移植了rt-thread系统,使用rt的内存管理api。

    移植rt-thread很方便,现在stm32代码生成工具cubemx可以直接添加rt-thread库,所以移植rt-thread系统很快。具体如下图:

    移植完rt-thread后,就需要把zbar库中用到的malloc、calloc、free等操作函数换成 rt-malloc、rt-calloc、rt-free等,直接用全局搜索和替换。

    替换后打开rt的内存调试功能宏定义:在rtdebug.h文件中

    更改后既可以看到打印内存申请和释放日志,以下为日志打印内容

     通过对申请和释放的对应关系,我们可以分析得出问题所在,zbar库在图片识别后释放了img->data指针,而这个指针是在zbar调用外部申请的空间,是不需要zbar内部释放的,具体代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    int main(void)
    {
      /* USER CODE BEGIN 1 */
        uint8_t test[]="start test\n";
        uint16_t i,j;
        int qr_img_width = 240;
         
        uint16_t Color;
        uint16_t cnt = 0;
         
        unsigned char *pic_rgb = (unsigned char *)gImage_test;
        unsigned char *pic_hd = NULL;
        unsigned char *pic_data = NULL;
         
        void * ptr_start;
     
      /* USER CODE END 1 */
     
      /* MCU Configuration--------------------------------------------------------*/
     
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      //HAL_Init();
     
      /* USER CODE BEGIN Init */
     
      /* USER CODE END Init */
     
      /* Configure the system clock */
      //SystemClock_Config();
     
      /* USER CODE BEGIN SysInit */
     
      /* USER CODE END SysInit */
     
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_ADC1_Init();
      MX_ETH_Init();
      MX_ICACHE_Init();
      MX_LPUART1_UART_Init();
      //MX_USART3_UART_Init();
      MX_UCPD1_Init();
      MX_USB_PCD_Init();
      /* USER CODE BEGIN 2 */
     
      pic_data = rt_malloc(qr_img_width*qr_img_width);
      if(pic_data == NULL)
      {
          printf("malloc error\n");
          return 0;
      }
      else
      {
          printf("pic_data:0x%x\n",pic_data);
      }
        //memset(pic_data,0,qr_img_width*qr_img_width);
         pic_hd = pic_data;
        for(i=0;i
        {
            for(j=0;j//将RGB565图片转成灰度
            {
     
                Color = (*pic_rgb) | (*(pic_rgb+1)<<8);
                *pic_hd = (((Color&0xF800)>> 8)*77+((Color&0x7E0)>>3)*150+((Color&0x001F)<<3)*29)/256;
                pic_hd++;
                pic_rgb++;
                pic_rgb++;
              
            }
        }
       
     
      /* USER CODE END 2 */
       
     
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
       
      while (1)
      {
        /* USER CODE END WHILE */
     
        /* USER CODE BEGIN 3 */
           
           
          if( Zbar_Test((void* )pic_data,qr_img_width,qr_img_width) == 0 )
          {
              printf("zbar failed \n");
              //rt_free(pic_data);
          }
          else
          {
              cnt ++;
              printf("zbar ok \n");
              //rt_free(pic_data);
          }
          printf("zbar count;%d\n",cnt);
          //list_thread();
          rt_thread_mdelay(5000);
           
      }
      rt_free(pic_data);
      /* USER CODE END 3 */
    }

      即pic_data灰度图片数据是不需要zbar释放的,但是zbar库中做了释放操作,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    inline void zbar_image_rt_free_data (zbar_image_t *img)
    {
        if(!img)
            return;
        if(img->src) {
            /* replace video image w/new copy */
            assert(img->refcnt); /* FIXME needs lock */
            zbar_image_t *newimg = zbar_image_create();
            memcpy(newimg, img, sizeof(zbar_image_t));
            /* recycle video image */
            newimg->cleanup(newimg);
            /* detach old image from src */
            img->cleanup = NULL;
            img->src = NULL;
            img->srcidx = -1;
        }
        else if(img->cleanup && img->data) {
            if(img->cleanup != zbar_image_rt_free_data) {
                /* using function address to detect this case is a bad idea;
                 * windows link libraries add an extra layer of indirection...
                 * this works around that problem (bug #2796277)
                 */
                zbar_image_cleanup_handler_t *cleanup = img->cleanup;
                img->cleanup = zbar_image_rt_free_data;
                cleanup(img);
            }
    //传入图片为外部指针,zbar内部不用free此指针
    //        else
    //            rt_free((void*)img->data);
        }
        img->data = NULL;
    }

      这里把这一句屏蔽,则可以解决问题,经过我测试,现在已经连续运行上千次

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    decoded QR-Code symbol "EEWorld STM32H5"
    len = 15
    45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
    zbar count;4290
    n = 1
     
    decoded QR-Code symbol "EEWorld STM32H5"
    len = 15
    45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
    zbar count;4291
    n = 1
     
    decoded QR-Code symbol "EEWorld STM32H5"
    len = 15
    45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
    zbar count;4292
    n = 1
     
    decoded QR-Code symbol "EEWorld STM32H5"
    len = 15
    45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
    zbar count;4293
    n = 1
     
    decoded QR-Code symbol "EEWorld STM32H5"
    len = 15
    45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
    zbar count;4294

     工程文件下载:http://bbs.eeworld.com.cn/thread-1244434-1-1.html

     

  • 相关阅读:
    设计模式------工厂模式的学习
    【Java】----面向对象
    java类的命名规范
    知识运维概述
    WEB安全基础 - - -漏洞扫描器
    C语言:计算阶乘与计算从1加到100的代码对比:都要用到3个变量,不同之处在于表达式
    Vue第1天:特性概览
    【附源码】计算机毕业设计SSM商品推荐系统
    使用soapUI获取webservice接口的调用格式
    【Spring 学习系列】Bean 的生命周期之初始化与销毁
  • 原文地址:https://www.cnblogs.com/uplaoding-ing/p/17431144.html