硬件准备
ADSP-EDU-BF533:BF533开发板
 AD-HP530ICE:ADI DSP仿真器
软件准备
Visual DSP++软件
硬件链接

功能介绍
作为一个最高600M主频,单核或双核的定点DSP,做图像处理还是挺行的,属于是老本行,那么我们后面一个系列,将会详细的说一说DSP做图像处理。
代码实现了将 RGB888 数据格式转为 RGB565 格式。板卡液晶屏和 VDSP 软件商 Image Viewer 工具上的 RGB565格式不同,其区别是 RGB 数据格式的位置,在液晶屏上,R 的数据位置位于低 5 位,B 数据位置位于高 5 位。在Image Viewer 工具上,R 数据位于高 5 位,B 数据位于低 5 位。为了方便查看,在代码中将这两种转换函数都列出,方便查看。
代码使用说明
RGB888 转 RGB565,以液晶屏格式为例:
dst[j+1] = src[i+2] &0xf8; //提取 5bit 的蓝色数据
 dst[j+1] |= ((src[i+1]>>5) & 0x07); //提取 3bit 的绿色高位数据
 dst[j] = ((src[i+1]<<3) & 0xe0); //提取 3bit 的绿色低位数据
 dst[j] |= ((src[i]>>3) &0x1f); //提取 5bit 的红色数据
在代码中,做了一个宏开关,当打开这个开关,转换后的数据格式为液晶屏 RGB565 的格式,当关闭开关,转换的数据可以直接通过 Image View 工具查看。
//#define LCD_FORMAT 1
代码中定义了两个 Buffer,in_buffer 中存放了 RGB888 格式的数据,通过”#include”指令将”.dat”文件倒入内存。
转换后输出的 RGB565 格式的数据存放在 out_buffer 中。
unsigned char in_buffer[391680]=
 {
 #include"RGB888_480_272.dat"
 };
 unsigned char out_buffer[261120];
调试步骤
- 将板卡连接仿真器,运行 VDSP 软件并连接板卡。
- 将工程 BF53x_RGB888_TO_RGB565.dpj 载入 VDSP 软件,编译并运行。
- 待代码停止,用 VDSP 下的 Image Viewer 工具以 RGB565 格式查看图像。其配置如下:

代码调试结果
在 Image View 窗口中可看到图像:

程序源码
#include <cdefBF533.h>
//#define LCD_FORMAT 1
unsigned char in_buffer[391680]=
 {
 #include"RGB888_480_272.dat"
 };
unsigned char out_buffer[261120];
void Set_PLL(unsigned int pmsel,unsigned int pssel)
 {
 unsigned int new_PLL_CTL; 
 *pPLL_DIV = pssel;
 asm(“ssync;”);
 new_PLL_CTL = (pmsel & 0x3f) << 9; 
 *pSIC_IWR |= 0xffffffff;
 if (new_PLL_CTL != *pPLL_CTL)
 {
 *pPLL_CTL = new_PLL_CTL;
 asm(“ssync;”);
 asm(“idle;”);
 }
 }
void Init_EBIU(void)
 {
 *pEBIU_AMBCTL0 = 0x7bb07bb0;
 *pEBIU_AMBCTL1 = 0xffc07bb0;
 *pEBIU_AMGCTL = 0x000f;
 }
#ifdef LCD_FORMAT
 void RGB888_RGB565(unsigned char *src, int src_len, unsigned char *dst)
 {
 int i = 0;
 int j = 0;
if (src_len % 3 != 0)
{
    return;
}
for (i = 0; i < src_len; i += 3)
{
     dst[j+1] = src[i+2] &0xf8; 			//B 
     dst[j+1] |= ((src[i+1]>>5) & 0x07);	//GH
     dst[j] = ((src[i+1]<<3) & 0xe0);  		//GL  
     dst[j] |= ((src[i]>>3) &0x1f); 		//R
    j += 2;  
    
}
}
 #else //VDSP Imgae Viewer Format
 void RGB888_RGB565(unsigned char *src, int src_len, unsigned char *dst)
 {
 int i = 0;
 int j = 0;
if (src_len % 3 != 0)
{
    return;
}
for (i = 0; i < src_len; i += 3)
{
     dst[j] = (src[i+2] >>3)&0x1f; 			//B 
     dst[j] |=((src[i+1]<<3) & 0xe0);    
     dst[j+1] = ((src[i+1]>>5) & 0x07);		//GL  
     dst[j+1] |= ((src[i]) &0xf8); 			//R
     j += 2;      
}
}
 #endif
