• OV摄像头SCCB通信协议


    /*!
     *     COPYRIGHT NOTICE
     *     Copyright (c) 2013,山外科技
     *     All rights reserved.
     *     技术讨论:山外论坛 http://www.vcan123.com
     *
     *     除注明出处外,以下所有内容版权均属山外科技所有,未经允许,不得用于商业用途,
     *     修改内容时必须保留山外科技的版权声明。
     *
     * @file       VCAN_SCCB.c
     * @brief      OV摄像头配置总线SCCB函数库
     * @author     山外科技
     * @version    v5.0
     * @date       2013-09-01
     */
    
    
    #include "common.h"
    #include "MK60_gpio.h"
    #include "VCAN_SCCB.h"
    
    static void SCCB_delay(uint16 i);
    
    /*!
     *  @brief      SCCB延迟函数
     *  @param      time    延时时间
     *  @since      v5.0
     */
    static void SCCB_delay(volatile uint16 time)
    {
        while(time)
        {
            time--;
        }
    }
    
    /*!
     *  @brief      SCCB管脚配置
     *  @since      v5.0
     */
    void SCCB_GPIO_init(void)
    {
        gpio_init  (SCCB_SCL, GPO, 1); //初始化SCL
        gpio_init  (SCCB_SDA, GPO, 1); //初始化SDA
    
        port_init_NoALT(SCCB_SCL,ODO | PULLUP);
        port_init_NoALT(SCCB_SDA,ODO | PULLUP);
    }
    
    /*!
     *  @brief      SCCB起始信号
     *  @since      v5.0
     */
    static uint8 SCCB_Start(void)
    {
        SDA_H();
        SCL_H();
        SCCB_DELAY();
    
        SDA_DDR_IN();
        if(!SDA_IN())
        {
            SDA_DDR_OUT();
            return 0;   /* SDA线为低电平则总线忙,退出 */
        }
        SDA_DDR_OUT();
        SDA_L();
    
        SCCB_DELAY();
        SCL_L();
    
        if(SDA_IN())
        {
            SDA_DDR_OUT();
            return 0;   /* SDA线为高电平则总线出错,退出 */
        }
        //SDA_DDR_OUT();
        //SDA_L();
        //SCCB_delay();
        return 1;
    }
    
    /*!
     *  @brief      SCCB停止信号
     *  @since      v5.0
     */
    static void SCCB_Stop(void)
    {
        SCL_L();
        //SCCB_DELAY();
        SDA_L();
        SCCB_DELAY();
        SCL_H();
        SCCB_DELAY();
        SDA_H();
        SCCB_DELAY();
    }
    
    /*!
     *  @brief      SCCB应答信号
     *  @since      v5.0
     */
    static void SCCB_Ack(void)
    {
        SCL_L();
        SCCB_DELAY();
        SDA_L();
        SCCB_DELAY();
        SCL_H();
        SCCB_DELAY();
        SCL_L();
        SCCB_DELAY();
    }
    
    /*!
     *  @brief      SCCB无应答信号
     *  @since      v5.0
     */
    static void SCCB_NoAck(void)
    {
        SCL_L();
        SCCB_DELAY();
        SDA_H();
        SCCB_DELAY();
        SCL_H();
        SCCB_DELAY();
        SCL_L();
        SCCB_DELAY();
    }
    
    /*!
     *  @brief      SCCB 等待应答
     *  @return     应答结果(0表示无应答,1表示有应答)
     *  @since      v5.0
     */
    static int SCCB_WaitAck(void)
    {
        SCL_L();
        //SDA_H();
        SDA_DDR_IN();
    
        SCCB_DELAY();
        SCL_H();
    
        SCCB_DELAY();
    
        if(SDA_IN())           //应答为高电平,异常,通信失败
        {
            SDA_DDR_OUT();
            SCL_L();
            return 0;
        }
        SDA_DDR_OUT();
        SCL_L();
        return 1;
    }
    
    /*!
     *  @brief      SCCB 发送的数据
     *  @param      SendByte    需要发送的数据
     *  @since      v5.0
     */
    static void SCCB_SendByte(uint8 SendByte)
    {
        uint8 i = 8;
        while(i--)
        {
    
            if(SendByte & 0x80)     //SDA 输出数据
            {
                SDA_H();
            }
            else
            {
                SDA_L();
            }
            SendByte <<= 1;
            SCCB_DELAY();
            SCL_H();                //SCL 拉高,采集信号
            SCCB_DELAY();
            SCL_L();                //SCL 时钟线拉低
            //SCCB_DELAY();
        }
        //SCL_L();
    }
    
    /*!
     *  @brief      接收SCCB总线的数据
     *  @return     接收到的数据
     *  @since      v5.0
     */
    static int SCCB_ReceiveByte(void)
    {
        uint8 i = 8;
        uint8 ReceiveByte = 0;
    
        //SDA_H();
        //SCCB_DELAY();
        SDA_DDR_IN();
    
        while(i--)
        {
            ReceiveByte <<= 1;
            SCL_L();
            SCCB_DELAY();
            SCL_H();
            SCCB_DELAY();
    
            if(SDA_IN())
            {
                ReceiveByte |= 0x01;
            }
    
    
        }
        SDA_DDR_OUT();
        SCL_L();
        return ReceiveByte;
    }
    
    /*****************************************************************************************
    * 函数名:SCCB_WriteByte
    * 描述  :写一字节数据
    * 输入  :- WriteAddress: 待写入地址    - SendByte: 待写入数据  - DeviceAddress: 器件类型
    * 输出  :返回为:=1成功写入,=0失败
    * 注意  :无
    *****************************************************************************************/
    static int SCCB_WriteByte_one( uint16 WriteAddress , uint8 SendByte );
    
    
    int SCCB_WriteByte( uint16 WriteAddress , uint8 SendByte )            //考虑到用sccb的管脚模拟,比较容易失败,因此多试几次
    {
        uint8 i = 0;
        while( 0 == SCCB_WriteByte_one ( WriteAddress, SendByte ) )
        {
            i++;
            if(i == 20)
            {
                return 0 ;
            }
        }
        return 1;
    }
    
    int SCCB_WriteByte_one( uint16 WriteAddress , uint8 SendByte )
    {
        if(!SCCB_Start())
        {
            return 0;
        }
        SCCB_SendByte( DEV_ADR );                    /* 器件地址 */
        if( !SCCB_WaitAck() )
        {
            SCCB_Stop();
            return 0;
        }
        SCCB_SendByte((uint8)(WriteAddress & 0x00FF));   /* 设置低起始地址 */
        SCCB_WaitAck();
        SCCB_SendByte(SendByte);
        SCCB_WaitAck();
        SCCB_Stop();
        return 1;
    }
    
    
    
    
    /******************************************************************************************************************
     * 函数名:SCCB_ReadByte
     * 描述  :读取一串数据
     * 输入  :- pBuffer: 存放读出数据  - length: 待读出长度    - ReadAddress: 待读出地址        - DeviceAddress: 器件类型
     * 输出  :返回为:=1成功读入,=0失败
     * 注意  :无
     **********************************************************************************************************************/
    static int SCCB_ReadByte_one(uint8 *pBuffer,   uint16 length,   uint8 ReadAddress);
    
    int SCCB_ReadByte(uint8 *pBuffer,   uint16 length,   uint8 ReadAddress)
    {
        uint8 i = 0;
        while( 0 == SCCB_ReadByte_one(pBuffer, length, ReadAddress) )
        {
            i++;
            if(i == 30)
            {
                return 0 ;
            }
        }
        return 1;
    }
    
    int SCCB_ReadByte_one(uint8 *pBuffer,   uint16 length,   uint8 ReadAddress)
    {
        if(!SCCB_Start())
        {
            return 0;
        }
        SCCB_SendByte( DEV_ADR );         /* 器件地址 */
        if( !SCCB_WaitAck() )
        {
            SCCB_Stop();
            return 0;
        }
        SCCB_SendByte( ReadAddress );           /* 设置低起始地址 */
        SCCB_WaitAck();
        SCCB_Stop();
    
        if(!SCCB_Start())
        {
            return 0;
        }
        SCCB_SendByte( DEV_ADR + 1 );               /* 器件地址 */
    
        if(!SCCB_WaitAck())
        {
            SCCB_Stop();
            return 0;
        }
        while(length)
        {
            *pBuffer = SCCB_ReceiveByte();
            if(length == 1)
            {
                SCCB_NoAck();
            }
            else
            {
                SCCB_Ack();
            }
            pBuffer++;
            length--;
        }
        SCCB_Stop();
        return 1;
    }
  • 相关阅读:
    LINUX安装 RPM与YUM
    ln s 软链接知识总结
    JQuery EasyUI 之 combobox plugin
    域名的DNS解析指南
    Asp.NET + OWC 输出Chart(图表)
    打败 IE 的葵花宝典:CSS Bug Table
    Route命令使用详解
    JQuery EasyUI 之 validatebox plugin
    JQuery easyUI 之 datebox plugin
    [转]如何安全的存储密码
  • 原文地址:https://www.cnblogs.com/scrazy/p/8316266.html
Copyright © 2020-2023  润新知