打印
[Kinetis]

【FRDM-K64F开发笔记】FRDM图像采集及显示

[复制链接]
1812|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
E-Kaia|  楼主 | 2016-1-23 21:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在申请FRDM-K64时提到了对图像的采集,随着对飞思卡尔M4平台的学习,现在一个简单的图像采集完全不在话下,本demo采用KSDK编写,主要涉及到的接口有SCCB和SPI以及一个摄像头的并口,利用FRDM-K64上的DSPI驱动一个串口显示屏用于显示,虽然SCCB是一个类似于I2C的接口,但是在便于移植的前提下没有采用FRAM-K64上的硬件I2C接口,而直接使用模拟I2C,在摄像头8位的并口方面由于没有在FRDM-K64上找到连续的8位GPIO,所以只能选择同一PORT上的两个连续的四位进行拼接,这样大大降低了摄像头采集时的速度,主要接口连线如下
PTD6<-------------->MOSI
PTD7<-------------->MISO(部分串口屏可以不接)
PTD5<-------------->MCLK
PTD4<-------------->CS
PTB20<-------------->RS
PTC18<-------------->BL
PTC16<-------------->WE
PTC17<-------------->WRST
PTB9<-------------->VSYNC
PTA1<-------------->RCLK
PTB23<-------------->PRST
PTA2<-------------->OE
PTC0<-------------->DB0
PTC1<-------------->DB1
PTC2<-------------->DB2
PTC3<-------------->DB3
PTC8<-------------->DB4
PTC9<-------------->DB5
PTC10<-------------->DB6
PTC11<-------------->DB7
PTC15<-------------->SCK
PTC14<-------------->SDA
       以上是所有的接口连线,使用的摄像头是OV7725,主要是通过SCCB对摄像头进行配置,配置相关寄存器(和LCD的初始化类似),由于我的显示屏是176*240这种奇葩的分辨率,所以我将OV7725设置成输出176*240分辨率的RGB数据,然后按照一定时序进行采集,这个OV7725摄像头上带有FIFO,话说如果FIFO没有的话估计M4也无法采集,貌似飞思卡尔的K64没有摄像头接口。
       而LCD驱动方面主要通过K64的DSPI,上篇帖子具体讲了KSDK编写的DSPI驱动FLASH的方法,本文就不再多讲,只要将驱动FLASH的底层函数简单的改一下就行了(主要是FLASH可读可写,我这个LCD是只能写不能读的),实际LCD驱动好后只有大概9FPS,相当慢的速度了,DSPI还是使用的最高速度30M,然而效果只有这样,估计是我这块LCD的瓶颈了吧。
       在图像采集时由于对数据进行了移位拼接大大降低了采集速度,本身可以达到的60FPS的采集速度在K64上也就只能实现9FPS,再加上龟速的显示最终效果只有5FPS,不尽人意,但是对飞思卡尔K64平台的学习也是挺好的。

由于FRDM上都是排插,而杜邦线也是排插,只能在排插上接上排针进行连接,这样连接同时降低了系统的稳定性,图像也出现了一点小瑕疵,不过也没有办法,毕竟没有公母头的排线。桌子比较乱见谅了,附件是完整的采集显示程序,主要还是IAR平台的keil下没有搞。

相关帖子

