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文件中
更改后既可以看到打印内存申请和释放日志,以下为日志打印内容
malloc size 156 allocate memory at 0x2001008c, size: 168 malloc size 296 allocate memory at 0x20010134, size: 308 malloc size 32 allocate memory at 0x20010268, size: 44 malloc size 48 allocate memory at 0x20010294, size: 60 malloc size 2856 allocate memory at 0x200102d0, size: 2868 malloc size 52 allocate memory at 0x20010e04, size: 64 allocate memory at 0x20010e04, size: 64 malloc size 16 allocate memory at 0x20010e44, size: 28 malloc size 20 allocate memory at 0x20011388, size: 32 malloc size 60 allocate memory at 0x200113a8, size: 72 release memory 0x20011388, size: 32 malloc size 140 allocate memory at 0x200113f0, size: 152 release memory 0x200113a8, size: 72 malloc size 300 allocate memory at 0x20011488, size: 312 release memory 0x200113f0, size: 152 malloc size 620 allocate memory at 0x200115c0, size: 632 release memory 0x20011488, size: 312 malloc size 1260 allocate memory at 0x20011838, size: 1272 release memory 0x200115c0, size: 632 malloc size 2540 allocate memory at 0x20011d30, size: 2552 release memory 0x20011838, size: 1272 malloc size 20 allocate memory at 0x20011388, size: 32 malloc size 60 allocate memory at 0x200113a8, size: 72 release memory 0x20011388, size: 32 malloc size 140 allocate memory at 0x200113f0, size: 152 release memory 0x200113a8, size: 72 malloc size 300 allocate memory at 0x20011488, size: 312 release memory 0x200113f0, size: 152 malloc size 620 allocate memory at 0x200115c0, size: 632 release memory 0x20011488, size: 312 malloc size 1260 allocate memory at 0x20011838, size: 1272 release memory 0x200115c0, size: 632 malloc size 2540 allocate memory at 0x20012728, size: 2552 release memory 0x20011838, size: 1272 malloc size 352 allocate memory at 0x20011388, size: 364 malloc size 352 allocate memory at 0x200114f4, size: 364 malloc size 88 allocate memory at 0x20011660, size: 100 release memory 0x20011660, size: 100 malloc size 440 allocate memory at 0x20011660, size: 452 malloc size 440 allocate memory at 0x20011824, size: 452 malloc size 110, but align to 112 allocate memory at 0x200119e8, size: 124 release memory 0x200119e8, size: 124 malloc size 5792 allocate memory at 0x20013120, size: 5804 malloc size 80 allocate memory at 0x200119e8, size: 92 malloc size 20 allocate memory at 0x20011a44, size: 32 malloc size 32 allocate memory at 0x20011a64, size: 44 malloc size 5, but align to 8 allocate memory at 0x20011a90, size: 24 malloc size 8 allocate memory at 0x20011aa8, size: 24 release memory 0x20011aa8, size: 24 release memory 0x20011a90, size: 24 release memory 0x20011a64, size: 44 release memory 0x20011a44, size: 32 release memory 0x20011824, size: 452 release memory 0x20011660, size: 452 release memory 0x200114f4, size: 364 release memory 0x20011388, size: 364 malloc size 57600 allocate memory at 0x200147cc, size: 57612 malloc size 960 allocate memory at 0x20011388, size: 972 release memory 0x20011388, size: 972 malloc size 3, but align to 4 allocate memory at 0x20011388, size: 24 malloc size 360 allocate memory at 0x200113a0, size: 372 release memory 0x200113a0, size: 372 malloc size 360 allocate memory at 0x200113a0, size: 372 release memory 0x200113a0, size: 372 malloc size 176 allocate memory at 0x200113a0, size: 188 release memory 0x200113a0, size: 188 malloc size 176 allocate memory at 0x200113a0, size: 188 release memory 0x200113a0, size: 188 malloc size 552 allocate memory at 0x200113a0, size: 564 malloc size 552 allocate memory at 0x200115d4, size: 564 release memory 0x200113a0, size: 564 release memory 0x200115d4, size: 564 malloc size 52 allocate memory at 0x200113a0, size: 64 allocate memory at 0x200113a0, size: 64 malloc size 116 allocate memory at 0x200113e0, size: 128 malloc size 32 allocate memory at 0x20011460, size: 44 malloc size 32 allocate memory at 0x2001148c, size: 44 release memory 0x20011460, size: 44 release memory 0x2001148c, size: 44 malloc size 116 allocate memory at 0x20011460, size: 128 malloc size 8 allocate memory at 0x200114e0, size: 24 malloc size 70, but align to 72 allocate memory at 0x200114f8, size: 84 release memory 0x200113e0, size: 128 release memory 0x200113a0, size: 64 release memory 0x200114e0, size: 24 release memory 0x20011460, size: 128 malloc size 12 allocate memory at 0x200113a0, size: 24 malloc size 15, but align to 16 allocate memory at 0x200113b8, size: 28 release memory 0x200114f8, size: 84 malloc size 48 allocate memory at 0x200113d4, size: 60 release memory 0x20011388, size: 24 malloc size 4 allocate memory at 0x20011388, size: 24 malloc size 1, but align to 4 allocate memory at 0x20011410, size: 24 malloc size 31, but align to 32 allocate memory at 0x20011428, size: 44 malloc size 52 allocate memory at 0x20011454, size: 64 allocate memory at 0x20011454, size: 64 malloc size 8 allocate memory at 0x20011494, size: 24 malloc size 16 allocate memory at 0x200114ac, size: 28 release memory 0x20011494, size: 24 malloc size 24 allocate memory at 0x200114c8, size: 36 release memory 0x200114ac, size: 28 malloc size 32 allocate memory at 0x20011494, size: 52 release memory 0x200114c8, size: 36 malloc size 16 allocate memory at 0x200114c8, size: 28 release memory 0x20011428, size: 44 release memory 0x20011410, size: 24 release memory 0x200113b8, size: 28 release memory 0x200113a0, size: 24 release memory 0x200113d4, size: 60 release memory 0x200147cc, size: 57612 release memory 0x200119e8, size: 92 release memory 0x20013120, size: 5804 n = 1 decoded QR-Code symbol "EEWorld STM32H5" len = 15 release memory 0x20010e04, size: 64 release memory 0x20011494, size: 52 release memory 0x200114c8, size: 28 release memory 0x20011454, size: 64 release memory 0x20010e44, size: 28 release memory 0x20010294, size: 60 release memory 0x20010268, size: 44 release memory 0x20010134, size: 308 release memory 0x20011d30, size: 2552 release memory 0x20012728, size: 2552 release memory 0x200102d0, size: 2868 release memory 0x2001008c, size: 168 45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok zbar count;56
通过对申请和释放的对应关系,我们可以分析得出问题所在,zbar库在图片识别后释放了img->data指针,而这个指针是在zbar调用外部申请的空间,是不需要zbar内部释放的,具体代码如下:
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<qr_img_width;i++) { for(j=0;j<qr_img_width;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库中做了释放操作,代码如下:
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; }
这里把这一句屏蔽,则可以解决问题,经过我测试,现在已经连续运行上千次
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