void main(void)
 { 
 Set_PLL(16,4);
 Init_EBIU(); 
 RGB888_RGB565(in_buffer,391680, out_buffer);
 }
RGB888-565
// blackfin-edinburgh-core
 #include <sys/platform.h>
 #include <sys/anomaly_macros_rtl.h>
/
 // standard
 #define IVBh (EVT0 >> 16)
 #define IVBl (EVT0 & 0xFFFF)
 #define UNASSIGNED_VAL 0x8181
 #define INTERRUPT_BITS 0x400 // just IVG15
 #define SYSCFG_VALUE 0x30
.section/DOUBLEANY program;
.file_attr requiredForROMBoot;
.align 2;
start:
/* V D S G < i n s e r t − c o d e − v e r y − b e g i n n i n g > ∗ / . s t a r t o f u s e r c o d e v e r y b e g i n n i n g : / / I n s e r t a d d i t i o n a l c o d e t o b e e x e c u t e d b e f o r e a n y o t h e r S t a r t u p C o d e h e r e . / / T h i s c o d e i s p r e s e r v e d i f t h e C R T i s r e − g e n e r a t e d . . e n d o f u s e r c o d e v e r y b e g i n n i n g : / ∗ VDSG<insert-code-very-beginning> */ .start_of_user_code_very_beginning: // Insert additional code to be executed before any other Startup Code here. // This code is preserved if the CRT is re-generated. .end_of_user_code_very_beginning: /* VDSG<insert−code−very−beginning>∗/.startofusercodeverybeginning://InsertadditionalcodetobeexecutedbeforeanyotherStartupCodehere.//ThiscodeispreservediftheCRTisre−generated..endofusercodeverybeginning:/∗VDSG */
/
 // blackfin-edinburgh-core
 #if WA_05000109
 // Avoid Anomaly 05-00-0109
 R1 = SYSCFG_VALUE;
 SYSCFG = R1;
 #endif
/
 // standard
 #if WA_05000229
 // Avoid Anomaly 05-00-0229: DMA5_CONFIG and SPI_CTL not cleared on reset.
 R1 = 0x400;
 #if defined(ADSPBF538) || defined(ADSPBF539)
 P0.L = SPI0_CTL & 0xFFFF;
 P0.H = SPI0_CTL >> 16;
 W[P0] = R1.L;
 #else
 P0.L = SPI_CTL & 0xFFFF;
 P0.H = SPI_CTL >> 16;
 W[P0] = R1.L;
 #endif
 P0.L = DMA5_CONFIG & 0xFFFF;
 P0.H = DMA5_CONFIG >> 16;
 R1 = 0;
 W[P0] = R1.L;
 #endif
 // Clear loop counters to disable hardware loops
 R7 = 0;
 LC0 = R7;
 LC1 = R7;