沙发
E-Kaia|  楼主 | 2016-1-23 21:30 | 只看该作者
#include "ov7725.h"
#include "spi_lcd.h"
#include "sccb.h"
#include "delay.h"
OV7725_IDTypeDef OV7725ID;
u8 ov_sta,ov_frame;
extern uint32_t count;
#define CAMERA_H 120
#define CAMERA_W 160
/* 寄存器参数配置 */
typedef struct Reg
{
  uint8_t Address;                               /*寄存器地址*/
  uint8_t Value;                           /*寄存器值*/
}Reg_Info;
Reg_Info Sensor_Config1[] =
{
  {OV7725_CLKRC,     0x00}, /*clock config*/
  {OV7725_COM7,      0x46}, /*QVGA RGB565 */
  {OV7725_HSTART,    0x3f},
  {OV7725_HSIZE,     0x50},
  {OV7725_VSTRT,     0x03},
  {OV7725_VSIZE,     0x78},
  {OV7725_HREF,      0x00},
  {OV7725_HOutSize,  0x2c},
  {OV7725_VOutSize,  0x78},
  {OV7725_EXHCH,     0x00},
  
  /*DSP control*/
  {OV7725_TGT_B,     0x7f},
  {OV7725_FixGain,   0x09},
  {OV7725_AWB_Ctrl0, 0xe0},
  {OV7725_DSP_Ctrl1, 0xff},
  {OV7725_DSP_Ctrl2, 0x20},
  {OV7725_DSP_Ctrl3,        0x00},
  {OV7725_DSP_Ctrl4, 0x00},
  
  /*AGC AEC AWB*/
  {OV7725_COM8,                  0xf0},
  {OV7725_COM4,                  0x81}, /*Pll AEC CONFIG*/
  {OV7725_COM6,                  0xc5},
  {OV7725_COM9,                  0x21},
  {OV7725_BDBase,          0xFF},
  {OV7725_BDMStep,          0x01},
  {OV7725_AEW,                    0x34},
  {OV7725_AEB,                    0x3c},
  {OV7725_VPT,                    0xa1},
  {OV7725_EXHCL,                  0x00},
  {OV7725_AWBCtrl3,  0xaa},
  {OV7725_COM8,                  0xff},
  {OV7725_AWBCtrl1,  0x5d},
  
  {OV7725_EDGE1,                  0x0a},
  {OV7725_DNSOff,          0x01},
  {OV7725_EDGE2,                  0x01},
  {OV7725_EDGE3,                  0x01},
  
  {OV7725_MTX1,                  0x5f},
  {OV7725_MTX2,                  0x53},
  {OV7725_MTX3,                  0x11},
  {OV7725_MTX4,                  0x1a},
  {OV7725_MTX5,                  0x3d},
  {OV7725_MTX6,                  0x5a},
  {OV7725_MTX_Ctrl,  0x1e},
  
  {OV7725_BRIGHT,          0x00},
  {OV7725_CNST,                  0x25},
  {OV7725_USAT,                  0x65},
  {OV7725_VSAT,                  0x65},
  {OV7725_UVADJ0,          0x81},
  {OV7725_SDE,                    0x06},
  
  /*GAMMA config*/
  {OV7725_GAM1,                  0x0c},
  {OV7725_GAM2,                  0x16},
  {OV7725_GAM3,                  0x2a},
  {OV7725_GAM4,                  0x4e},
  {OV7725_GAM5,                  0x61},
  {OV7725_GAM6,                  0x6f},
  {OV7725_GAM7,                  0x7b},
  {OV7725_GAM8,                  0x86},
  {OV7725_GAM9,                  0x8e},
  {OV7725_GAM10,                  0x97},
  {OV7725_GAM11,                  0xa4},
  {OV7725_GAM12,                  0xaf},
  {OV7725_GAM13,                  0xc5},
  {OV7725_GAM14,                  0xd7},
  {OV7725_GAM15,                  0xe8},
  {OV7725_SLOP,                  0x20},
  
  {OV7725_HUECOS,          0x80},
  {OV7725_HUESIN,          0x80},
  {OV7725_DSPAuto,          0xff},
  {OV7725_DM_LNL,          0x00},
  {OV7725_BDBase,          0x99},
  {OV7725_BDMStep,          0x03},
  {OV7725_LC_RADI,          0x00},
  {OV7725_LC_COEF,          0x13},
  {OV7725_LC_XC,                  0x08},
  {OV7725_LC_COEFB,  0x14},
  {OV7725_LC_COEFR,  0x17},
  {OV7725_LC_CTR,          0x05},
  
  {OV7725_COM3,                  0xd0},/*Horizontal mirror image*/
  
  /*night mode auto frame rate control*/
  {OV7725_COM5,                0xf5},         /*?úò1êó?·?3??£?×??ˉ?μμí???ê£?±£?¤μí???è?-???êá?*/
  //{COM5,                0x31},        /*ò1êó?·?3???ê2?±?*/
};
/*OV7725初始化配置表*/
Reg_Info Sensor_Config[] =
{
  //寄存器,寄存器值次
  {OV7725_COM4         , 0xC1},
  {OV7725_CLKRC        , 0x00},
  {OV7725_COM2         , 0x03},
  {OV7725_COM3         , 0xD0},
  {OV7725_COM7         , 0x40},
  {OV7725_HSTART       , 0x3F},
  {OV7725_HSIZE        , 0x50},
  {OV7725_VSTRT        , 0x03},
  {OV7725_VSIZE        , 0x78},
  {OV7725_HREF         , 0x00},
  {OV7725_SCAL0        , 0x0A},
  {OV7725_AWB_Ctrl0    , 0xE0},
  {OV7725_DSPAuto      , 0xff},
  {OV7725_DSP_Ctrl2    , 0x0C},
  {OV7725_DSP_Ctrl3    , 0x00},
  {OV7725_DSP_Ctrl4    , 0x00},
  
#if (CAMERA_W == 80)
  {OV7725_HOutSize     , 0x14},
#elif (CAMERA_W == 160)
  {OV7725_HOutSize     , 0x28},
#elif (CAMERA_W == 240)
  {OV7725_HOutSize     , 0x3c},
#elif (CAMERA_W == 320)
  {OV7725_HOutSize     , 0x50},
#else
  
#endif
  
#if (CAMERA_H == 60 )
  {OV7725_VOutSize     , 0x1E},
#elif (CAMERA_H == 120 )
  {OV7725_VOutSize     , 0x3c},
#elif (CAMERA_H == 180 )
  {OV7725_VOutSize     , 0x5a},
#elif (CAMERA_H == 240 )
  {OV7725_VOutSize     , 0x78},
#else
  
#endif
  
  {OV7725_EXHCH        , 0x00},
  {OV7725_GAM1         , 0x0c},
  {OV7725_GAM2         , 0x16},
  {OV7725_GAM3         , 0x2a},
  {OV7725_GAM4         , 0x4e},
  {OV7725_GAM5         , 0x61},
  {OV7725_GAM6         , 0x6f},
  {OV7725_GAM7         , 0x7b},
  {OV7725_GAM8         , 0x86},
  {OV7725_GAM9         , 0x8e},
  {OV7725_GAM10        , 0x97},
  {OV7725_GAM11        , 0xa4},
  {OV7725_GAM12        , 0xaf},
  {OV7725_GAM13        , 0xc5},
  {OV7725_GAM14        , 0xd7},
  {OV7725_GAM15        , 0xe8},
  {OV7725_SLOP         , 0x20},
  {OV7725_LC_RADI      , 0x00},
  {OV7725_LC_COEF      , 0x13},
  {OV7725_LC_XC        , 0x08},
  {OV7725_LC_COEFB     , 0x14},
  {OV7725_LC_COEFR     , 0x17},
  {OV7725_LC_CTR       , 0x05},
  {OV7725_BDBase       , 0x99},
  {OV7725_BDMStep      , 0x03},
  {OV7725_SDE          , 0x04},
  {OV7725_BRIGHT       , 0x00},
  {OV7725_CNST         , 0xFF},
  {OV7725_SIGN         , 0x06},
  {OV7725_UVADJ0       , 0x11},
  {OV7725_UVADJ1       , 0x02},
  
};

