• NK-RTU980 CAP


            BSP包中有两个CAP相关的例程,两个例程的区别为获取的图像数据的存储格式不同,planar例程是先存储所有像素点的Y,再存U,再存V。packed例程是每个像素的YUV连续存储。

    一、硬件电路

    处理器为NUC980DR61Y,封装为64pin,只有CAP0接口,所以Sensor接在处理器的CAP0接口:

    硬件连接如下: 

    CMOS的所需的24MHz工作时钟由处理器PC.3输出。

    二、例程修改

    1、添加void CAP0_IRQHandler(void)函数

    1. /*------------------------------------------------------------------------------------------*/
    2. /* CAP_IRQHandler */
    3. /*------------------------------------------------------------------------------------------*/
    4. void CAP0_IRQHandler(void)
    5. {
    6. uint32_t u32CapInt;
    7. u32CapInt = CAP0->INT;
    8. if( (u32CapInt & (CAP_INT_VIEN_Msk | CAP_INT_VINTF_Msk )) == (CAP_INT_VIEN_Msk | CAP_INT_VINTF_Msk))
    9. {
    10. CAP_InterruptHandler();
    11. CAP0->INT |= CAP_INT_VINTF_Msk; /* Clear Frame end interrupt */
    12. u32EscapeFrame = u32EscapeFrame+1;
    13. }
    14. if((u32CapInt & (CAP_INT_ADDRMIEN_Msk|CAP_INT_ADDRMINTF_Msk)) == (CAP_INT_ADDRMIEN_Msk|CAP_INT_ADDRMINTF_Msk))
    15. {
    16. CAP0->INT |= CAP_INT_ADDRMINTF_Msk; /* Clear Address match interrupt */
    17. }
    18. if ((u32CapInt & (CAP_INT_MEIEN_Msk|CAP_INT_MEINTF_Msk)) == (CAP_INT_MEIEN_Msk|CAP_INT_MEINTF_Msk))
    19. {
    20. CAP0->INT |= CAP_INT_MEINTF_Msk; /* Clear Memory error interrupt */
    21. }
    22. if ((u32CapInt & (CAP_INT_MDIEN_Msk|CAP_INT_MDINTF_Msk)) == (CAP_INT_MDIEN_Msk|CAP_INT_MDINTF_Msk))
    23. {
    24. CAP0->INT |= CAP_INT_MDINTF_Msk; /* Clear Motion Detection interrupt */
    25. }
    26. CAP0->CTL = CAP0->CTL | CAP_CTL_UPDATE;
    27. }

    2、注册IRQ_CAP0中断

    1. sysInstallISR(IRQ_LEVEL_1, IRQ_CAP0, (PVOID)CAP0_IRQHandler);
    2. sysSetLocalInterrupt(ENABLE_IRQ);
    3. sysEnableInterrupt(IRQ_CAP0);

    3、使能时钟

    1. /* Init Engine clock and Sensor clock */
    2. CAP_SetFreq(CAP0,48000000,24000000);

     CMOS的时钟结构如上图所示,例程中的配置SENSORx_S是选择的XTALIN12M,如果需要设置SENx_CLK为24MHz,那么需要XTALIN12M为48MHz才行,如果XTALIN12M为12MHz,那么经过分频之后SENx_CLK为6MHz。一般APLLFout、UPLLFout为300MHz,将SENSORx_SDIV配置为2,三分频后ACLKout或UCLKout为100MHz,再将SENSORx_N配置为3,四分频后SENx_CLK为25MHz,测试时发现SENSORx_S选择ULCKout才行,选ACLKout会有问题。

    4、将void PacketFormatDownScale(uint32_t SensorId)函数中关于CAP1的配置改为CAP0

    1. void PacketFormatDownScale(uint32_t SensorId)
    2. {
    3. uint32_t u32Frame;
    4. /* Enable External CAP Interrupt */
    5. CAP_EnableInt(CAP0,CAP_INT_VIEN_Msk);
    6. /* Set Vsync polarity, Hsync polarity, pixel clock polarity, Sensor Format and Order */
    7. if(SensorId==SENSOR_GC0308)
    8. CAP_Open(CAP0,GC0308SensorPolarity | GC0308DataFormatAndOrder, CAP_CTL_PKTEN );
    9. else
    10. CAP_Open(CAP0,NT99XXXSensorPolarity | NT99XXXDataFormatAndOrder, CAP_CTL_PKTEN );
    11. /* Set Cropping Window Vertical/Horizontal Starting Address and Cropping Window Size */
    12. CAP_SetCroppingWindow(CAP0,0,0,SENSOR_IN_HEIGHT,SENSOR_IN_WIDTH);
    13. /* Set System Memory Packet Base Address Register */
    14. CAP_SetPacketBuf(CAP0,(uint32_t)u8FrameBuffer);
    15. /* Set Packet Scaling Vertical/Horizontal Factor Register */
    16. CAP_SetPacketScaling(CAP0,SYSTEM_HEIGHT,SENSOR_IN_HEIGHT,SYSTEM_WIDTH,SENSOR_IN_WIDTH);
    17. /* Set Packet Frame Output Pixel Stride Width */
    18. CAP_SetPacketStride(CAP0,SYSTEM_WIDTH);
    19. /* Start Image Capture Interface */
    20. CAP_Start(CAP0);
    21. u32Frame=u32FramePass;
    22. while(1)
    23. {
    24. if(u32Frame!=u32FramePass)
    25. {
    26. u32Frame=u32FramePass;
    27. printf("Get frame %3d\n",u32Frame);
    28. }
    29. }
    30. }

    5、添加Sensor

    例程中包含了三款Sensor的初始化代码,而我们项目中用到的sensor型号没在例程中,所以需要编写Sensor的初始化代码。

    修改XXX_SnrReset()函数:

    1. static void XXX_SnrReset(void)
    2. {
    3. /* PB4 reset: H->L->H */
    4. outpw(REG_SYS_GPB_MFPL,(inpw(REG_SYS_GPB_MFPL) & ~0x000F0000));
    5. GPIO_SetMode(PB,1<<4,GPIO_MODE_OUTPUT);
    6. PB4=1;
    7. Delay(100);
    8. PB4=0;
    9. Delay(100);
    10. PB4=1;
    11. }

    例程中所用RESET管脚为PE10,改为PB4。关于GPIO相关的寄存器,参看文档

    修改XXX_SnrPowerDown()函数:

    1. static void XXX_SnrPowerDown(BOOL bIsEnable)
    2. {
    3. /* PB6 power down, HIGH for power down */
    4. outpw( REG_SYS_GPB_MFPL,(inpw(REG_SYS_GPB_MFPL) & ~0x0F000000));
    5. GPIO_SetMode(PB,1<<6,GPIO_MODE_OUTPUT);
    6. PB6=0;
    7. if(bIsEnable)
    8. PB6=1;
    9. else
    10. PB6=0;
    11. }

    例程中所用power down管脚为PC0,改为PB6。高电平进入power down模式。

    修改I2C SCL和SDA管脚,SCL改为PA1,SDA改为PA0:

    		SWI2C_Open(eDRVGPIO_GPIOA,eDRVGPIO_PIN1,eDRVGPIO_GPIOA,eDRVGPIO_PIN0,Delay);

     例程中i2c驱动为gpio模拟,并且SWI2C_ReadByte(,)函数中关于ACK和NO_ACK的时序不符规范要求,修改之后如下:

    1. //-------------------------------
    2. //master read bytes data from slave device
    3. uint32_t
    4. SWI2C_ReadByte(
    5. uint8_t u8AckType,
    6. uint8_t u8Length
    7. )
    8. {
    9. uint32_t u32Data=0;
    10. uint8_t u8DataCount;
    11. _SWI2C_SDA_SETIN(s_sChannel.u32SDAPortIndex, s_sChannel.u32SDAPinMask);
    12. // Read data from slave device and the most signification bit(MSB) first
    13. for ( u8DataCount=0; u8DataCount<u8Length; u8DataCount++ )
    14. {
    15. u32Data = u32Data<<1;
    16. _SWI2C_Delay(3);
    17. _SWI2C_SCK_SETHIGH(s_sChannel.u32SCKPortIndex, s_sChannel.u32SCKPinMask);
    18. if (_SWI2C_SDA_GETVALUE(s_sChannel.u32SDAPortIndex, s_sChannel.u32SDAPinMask)==s_sChannel.u32SDAPinMask)
    19. u32Data = u32Data|0x01;
    20. _SWI2C_Delay(2);
    21. _SWI2C_SCK_SETLOW(s_sChannel.u32SCKPortIndex, s_sChannel.u32SCKPinMask);
    22. _SWI2C_Delay(2);
    23. }
    24. _SWI2C_SDA_SETOUT(s_sChannel.u32SDAPortIndex, s_sChannel.u32SDAPinMask);
    25. // No write Ack
    26. if ( u8AckType == DrvI2C_Ack_No )
    27. {
    28. _SWI2C_SDA_SETHIGH(s_sChannel.u32SDAPortIndex, s_sChannel.u32SDAPinMask);
    29. _SWI2C_Delay(3);
    30. _SWI2C_SCK_SETHIGH(s_sChannel.u32SCKPortIndex, s_sChannel.u32SCKPinMask);
    31. _SWI2C_Delay(2);
    32. _SWI2C_SCK_SETLOW(s_sChannel.u32SCKPortIndex, s_sChannel.u32SCKPinMask);
    33. _SWI2C_Delay(2);
    34. return u32Data;
    35. }
    36. // Have a Ack
    37. // write a ACK bit to slave device
    38. _SWI2C_SDA_SETLOW(s_sChannel.u32SDAPortIndex, s_sChannel.u32SDAPinMask);
    39. _SWI2C_Delay(3);
    40. _SWI2C_SCK_SETHIGH(s_sChannel.u32SCKPortIndex, s_sChannel.u32SCKPinMask);
    41. _SWI2C_Delay(2);
    42. _SWI2C_SCK_SETLOW(s_sChannel.u32SCKPortIndex, s_sChannel.u32SCKPinMask);
    43. _SWI2C_Delay(2);
    44. return u32Data;
    45. }

    6、根据Sensor的手册修改g_XXX_VGA_RegValue[]寄存器列表。

    7、运行日志

    1. This sample code demonstrate CAP packet down scale function
    2. ======================================================
    3. CAP library demo code
    4. [1] NT99141 VGA
    5. [2] NT99050 VGA
    6. [3] GC0308 VGA
    7. [4] XXX VGA
    8. ======================================================
    9. Sensor Chip_Version = 0x1324(0x1324)
    10. Get frame 1
    11. Get frame 2
    12. Get frame 3
    13. Get frame 4

    三、缓存图像数据

    由于u8FrameBuffer的内容会被不断覆盖,如果想要将数据缓存以待处理,那么可再定义一个相同尺寸的u8ImageBuffer,在CAP_InterruptHandler()函数中将u8FrameBuffer的内容拷贝到u8ImageBuffer,并通过一个标志防止u8ImageBuffer中的数据未处理时被覆盖,待数据处理后将标志置0。CAP_InterruptHandler()修改如下:

    1. void CAP_InterruptHandler(void)
    2. {
    3. u32FramePass++;
    4. if( ImageCpyFlag == 0 )
    5. {
    6. memcpy(u8ImageBuffer, u8FrameBuffer, SYSTEM_WIDTH*SYSTEM_HEIGHT * 2 );
    7. ImageCpyFlag = 1;
    8. }
    9. }

  • 相关阅读:
    Vue知识点整理(待更新)
    基于ntchat的微信群聊同步机器人
    基于Python实现的某宝服装类销售评论数据提取
    学习分享:如何进行全局变量的学习
    JavaScript中的DOM
    云原生之持续交付
    Linux XWindow的安装和配置
    1110:查找特定的值
    C# 结合 JS 暴改腾讯 IM SDK Demo
    java计算机毕业设计bs架构实习管理系统源码+mysql数据库+系统+lw文档+部署
  • 原文地址:https://blog.csdn.net/professionalmcu/article/details/126589756