// Clear the DAG Length regs, to force linear addressing
L0 = R7;
L1 = R7;
L2 = R7;
L3 = R7;
// Clear ITEST_COMMAND and DTEST_COMMAND registers
I0.L = (ITEST_COMMAND & 0xFFFF);
I0.H = (ITEST_COMMAND >> 16);
I1.L = (DTEST_COMMAND & 0xFFFF);
I1.H = (DTEST_COMMAND >> 16);
[I0] = R7;
[I1] = R7;
CSYNC;
// Initialise the Event Vector table.
P0.H = IVBh;
P0.L = IVBl;
// Install __unknown_exception_occurred in EVT so that
// there is defined behaviour.
P0 += 2*4;		// Skip Emulation and Reset
P1 = 13;
R1.L = __unknown_exception_occurred;
R1.H = __unknown_exception_occurred;
LSETUP (.ivt,.ivt) LC0 = P1;
.ivt: [P0++] = R1;
// Set IVG15's handler to be the start of the mode-change
// code. Then, before we return from the Reset back to user
// mode, we'll raise IVG15. This will mean we stay in supervisor
// mode, and continue from the mode-change point, but at a
// much lower priority.
P1.H = supervisor_mode;
P1.L = supervisor_mode;
[P0] = P1;
/
 // standard
 // Initialise the stack.
 // Note: this points just past the end of the section.
 // First write should be with [–SP].
 SP.L=ldf_stack_end;
 SP.H=ldf_stack_end;
 usp = sp;
// We're still in supervisor mode at the moment, so the FP
// needs to point to the supervisor stack.
FP = SP;
// Make space for incoming "parameters" for functions
// we call from here:
SP += -12;
R0 = INTERRUPT_BITS;
R0 <<= 5;	// Bits 0-4 not settable.
/
 // install-default-handlers
 CALL.X __install_default_handlers;
.extern __install_default_handlers;
 .type __install_default_handlers,STT_FUNC;
/
 // standard
 R1 = SYSCFG;
 R4 = R0; // Save modified list
 BITSET(R1,1);
 SYSCFG = R1; // Enable the cycle counter
/
 // blackfin-edinburgh-core
 #if WA_05000137 || WA_05000162
 // Avoid Anomaly 02-00-0137
 // Set the port preferences of DAG0 and DAG1 to be
 // different; this gives better performance when
 // performing daul-dag operations on SDRAM.
 P0.L = DMEM_CONTROL & 0xFFFF;
 P0.H = DMEM_CONTROL >> 16;
 R0 = [P0];
 BITSET(R0, 12);
 BITCLR(R0, 13);
 [P0] = R0;
 CSYNC;
 #endif
/* V D S G < i n s e r t − c o d e − e a r l y − s t a r t u p > ∗ / . s t a r t o f u s e r c o d e 1 : / / I n s e r t a d d i t i o n a l c o d e t o b e e x e c u t e d b e f o r e m a i n h e r e . / / T h i s c o d e i s p r e s e r v e d i f t h e C R T i s r e − g e n e r a t e d . . e n d o f u s e r c o d e 1 : / ∗ VDSG<insert-code-early-startup> */ .start_of_user_code1: // Insert additional code to be executed before main here. // This code is preserved if the CRT is re-generated. .end_of_user_code1: /* VDSG<insert−code−early−startup>∗/.startofusercode1://Insertadditionalcodetobeexecutedbeforemainhere.//ThiscodeispreservediftheCRTisre−generated..endofusercode1:/∗VDSG */
/
 // standard
 // Enable interrupts
 STI R4; // Using the mask from default handlers
 RAISE 15;
// Move the processor into user mode.
P0.L=still_interrupt_in_ipend;
P0.H=still_interrupt_in_ipend;
RETI=P0;
NOP;		// Purely to prevent a stall warning
still_interrupt_in_ipend:
 // execute RTI until we’ve finished servicing all
 // interrupts of priority higher than IVG15. Normally one
 // would expect to only have the reset interrupt in IPEND
 // being serviced, but occasionally when debugging this may
 // not be the case - if restart is hit when servicing an
 // interrupt.
 //
 // When we clear all bits from IPEND, we’ll enter user mode,
 // then we’ll automatically jump to supervisor_mode to start
 // servicing IVG15 (which we will ‘service’ for the whole
 // program, so that the program is in supervisor mode.
 // Need to do this to ‘finish’ servicing the reset interupt.
 RTI;
