二維碼開源庫ZBar-MDK STM32F429移植

前兩篇文章已經實現ZBar在Windows平臺下的編譯和使用,本文將介紹如何把ZBar移植到STM32F429,IDE使用MDK。php

1. MDK工程設置

(1)不勾選Use MicroLIB ,使用ISO C。
如MDK 幫助文檔關於MicroLIB的介紹,故在硬件資源容許的狀況仍是優先使用ISO C。數組

 

(2)勾選C99 Mode,由於ZBar源碼是基於C99的函數

 


(3)不勾選Use Memory Layout From Target Dialog,使用自定義Scatter File測試

2.工程目錄結構

 

3. ZBar源碼修改地方

因爲MDK使用的編譯器不是GCC,故不能支持一些特殊GCC語法和相應的C庫函數。
(1) error.c和error.h文件中strdup函數報錯。
處理方法:屏蔽該函數相關代碼或者本身實現strdup函數
(2) 屏蔽img_scanner.c文件中的ui

.....
//#include <unistd.h>
//#include <time.h> /* clock_gettime */
//#include <sys/time.h> /* gettimeofday */
....
// struct timeval abstime;
// gettimeofday(&abstime, NULL);
// iscn->time = (abstime.tv_sec * 1000) + ((abstime.tv_usec / 500) + 1) / 2;
.....

(3) GCC默認void*爲char*,MDK的編譯器對void指針的加減操做看成錯誤處理
處理方法:把void指針強制轉換爲char指針

spa

4. 系統存儲空間分配


對於STM32來講ZBar對Heap消耗較大,跟解析的二維碼圖片大小有關,將系統未使用的內存 所有分配給Heap。
Scatter file 以下3d

LR_IROM1 0x08000000 0x00100000  {    ; load region size_region
    ER_IROM1 0x08000000 0x00100000  {  ; load address = execution address
    *.o (RESET, +First)
    *(InRoot$$Sections)
    .ANY (+RO)
    }
    

    RW_IRAM_DATA 0x20000000 0x00030000 {  ; RW data
    .ANY (+RW +ZI)
    }
    
    
    ARM_LIB_STACK 0x20030000 EMPTY -(0x20030000 - ImageLimit(RW_IRAM_DATA))  ; Stack region growing down
    { }
   
   
    RW_ERAM 0xD0000000 0x00800000 { ;Extern SDRAM
    main.o(+RW +ZI)
    }
    
    ARM_LIB_HEAP +0 EMPTY  (0xD0800000 - ImageLimit(RW_ERAM)) ; Heap region growing up
    { }
}

5. 修改默認的啓動文件startup_stm32f429_439xx.s


(1) Stack和Heap已經在Scatter文件中指定,故屏蔽startup_stm32f429_439xx.s中Stack和Heap的相關代碼。指針

;Stack_Size      EQU     0x00000400

                ;AREA    STACK, NOINIT, READWRITE, ALIGN=3
;Stack_Mem       SPACE   Stack_Size
;__initial_sp


;; <h> Heap Configuration
;;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
;; </h>

;Heap_Size       EQU     0x00000200

                ;AREA    HEAP, NOINIT, READWRITE, ALIGN=3
;__heap_base
;Heap_Mem        SPACE   Heap_Size
;__heap_limit

......

                 ;IF      :DEF:__MICROLIB
                
                 ;EXPORT  __initial_sp
                 ;EXPORT  __heap_base
                 ;EXPORT  __heap_limit
                
                 ;ELSE
                
                 ;IMPORT  __use_two_region_memory
                 ;EXPORT  __user_initial_stackheap
                 
;__user_initial_stackheap

                 ;LDR     R0, =  Heap_Mem
                 ;LDR     R1, =(Stack_Mem + Stack_Size)
                 ;LDR     R2, = (Heap_Mem +  Heap_Size)
                 ;LDR     R3, = Stack_Mem
                 ;BX      LR

                 ;ALIGN

                 ;ENDIF

 


(2) 把Scatter文件指定的Stack基地址賦給向量表的首地址code

.....
                IMPORT  |Image$$ARM_LIB_STACK$$Base|
__Vectors       DCD     |Image$$ARM_LIB_STACK$$Base|;__initial_sp               ; Top of Stack
.....

(3) 由於Heap分配在外部SDRAM中,故在進入__main前需初始化SDRAMorm

....
        IMPORT  SystemInit
        IMPORT  SDRAM_Init
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =SDRAM_Init
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP
....

 6.測試代碼

  以前Windows平臺下的測試例程是直接讀取PNG格式的二維碼,在STM32F429平臺下沒有移植文件系統和PNG解碼庫,爲了簡單起見,直接把待

測試的二維碼圖片轉換爲二值化數組,而後把該該數組傳給ZBar。

#include "type_define.h"
#include "usart.h"
#include "sdram.h" 
 #include "zbar.h"
#include "image.h"
//280X280的二維碼圖片灰度值數組
const uint8_t image_data_buf[] = {
.......
};
int Zbar_Test(void* raw, int width, int height)
{
      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);

    /* obtain image data */
    //int width = 0, height = 0;
    //void *raw = NULL;
    //get_data("barcode.png", &width, &height, &raw);

    /* 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);
    printf("n = %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("decoded %s symbol \"%s\"\r\n",
               zbar_get_symbol_name(typ), data);
        printf("len = %d\r\n",strlen(data));
        for(int k=0; k<strlen(data); k++)
        {
            printf("%X ", (uint8_t)data[k]);
        }
    }

    /* clean up */
    zbar_image_destroy(image);
    zbar_image_scanner_destroy(scanner);

    return(0);
}      

int main(void)
{    
    Usart_Init();   
    printf("Hello CJS\r\n ");    
    Zbar_Test((void* )image_data_buf,280,280);    
    while(1)
    { 
    
    }
  return 0;
}

7.運行結果

編譯下載到STM32F429後,運行結果以下

 

到此,ZBar已經能正常在STM32F429上運行了,但有點小問題,如上圖,會檢測到decoded I2/5 symbol "",緣由未知。

 

工程傳送門:http://www.openedv.com/forum.php?mod=viewthread&tid=266510&page=1#pid828789

相關文章
相關標籤/搜索