u8 OV7725_REG_NUM = sizeof(Sensor_Config)/sizeof(Sensor_Config[0]);          /*结构体数组成员数目*/
u8 OV7725_REG_NUM1= sizeof(Sensor_Config1)/sizeof(Sensor_Config1[0]);
uint8_t Ov7725_vsync = 0;         /* 帧同步信号标志,在中断函数和main函数里面使用 */
void OV7725_GPIO_Init(void)
{
  uint8_t i=0;
const gpio_output_pin_user_config_t sccb_gpio_config[]=
  {
    {.pinName = GPIO_MAKE_PIN(GPIOC_IDX, 16U),
    .config.outputLogic = 1,
    .config.slewRate = kPortFastSlewRate,
    .config.isOpenDrainEnabled = false,
    .config.driveStrength = kPortHighDriveStrength,
    },                                                                       //PTC16 WE
    {.pinName = GPIO_MAKE_PIN(GPIOC_IDX, 17U),
    .config.outputLogic = 1,
    .config.slewRate = kPortFastSlewRate,
    .config.isOpenDrainEnabled = false,
    .config.driveStrength = kPortHighDriveStrength,
    },                                                                       //PTC17 WRST
    {.pinName = GPIO_MAKE_PIN(GPIOA_IDX, 1U),
    .config.outputLogic = 1,
    .config.slewRate = kPortFastSlewRate,
    .config.isOpenDrainEnabled = false,
    .config.driveStrength = kPortHighDriveStrength,
    },                                                                       //PTA1 RCLK
    {.pinName = GPIO_MAKE_PIN(GPIOB_IDX, 23U),
    .config.outputLogic = 1,
    .config.slewRate = kPortFastSlewRate,
    .config.isOpenDrainEnabled = false,
    .config.driveStrength = kPortHighDriveStrength,
    },                                                                       //PTB23 PRST
    {.pinName = GPIO_MAKE_PIN(GPIOA_IDX, 2U),
    .config.outputLogic = 1,
    .config.slewRate = kPortFastSlewRate,
    .config.isOpenDrainEnabled = false,
    .config.driveStrength = kPortHighDriveStrength,
    },                                                                       //PTA2 OE
   
  };

使用特权

评论回复
板凳
E-Kaia|  楼主 | 2016-1-23 21:31 | 只看该作者
 for(i=0;i<5;i++)
GPIO_DRV_OutputPinInit(&sccb_gpio_config[i]);

  //GPIO_DRV_OutputPinInit(&sccb_gpio_config[0]);
  const gpio_input_pin_user_config_t VSYNC_Pin =
  {
    .pinName = GPIO_MAKE_PIN(GPIOB_IDX, 9U),
    .config.isPullEnable = true,
    .config.pullSelect = kPortPullUp,
    .config.isPassiveFilterEnabled = false,
    .config.interrupt = kPortIntFallingEdge
  };
  const gpio_input_pin_user_config_t DATA_Pin[] =
  {
    {
    .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 0U),
    .config.isPullEnable = true,
    .config.pullSelect = kPortPullUp,
    .config.isPassiveFilterEnabled = false,
    .config.interrupt = kPortIntDisabled,
    },
     {
    .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 1U),
    .config.isPullEnable = true,
    .config.pullSelect = kPortPullUp,
    .config.isPassiveFilterEnabled = false,
    .config.interrupt = kPortIntDisabled,
    },
     {
    .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 2U),
    .config.isPullEnable = true,
    .config.pullSelect = kPortPullUp,
    .config.isPassiveFilterEnabled = false,
    .config.interrupt = kPortIntDisabled,
    },
     {
    .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 3U),
    .config.isPullEnable = true,
    .config.pullSelect = kPortPullUp,
    .config.isPassiveFilterEnabled = false,
    .config.interrupt = kPortIntDisabled,
    },
   
     {
    .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 8U),
    .config.isPullEnable = true,
    .config.pullSelect = kPortPullUp,
    .config.isPassiveFilterEnabled = false,
    .config.interrupt = kPortIntDisabled,
    },
     {
    .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 9U),
    .config.isPullEnable = true,
    .config.pullSelect = kPortPullUp,
    .config.isPassiveFilterEnabled = false,
    .config.interrupt = kPortIntDisabled,
    },
     {
    .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 10U),
    .config.isPullEnable = true,
    .config.pullSelect = kPortPullUp,
    .config.isPassiveFilterEnabled = false,
    .config.interrupt = kPortIntDisabled,
    },
     {
    .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 11U),
    .config.isPullEnable = true,
    .config.pullSelect = kPortPullUp,
    .config.isPassiveFilterEnabled = false,
    .config.interrupt = kPortIntDisabled,
    },
  };

  for(i=0;i<8;i++)
  {
    GPIO_DRV_InputPinInit(&DATA_Pin[i]);
  }
   GPIO_DRV_InputPinInit(&VSYNC_Pin);
   NVIC_DisableIRQ(PORTB_IRQn);
}
void OV7725_Init(void)
{
  
  SCCB_Init();
  OV7725_GPIO_Init();
  OV7725_ReadID(&OV7725ID);  //重要环节,使用OV7725要先看看读取ID正不正常
  OV7725_config();   //配置JPEG参数
  NVIC_EnableIRQ(PORTB_IRQn);
  
}

