硬件准备
ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器
软件准备
Visual DSP++软件
硬件链接
功能介绍
代码实现了摄像头拍摄一张 640480 大小,YUV422 格式的图片,然后将图片转成 RGB565 格式,裁剪为 480272尺寸,将其显示在液晶屏上。通过点击触摸屏,可以拍摄下一张图片显示在液晶屏上。
代码使用说明
摄像头采集到 YUV422 的图像后,通过以下函数将图像转为 480*272 尺寸的 RGB565 格式:
ConvertYUY2toRGB24(rgbdata_buffer,yuvdata_buffer, 640,480);
//将 YUV422 格式数据转为 RGB888 格式
size_convert(rgbdata_buffer,DisplayBuffer);
//将 640480 尺寸的数据裁剪为 480272 尺寸
RGB888_RGB565(DisplayBuffer, 391680,DisplayBuffer_565);
//将 RGB888 格式的数据转为 RGB565 格式
代码实验步骤
代码实验结果
待图像显示出一张拍摄到的图片时,点击触摸屏,可拍摄下一张图片,并显示到液晶屏上。
程序源码
cap.s
static int WIDTH;
static int HEIGHT;
static int IMG_SIZE;
static int fd_ppi;
unsigned char *in_buff;
typedef unsigned int dword_t;
typedef unsigned short word_t;
typedef unsigned char BYTE;
#define BI_RGB 0L
#define BI_RLE8 1L
#define BI_RLE4 2L
#define BI_BITFIELDS 3L
#pragma pack (1)
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
#pragma pack (0)
#define BMP_WITH 640
#define BMP_HEGHT 480
#define Y_DATA 1
#define YUYV_DATA 2
typedef struct tagTABLE_YUV2RGB
{
unsigned short YtoR[256];
unsigned short YtoG[256];
unsigned short YtoB[256];
unsigned short UtoG[256];
unsigned short UtoB[256];
unsigned short VtoR[256];
unsigned short VtoG[256];
}TABLE_YUV2RGB;
TABLE_YUV2RGB table_yuv2rgb;
void Init()
{
long j = 0;
for (j = 0; j < 256; ++j)
{
table_yuv2rgb.YtoR[j] = table_yuv2rgb.YtoG[j] = table_yuv2rgb.YtoB[j] = (unsigned short)(j << 7);
table_yuv2rgb.VtoR[j] = j * 180;
table_yuv2rgb.VtoG[j] = j * 91;
table_yuv2rgb.UtoG[j] = j * 44;
table_yuv2rgb.UtoB[j] = j * 226;
}
}
void ConvertYUY2toRGB24(BYTE* pDst, BYTE* pSrc, int w, int h)
{
long m = 0;
long k = 0;
int n=w/2;
int dec=w*4;
int tmpR0 = 0;
int tmpG0 = 0;
int tmpB0 = 0;
int tmpR1 = 0;
int tmpG1 = 0;
int tmpB1 = 0;
int i;
int j;
k=(h-1)*w<<1;
for( i=h-1;i>-1;i--)
{
for(j=0;j> 7;
tmpG0 = (table_yuv2rgb.YtoG[pSrc[k + 0]] - table_yuv2rgb.VtoG[pSrc[k + 3]] - table_yuv2rgb.UtoG[pSrc[k + 1]] + 17264) >> 7;
tmpB0 = (table_yuv2rgb.YtoB[pSrc[k + 0]] + table_yuv2rgb.UtoB[pSrc[k + 1]] - 28928) >> 7;
tmpR1 = (table_yuv2rgb.YtoR[pSrc[k + 2]] + table_yuv2rgb.VtoR[pSrc[k + 3]] - 22906) >> 7;
tmpG1 = (table_yuv2rgb.YtoG[pSrc[k + 2]] - table_yuv2rgb.VtoG[pSrc[k + 3]] - table_yuv2rgb.UtoG[pSrc[k + 1]] + 17264) >> 7;
tmpB1 = (table_yuv2rgb.YtoB[pSrc[k + 2]] + table_yuv2rgb.UtoB[pSrc[k + 1]] - 28928) >> 7;
if (tmpR0 > 255) tmpR0 = 255;
if (tmpG0 > 255) tmpG0 = 255;
if (tmpB0 > 255) tmpB0 = 255;
if (tmpR1 > 255) tmpR1 = 255;
if (tmpG1 > 255) tmpG1 = 255;
if (tmpB1 > 255) tmpB1 = 255;
if (tmpR0 < 0) tmpR0 = 0;
if (tmpG0 < 0) tmpG0 = 0;
if (tmpB0 < 0) tmpB0 = 0;
if (tmpR1 < 0) tmpR1 = 0;
if (tmpG1 < 0) tmpG1 = 0;
if (tmpB1 < 0) tmpB1 = 0;
pDst[m + 0] = tmpB0;
pDst[m + 1] = tmpG0;
pDst[m + 2] = tmpR0;
pDst[m + 3] = tmpB1;
pDst[m + 4] = tmpG1;
pDst[m + 5] = tmpR1;
k += 4;
m += 6;
}
k=k-dec;
}
}
cmos.c
#include
#include"i2c.h"
#define OV9653_ADDRESS 0x60
static i2c_device mcu_i2c;
void init_OV9653(void);
int ov9653_write(unsigned char addr, unsigned char dat);
int ov9653_read(unsigned char addr, unsigned char * buf);
/****************************************************************************
/****************************************************************************
名称 :Init_OV9653
功能 : CMOS 130万 内部寄存器配置信息
入口参数 :无
出口参数 :无
****************************************************************************/
void init_OV9653(void)
{
mcu_i2c.sclk = PF0; //时钟PF脚
mcu_i2c.sdata = PF1; //数据PF脚
mcu_i2c.low_ns = 7000; //低电平延时 ns
mcu_i2c.high_ns = 6000; //高电平延时 ns
i2c_init(&mcu_i2c);
ov9653_write(0x12,0x80);
ov9653_write(0x12,0x80);
ov9653_write(0x11,0x81);
ov9653_write(0x6b,0x0a);
ov9653_write(0x6a,0x3e);
ov9653_write(0x3b,0x09);
ov9653_write(0x13,0xe0);
ov9653_write(0x01,0x80);
ov9653_write(0x02,0x80);
ov9653_write(0x00,0x00);
ov9653_write(0x10,0x00);
ov9653_write(0x13,0xe5);
ov9653_write(0x39,0x43);
ov9653_write(0x38,0x12);
ov9653_write(0x37,0x00);
ov9653_write(0x35,0x91);
ov9653_write(0x0e,0x20);
ov9653_write(0x1e,0x34);
ov9653_write(0xA8,0x80);
ov9653_write(0x12,0x40);
ov9653_write(0x04,0x00);
ov9653_write(0x0c,0x04);
ov9653_write(0x0d,0x80);
ov9653_write(0x18,0xc6);
ov9653_write(0x17,0x26);
ov9653_write(0x32,0xad);
ov9653_write(0x03,0x00);
ov9653_write(0x1a,0x3d);
ov9653_write(0x19,0x01);
ov9653_write(0x3f,0xa6);
ov9653_write(0x14,0x1a);
ov9653_write(0x15,0x02);
ov9653_write(0x41,0x12);
ov9653_write(0x42,0x08);
ov9653_write(0x1b,0x00);
ov9653_write(0x16,0x06);
ov9653_write(0x33,0xe2);
ov9653_write(0x49,0x60);
ov9653_write(0x34,0x16);
ov9653_write(0x96,0x04);
ov9653_write(0x3a,0x00);
ov9653_write(0x8e,0x00);
ov9653_write(0x3c,0x77);
ov9653_write(0x8B,0x06);
ov9653_write(0x94,0x88);
ov9653_write(0x95,0x88);
ov9653_write(0x40,0xc1);
ov9653_write(0x29,0x3f);
ov9653_write(0x0f,0x42);
ov9653_write(0x3d,0x92);
ov9653_write(0x69,0x40);
ov9653_write(0x5C,0xb9);
ov9653_write(0x5D,0x96);
ov9653_write(0x5E,0x10);
ov9653_write(0x59,0xc0);
ov9653_write(0x5A,0xaf);
ov9653_write(0x5B,0x55);
ov9653_write(0x43,0xf0);
ov9653_write(0x44,0x10);
ov9653_write(0x45,0x68);
ov9653_write(0x46,0x96);
ov9653_write(0x47,0x60);
ov9653_write(0x48,0x80);
ov9653_write(0x5F,0xe0);
ov9653_write(0x60,0x8c);
ov9653_write(0x61,0x20);
ov9653_write(0xa5,0xd9);
ov9653_write(0xa4,0x74);
ov9653_write(0x8d,0xc2);
ov9653_write(0x13,0xe7);
ov9653_write(0x4f,0x3a);
ov9653_write(0x50,0x3d);
ov9653_write(0x51,0x03);
ov9653_write(0x52,0x12);
ov9653_write(0x53,0x26);
ov9653_write(0x54,0x38);
ov9653_write(0x55,0x40);
ov9653_write(0x56,0x40);
ov9653_write(0x57,0x40);
ov9653_write(0x58,0x0d);
ov9653_write(0x8C,0x23);
ov9653_write(0x3E,0x02);
ov9653_write(0xa9,0xb8);
ov9653_write(0xaa,0x92);
ov9653_write(0xab,0x0a);
ov9653_write(0x8f,0xdf);
ov9653_write(0x90,0x00);
ov9653_write(0x91,0x00);
ov9653_write(0x9f,0x00);
ov9653_write(0xa0,0x00);
ov9653_write(0x3A,0x01);
ov9653_write(0x24,0x80);
ov9653_write(0x25,0x70);
ov9653_write(0x26,0xd3);
ov9653_write(0x2a,0x10);
ov9653_write(0x2b,0x40);
ov9653_write(0x6c,0x40);
ov9653_write(0x6d,0x30);
ov9653_write(0x6e,0x4b);
ov9653_write(0x6f,0x60);
ov9653_write(0x70,0x70);
ov9653_write(0x71,0x70);
ov9653_write(0x72,0x70);
ov9653_write(0x73,0x70);
ov9653_write(0x74,0x60);
ov9653_write(0x75,0x60);
ov9653_write(0x76,0x50);
ov9653_write(0x77,0x48);
ov9653_write(0x78,0x3a);
ov9653_write(0x79,0x2e);
ov9653_write(0x7a,0x28);
ov9653_write(0x7b,0x22);
ov9653_write(0x7c,0x04);
ov9653_write(0x7d,0x07);
ov9653_write(0x7e,0x10);
ov9653_write(0x7f,0x28);
ov9653_write(0x80,0x36);
ov9653_write(0x81,0x44);
ov9653_write(0x82,0x52);
ov9653_write(0x83,0x60);
ov9653_write(0x84,0x6c);
ov9653_write(0x85,0x78);
ov9653_write(0x86,0x8c);
ov9653_write(0x87,0x9e);
ov9653_write(0x88,0xbb);
ov9653_write(0x89,0xd2);
ov9653_write(0x8a,0xe6);
}
cpu.c
#include
/**********************************************************************************
/****************************************************************************
void Init_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0xffc0ffc0;
*pEBIU_AMGCTL = 0x000f;
}
/****************************************************************************
/****************************************************************************
void Init_Timers0(int dat)
{
*pTIMER0_CONFIG = 0x0019;
*pTIMER0_WIDTH = dat;
*pTIMER0_PERIOD = 2000;
}
void Enable_Timers0(void)
{
*pTIMER_ENABLE|= 0x0001;
asm(“ssync;”);
}
void Disable_Timers0(void)
{
*pTIMER_DISABLE |= 0x0001;
}
i2c.c
#include
#include “i2c.h”
#define CORE_CLK_IN 25 * 1000 * 1000
#define SET_PF(pf)
do{
*pFIO_FLAG_S = (pf);
ssync();
}while(0)
#define CLR_PF(pf)
do{
*pFIO_FLAG_C = (pf);
ssync();
}while(0)
#define SET_PF_OUTPUT(pf)
do{
*pFIO_INEN &= ~(pf);
*pFIO_DIR |= (pf);
ssync();
}while(0)
#define SET_PF_INPUT(pf)
do{
*pFIO_DIR &= ~(pf);
*pFIO_INEN |= (pf);
ssync();
}while(0)
int get_core_clk(void)
{
int tempPLLCTL;
int _DF;
int VCO;
int MSEL1;
tempPLLCTL = *pPLL_CTL;
MSEL1 = ((tempPLLCTL & 0x7E00) >> 9);
_DF = tempPLLCTL & 0x0001;
VCO = MSEL1 * __CORE_CLK_IN__;
if(_DF == 1)
VCO /= 2;
return VCO;
}
void delay_ns(unsigned int core_clock, unsigned long long count)
{
count *= core_clock;
count /= 1000000000;
while(count–);
}
int _get_sdata(i2c_device * dev)
{
return ((*pFIO_FLAG_D & dev->sdata) ? 1 : 0);
}
void i2c_init(i2c_device * dev)
{
dev->core_clock = get_core_clk();
dev->delay_ns = delay_ns;
*pFIO_DIR |= dev->sclk | dev->sdata;
ssync();
}
void i2c_deinit(i2c_device * dev)
{
dev->sclk = 0;
dev->sdata = 0;
*pFIO_DIR &= ~(dev->sclk | dev->sdata);
ssync();
}
void i2c_start(i2c_device * dev)
{
SET_PF_OUTPUT(dev->sdata);
SET_PF_OUTPUT(dev->sclk);
SET_PF(dev->sdata);
SET_PF(dev->sclk);
delay_ns(dev->core_clock, dev->high_ns);
CLR_PF(dev->sdata);
delay_ns(dev->core_clock, dev->low_ns);
CLR_PF(dev->sclk);
delay_ns(dev->core_clock, dev->low_ns);
}
void i2c_stop(i2c_device * dev)
{
CLR_PF(dev->sclk);
delay_ns(dev->core_clock, dev->low_ns);
SET_PF_OUTPUT(dev->sdata);
CLR_PF(dev->sdata);
delay_ns(dev->core_clock, dev->low_ns);
SET_PF_INPUT(dev->sclk);
delay_ns(dev->core_clock, dev->high_ns);
SET_PF_INPUT(dev->sdata);
delay_ns(dev->core_clock, dev->high_ns);
}
int i2c_read_ack(i2c_device * dev)
{
int ret = 0;
SET_PF_INPUT(dev->sdata);
delay_ns(dev->core_clock, dev->high_ns/3);
SET_PF(dev->sclk);
delay_ns(dev->core_clock, dev->high_ns/3);
ret = _get_sdata(dev);
delay_ns(dev->core_clock, dev->high_ns/3);
CLR_PF(dev->sclk);
delay_ns(dev->core_clock, dev->low_ns);
SET_PF_OUTPUT(dev->sdata);
return ret;
}
int i2c_wait_slave(i2c_device * dev, unsigned int time_out)
{
int ret;
int count = time_out * 2 / dev->high_ns;
SET_PF_INPUT(dev->sclk);
delay_ns(dev->core_clock, dev->high_ns/2);
do{
ret = *pFIO_FLAG_D & dev->sclk;
if(ret)
break;
delay_ns(dev->core_clock, dev->high_ns/2);
}while(count--);
SET_PF_OUTPUT(dev->sclk);
return !ret;
}
void i2c_write_ack(i2c_device * dev)
{
SET_PF_OUTPUT(dev->sdata);
CLR_PF(dev->sdata);
delay_ns(dev->core_clock, dev->high_ns/2);
SET_PF(dev->sclk);
delay_ns(dev->core_clock, dev->high_ns);
CLR_PF(dev->sclk);
delay_ns(dev->core_clock, dev->low_ns);
}
int i2c_write(i2c_device * dev, unsigned char value, int need_ack)
{
int ret = -1;
unsigned char index;
SET_PF_OUTPUT(dev->sdata);
//send 8 bits to slave
for(index = 0; index < 8; index++){
//send one bit to the i2c bus
if((value<sdata);
} else {
CLR_PF(dev->sdata);
}
delay_ns(dev->core_clock, dev->low_ns/2);
SET_PF(dev->sclk);
delay_ns(dev->core_clock, dev->high_ns);
CLR_PF(dev->sclk);
delay_ns(dev->core_clock, dev->low_ns/2);
}
if(need_ack){
ret = i2c_read_ack(dev);
}
return ret;
}
int i2c_read(i2c_device * dev, unsigned char * value, int send_ack)
{
unsigned char index;
*value = 0x00;
SET_PF_INPUT(dev->sdata);
delay_ns(dev->core_clock, dev->high_ns/2);
//get 8 bits from the device
for(index = 0; index < 8; index++){
SET_PF(dev->sclk);
delay_ns(dev->core_clock, dev->high_ns/2);
*value <<= 1;
*value |= _get_sdata(dev);
delay_ns(dev->core_clock, dev->high_ns/2);
CLR_PF(dev->sclk);
delay_ns(dev->core_clock, dev->low_ns);
}
// send ack to slave
if(send_ack){
i2c_write_ack(dev);
}
return *value;
}
int.c
#include
#include
#include “cpld.h”
EX_INTERRUPT_HANDLER(FlagA_ISR);
EX_INTERRUPT_HANDLER(DMA0_PPI_ISR);
void Init_Flags(void)
{
*pFIO_INEN = 0x0001;
*pFIO_DIR = 0x0000;
*pFIO_EDGE = 0x0001;
*pFIO_POLAR = 0x0001;
*pFIO_MASKA_D = 0x0001;
}
void Init_Interrupts(void)
{
*pSIC_IAR0 = 0xffffffff;
*pSIC_IAR1 = 0xfffffff1;
*pSIC_IAR2 = 0xffff5fff;
register_handler(ik_ivg8, DMA0_PPI_ISR);
register_handler(ik_ivg12, FlagA_ISR);
*pSIC_IMASK = 0x00000100;
}
int cmos_flag;
EX_INTERRUPT_HANDLER(FlagA_ISR)
{
unsigned char interrupt=0;
interrupt = (~*pINTERRUPT_DAT&0x7f);
if(interrupt&0x02)
{
*pSIC_IMASK = 0x00000100;
LCDBK_Disable();
PPI_TMR_DMAR_Disable();
delay(1000000);
CMOS_Enable();
delay(1000000);
*pPPI_CONTROL = 0;
*pDMA0_CONFIG = 0;
Video_Frame_Capture();
}
*pFIO_FLAG_C = 0x0001;
}
main.c
#include
/****************************************************************************
ppi.c
#include
#include
unsigned char yuvdata_buffer[4801280];
unsigned char rgbdata_buffer[4801920];
unsigned char DisplayBuffer[2721440] ;
unsigned char DisplayBuffer_565[272960] ;
EX_INTERRUPT_HANDLER(DMA0_PPI_ISR);
void size_convert(unsigned char src, unsigned char dst)
{
int i;
int j;
for(i=0;i<272;i++)
{
for(j=0;j<1920;j++)
{
dst[((i4803)+j)]=src[(271-i)6403+j];
}
}
}
/****************************************************************************
/****************************************************************************
int img_count = 0;
EX_INTERRUPT_HANDLER(DMA0_PPI_ISR)
{
*pDMA0_IRQ_STATUS = 0x1;
img_count++;
if(img_count<10)
{
Video_Frame_Capture();
}
else
{
img_count = 0;
*pPPI_CONTROL &= 0xfffe;
*pSIC_IMASK = 0x00000000;
Init();
ConvertYUY2toRGB24(rgbdata_buffer,yuvdata_buffer, 640,480);
size_convert(rgbdata_buffer,DisplayBuffer);
RGB888_RGB565(DisplayBuffer, 391680,DisplayBuffer_565);
*pPPI_CONTROL = 0;
*pDMA0_CONFIG = 0;
InitDMA();
InitPPI();
InitTimer();
PPI_TMR_DMA_Enable();
LCD_Enable();
Init_Timers0(1999);//1~1999 控制背光亮度
Enable_Timers0();
LCDBK_Enable();
*pSIC_IMASK = 0x00080000;
}
}
lcd.c
#include
extern unsigned char DisplayBuffer_565[272*960] ;
void InitDMA(void)
{
int addr;
addr = &DisplayBuffer_565;
addr -= 1920;
*pDMA0_START_ADDR = addr;
*pDMA0_X_COUNT = 480;
*pDMA0_X_MODIFY = 2;
*pDMA0_Y_COUNT = 286;
*pDMA0_Y_MODIFY = 2;
*pDMA0_CONFIG = 0x1034;
}
void InitPPI(void)
{
*pPPI_CONTROL = 0x781e;
*pPPI_DELAY = 0;
*pPPI_COUNT = 479;
*pPPI_FRAME = 286;
}
void InitTimer(void)
{
*pTIMER1_PERIOD = 525;
*pTIMER1_WIDTH = 41;
*pTIMER1_CONFIG = 0x00a9;
*pTIMER2_PERIOD = 150150;
*pTIMER2_WIDTH = 5250;
*pTIMER2_CONFIG = 0x00a9;
}
void PPI_TMR_DMA_Enable(void)
{
*pDMA0_CONFIG |= 0x1;
asm(“ssync;”);
InitTimer();
*pPPI_CONTROL |= 0x1;
asm(“ssync;”);
*pTIMER_ENABLE|= 0x0006;
asm(“ssync;”);
}
void PPI_TMR_DMAR_Disable(void)
{
*pDMA0_CONFIG &= (~0x1);
*pPPI_CONTROL &= (~0x1);
*pTIMER_DISABLE|= 0x0006;
}
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] &0xf8; //B
dst[j+1] |= ((src[i+1]>>5) & 0x07);//GH
dst[j] = ((src[i+1]<<3) & 0xe0); //GL
dst[j] |= ((src[i+2]>>3) &0x1f); //R
j += 2;
}
}