无线手持二维码识别项目是中山大学电子与信息工程学院(微电子学院)的工程应用训练课程的设计要求。项目是基于STM32F103开发的,开源代码:stm32f103zet6-qrcode-detect,bilibili:基于STM32F1的无线手持二维码识别项目。CSDN总目录:基于STM32F103的二维码识别项目。项目移植了Zbar库进行二维码识别,而非使用二维码识别模块。
此篇文章讲述Zbar库移植的实现。
二维码开源库ZBar STM32F429 移植-OpenEdv-开源电子网
STM32H5移植zbar记录 - Jayson_Ge - 博客园 (cnblogs.com)
前排感谢大佬们实现移植!
跟着教程走即可,注意下面的图的这两步不需要跟着做了。
我们使用正点原子的内存管理机制,移植他们的malloc函数进行内存管理。同时,我们使用了SRAM,所以也借鉴了正点原子这方面的代码。
【正点原子】战舰版视频(STM32F103)-哔哩哔哩之外部SRAM
【正点原子】战舰版视频(STM32F103)-哔哩哔哩之内存管理
移植后的具体代码在项目中详见下图:
Zbar移植后主函数最重要的代码部分为:
int Zbar_Test( int width, int height)
{
int a;
void *raw = (void* )data_buf;
zbar_image_scanner_t *scanner = NULL;
/* create a reader */
scanner = zbar_image_scanner_create();
/* configure the reader */
zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1);
/* wrap image data */
zbar_image_t *image = zbar_image_create();
zbar_image_set_format(image, *(int*)"Y800");
zbar_image_set_size(image, width, height);
zbar_image_set_data(image, raw, width * height, zbar_image_free_data);
/* scan the image for barcodes */
int n = zbar_scan_image(scanner, image);
if(n==0){LED4_ON();}
else{LED5_ON();}
printf("识别的二维码个数为 = %d\r\n", n);
/* extract results */
const zbar_symbol_t *symbol = zbar_image_first_symbol(image);
for(; symbol; symbol = zbar_symbol_next(symbol)) {
/* do something useful with results */
zbar_symbol_type_t typ = zbar_symbol_get_type(symbol);
const char *data = zbar_symbol_get_data(symbol);
printf("识别为 %s 结果是 \"%s\"\r\n",
}
/* clean up */
zbar_image_destroy(image);
zbar_image_scanner_destroy(scanner);
return(0);
}
注意该函数需要传入你需要检测的图片的长和宽,且Zbar的检测需要送入灰度图进行检测,不过博主为了方便直接将图片简单的二值化,也可以正常识别。之后函数通过 zbar_image_destroy(image);和 zbar_image_scanner_destroy(scanner);在检测后释放内存。
二值化的过程比较粗暴,但是能用,也就没有继续修改了。
if(color > 0x4500)
{
color = 0xffff;
colorQR = 0xff;
}
else
{
color = 0x0000;
colorQR = 0x00;
}
接下来是主函数里面的Init的一些说明,注意width和height在这里定义了,这个就是送去Zbar检测的长和宽,如果要修改代码这里的长宽要改掉。还有一个巨坑的bug:FSMC_SRAM_Init();、my_mem_init(SRAMIN);和my_mem_init(SRAMEX);必须放在最后,如果放在前面其他的初始化函数放在后面会直接导致程序跑飞。
GPIO_Config();//LED GPIO 初始化
USART_Config();
Systick_Config(72);
Buzzle_Init();
uint16_t width=240;
uint8_t height = 240;
int i=0;
SystemInit();//初始化RCC 设置系统主频为72MHZ
LCD_Init(); //液晶屏初始化
LCD_Clear(0xffff);
LCD_Clear(BLUE);
i=OV7670_Init();
delay_ms(1500);
OV7670_Light_Mode(0);
OV7670_Color_Saturation(2);
OV7670_Brightness(2);
OV7670_Contrast(2);
OV7670_Special_Effects(0);
EXTI7_Init();
OV7670_CS=0;
LCD_Clear(BLACK);
delay_ms(1500);
UART4_Init();
USART2_Init();
UART4_Init();
LED_Init();
FSMC_SRAM_Init();//初始化FSMC
my_mem_init(SRAMIN); //初始化内部内存池
my_mem_init(SRAMEX); //初始化内部内存池 内部内存池不够用