uint8_t OV7725_ReadID(OV7725_IDTypeDef* OV7725ID)
{
  if(SCCB_WR_Reg(OV7725_COM7, 0x80)) return 1;
  
  
  OV7725ID->Manufacturer_IDH =SCCB_RD_Reg(OV7725_MIDH);
  
  OV7725ID->Manufacturer_IDL =SCCB_RD_Reg(OV7725_MIDL);
  
  OV7725ID->Version =SCCB_RD_Reg(OV7725_VER);
  
  OV7725ID->PID =SCCB_RD_Reg(OV7725_PID);
  
  return 0;
}



void OV7725_config(void)
{
  uint8_t i=0;
  if(OV7725ID.Version == 0x21)
  {
    for( i = 0 ; i < OV7725_REG_NUM1 ; i++ )
    {
      SCCB_WR_Reg(Sensor_Config1[i].Address, Sensor_Config1[i].Value);
      delay_ms(2);
    }
  }
  
}
void PORTB_IRQHandler(void)
{
    // Clear external interrupt flag.
  if(GPIO_DRV_IsPinIntPending(GPIO_MAKE_PIN(GPIOB_IDX, 9U)))
  {
        if(ov_sta<2)
    {
      if(ov_sta==0)
      {
        FIFO_WRST_L();                                            
        FIFO_WRST_H();       
        FIFO_WE_H();       
      }else
      {
        FIFO_WE_L();       
      }         
      ov_sta++;
    }
    GPIO_DRV_ClearPinIntFlag(GPIO_MAKE_PIN(GPIOB_IDX, 9U));
  }
}
//void EXTI15_10_IRQHandler(uint16_t GPIO_Pin)
//{
//  if(EXTI_GetITStatus(EXTI_Line10) != RESET)
//  {
//    if(ov_sta<2)
//    {
//      if(ov_sta==0)
//      {
//        FIFO_WRST_L();                                            
//        FIFO_WRST_H();       
//        FIFO_WE_H();       
//      }else
//      {
//        FIFO_WE_L();       
//      }         
//      ov_sta++;
//    }
   