supervisor_mode:
 [–SP] = RETI; // re-enables the interrupt system
 R0.L = UNASSIGNED_VAL;
 R0.H = UNASSIGNED_VAL;
// Push a RETS and Old FP onto the stack, for sanity.
[--SP]=R0;
[--SP]=R0;
// Make sure the FP is sensible.
FP = SP;
// Leave space for incoming "parameters"
SP += -12;
/* V D S G < i n s e r t − c o d e − b e f o r e − d e v i c e − i n i t i a l i z a t i o n > ∗ / . s t a r t o f u s e r c o d e 2 : / / I n s e r t a d d i t i o n a l c o d e t o b e e x e c u t e d b e f o r e d e v i c e i n i t i a l i z a t i o n h e r e . / / T h i s c o d e i s p r e s e r v e d i f t h e C R T i s r e − g e n e r a t e d . . e n d o f u s e r c o d e 2 : / ∗ VDSG<insert-code-before-device-initialization> */ .start_of_user_code2: // Insert additional code to be executed before device initialization here. // This code is preserved if the CRT is re-generated. .end_of_user_code2: /* VDSG<insert−code−before−device−initialization>∗/.startofusercode2://Insertadditionalcodetobeexecutedbeforedeviceinitializationhere.//ThiscodeispreservediftheCRTisre−generated..endofusercode2:/∗VDSG */
/
 // device-initialization
 // initialise the devices known about for stdio.
 CALL.X _init_devtab;
 .extern _init_devtab;
 .type _init_devtab,STT_FUNC;
/
 // cplusplus
 CALL.X ___ctorloop; // run global scope C++ constructors
 .extern ___ctorloop;
 .type ___ctorloop,STT_FUNC;
/* V D S G < i n s e r t − c o d e − b e f o r e − m a i n − e n t r y > ∗ / . s t a r t o f u s e r c o d e 3 : / / I n s e r t a d d i t i o n a l c o d e t o b e e x e c u t e d b e f o r e m a i n h e r e . / / T h i s c o d e i s p r e s e r v e d i f t h e C R T i s r e − g e n e r a t e d . . e n d o f u s e r c o d e 3 : / ∗ VDSG<insert-code-before-main-entry> */ .start_of_user_code3: // Insert additional code to be executed before main here. // This code is preserved if the CRT is re-generated. .end_of_user_code3: /* VDSG<insert−code−before−main−entry>∗/.startofusercode3://Insertadditionalcodetobeexecutedbeforemainhere.//ThiscodeispreservediftheCRTisre−generated..endofusercode3:/∗VDSG */
/
 // get-args
 // Read command-line arguments.
 CALL.X __getargv;
 r1.l=__Argv;
 r1.h=__Argv;
.extern __getargv;
 .type __getargv,STT_FUNC;
 .extern __Argv;
 .type __Argv,STT_OBJECT;
/
 // standard
 // Call the application program.
 CALL.X _main;
/
 // call-exit
 CALL.X _exit; // passing in main’s return value
 .extern _exit;
 .type _exit,STT_FUNC;
/
 // standard
 .start.end: // Required by the linker to know the size of the routine
 // that is needed for absolute placement.
.global start;
 .type start,STT_FUNC;
 .extern _main;
 .type _main,STT_FUNC;
 .extern ldf_stack_end;
 .extern __unknown_exception_occurred;
 .type __unknown_exception_occurred,STT_FUNC;
/
 // cplusplus
 .section/DOUBLEANY ctor;
 .align 4;
 ___ctor_table:
 .byte4=0;
 .global ___ctor_table;
 .type ___ctor_table,STT_OBJECT;
 .section/DOUBLEANY .gdt;
 .align 4;
 ___eh_gdt:
 .global ___eh_gdt;
 .byte4=0;
 .type ___eh_gdt,STT_OBJECT;
 .section/DOUBLEANY .frt;
 .align 4;
 ___eh_frt:
 .global ___eh_frt;
 .byte4=0;
 .type ___eh_frt,STT_OBJECT;

