//  }
//  EXTI_ClearITPendingBit(EXTI_Line10); //清除LINE0上的中断标志位
//}

void camera_refresh(void)
{
  u32 i,j;
  u16 color,temp;
  if(ov_sta==2)
  {
     NVIC_DisableIRQ(PORTB_IRQn);
    FIFO_OE_L();         
    FIFO_RRST_L();                                //开始复位读指针
    FIFO_RCLK_L();
    FIFO_RCLK_H();
    FIFO_RCLK_L();
    FIFO_RRST_H();                                //复位读指针结束
    FIFO_RCLK_H();
    count=0;
    for(i=0;i<176;i++)
    {
      for(j=0;j<240;j++)
      {
        FIFO_RCLK_L();
        //temp=PTC->PDIR;
        color=OV7725_DATA;
        FIFO_RCLK_H();
      
//        color=(temp>>4|temp)&0xff;       
        color<<=8;                                          
        FIFO_RCLK_L();
        color|=OV7725_DATA;
        //temp=PTC->PDIR;  
        FIFO_RCLK_H();        
        //color|=(temp>>4|temp)&0xff;                //读数据
       
        SPILCD_WriteRAM(color);                            
      }  
    }
    PRINTF("DISP TIME IS %d ms\r\n",count);
    FIFO_OE_H();                                                          
    FIFO_RCLK_L();
    FIFO_RCLK_H();                
    ov_sta=0;                                        //开始下一次采集
    ov_frame++;
GPIO_DRV_ClearPinIntFlag(GPIO_MAKE_PIN(GPIOB_IDX, 9U)); //清除LINE0上的中断标志位
    NVIC_EnableIRQ(PORTB_IRQn);
  }   
}         

使用特权

评论回复
地板
E-Kaia|  楼主 | 2016-1-23 21:31 | 只看该作者
//-----------------------------------------------------------------------
// KSDK Includes
//-----------------------------------------------------------------------
#include "board.h"
#include "pin_mux.h"
#include "fsl_clock_manager.h"
#include "fsl_debug_console.h"
//-----------------------------------------------------------------------
// Hardware Initialization
//-----------------------------------------------------------------------
void hardware_init(void)
{

    /* enable clock for PORTs */
    CLOCK_SYS_EnablePortClock(PORTA_IDX);
    CLOCK_SYS_EnablePortClock(PORTB_IDX);
    CLOCK_SYS_EnablePortClock(PORTC_IDX);
    CLOCK_SYS_EnablePortClock(PORTD_IDX);
    CLOCK_SYS_EnablePortClock(PORTE_IDX);

    /* Init board clock */
    BOARD_ClockInit();
}

使用特权

评论回复
5
E-Kaia|  楼主 | 2016-1-23 21:33 | 只看该作者
#include <stdio.h>
//-----------------------------------------------------------------------
// KSDK Includes
//-----------------------------------------------------------------------
#include "main.h"
#include "pit.h"
#include "delay.h"
#include "spi_lcd.h"
#include "ov7725.h"
//-----------------------------------------------------------------------
// Application Includes
//-----------------------------------------------------------------------

//-----------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------

//-----------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------

//-----------------------------------------------------------------------
// Typedefs
//-----------------------------------------------------------------------

//-----------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------

//-----------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------

//-----------------------------------------------------------------------
// Main Function
//-----------------------------------------------------------------------
extern uint32_t count;

int main(void)
{

    // Configure board specific pin muxing
  uint32_t temp;
    hardware_init();
    delay_init(120);
    // Initialize UART terminal
    dbg_uart_init();

    PRINTF("\r\nRunning the Demo project.\r\n");
    LED1_EN;
    LED2_EN;
    LED3_EN;
    PIT_Init(0,true,1000);
    LCD_Init();
    LCD_Set_Dir(DFT_SCAN_DIR);
  SPILCD_Clear(BLUE);
  SPILCD_SetWindow(0,175,0,240);     //开始写入GRAM       
  OV7725_Init();
   
    //LCD_ShowString();
    for (;;)                                         // Forever loop
    {
//      LED1_TOGGLE;
//      delay_ms(500);
//      count=0;
//      SPILCD_Clear(RED);
//      temp=count;
//      printf("LCD clear time is %d ms\r\n",temp);
camera_refresh();
    }


}

使用特权

评论回复
6
lll6711| | 2016-1-23 23:53 | 只看该作者
多谢分享

使用特权

评论回复
7
大秦正声| | 2016-1-24 08:44 | 只看该作者
关注

使用特权

评论回复
8
justinlin2015| | 2016-1-25 17:38 | 只看该作者
多谢分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

100

帖子

0

粉丝