0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

EMIO方式模拟SCCB时序进行读写操作详解

Hx 作者:工程师陈翠 2018-06-29 10:32 次阅读

一、SCCB介绍

SCCB是OmniVision Serial Camera Control Bus的简称,即OV公司的串行摄像机控制总线。OV公司定义的SCCB是一个3线结构,但是,为了缩减Sensorpin封装,SCCB大多采用2线方式。

开始传输数据

EMIO方式模拟SCCB时序进行读写操作详解

结束数据传输

EMIO方式模拟SCCB时序进行读写操作详解

传输规则

一个基本传输单元称作一个相

一个相包含总共9比特,前8比特为数据,第9比特为 Don‘t-Care bit 不关心比特,该第9比特的数据取决于

传输任务是读还是写。一个传输任务的最大相个数是3

EMIO方式模拟SCCB时序进行读写操作详解

3相写传输规则

提供些传输,主机能将1byte数据写至指定从机

EMIO方式模拟SCCB时序进行读写操作详解

ID Address表示指定从机的地址

Sub-address表示从机的寄存器

后面是数据,1字节数据

3个相为后一位都是Don’t-Care bits

2相写传输规则

EMIO方式模拟SCCB时序进行读写操作详解

2相写传送是在2相读传送前的,它的目的是指明主机要从哪个从机的哪个寄存器读数据。

2相读传输规则

EMIO方式模拟SCCB时序进行读写操作详解

在2相读前面必须有2相写或者3相写,否则2相读没有办法读出哪个寄存器发的数据,主机必须将NA bit置为1(否则OV摄像头会把SIOD拉低)

“X”表示Don‘t-Care bit。意思是Master可以不关注此bit。从OV给的手册来看,Slave也可以驱动此bit为低,然后Master来确认响应。当然,Master也可以不关注。在SCCB手册中,这部分说的比较含糊,所以,简单来说,在SCCB中,Master不关注是否传输数据有错误发生。说实话,为了所做的设计可靠,还是应该关注的。

二、EMIO介绍

zynq的GPIO,分为两种,MIO(multiuse I/O)和EMIO(extendable multiuse I/O)

EMIO方式模拟SCCB时序进行读写操作详解

MIO分配在bank0和bank1直接与PS部分相连,EMIO分配在bank2和接和PL部分相连。除了bank1是22-bit之外,其他的bank都是32-bit。所以MIO有53个引脚可供我们使用,而EMIO有64个引脚可供我们使用。

使用EMIO的好处就,当MIO不够用时,PS可以通过驱动EMIO控制PL部分的引脚,接下来就来详细介绍下EMIO的使用。

EMIO的使用和MIO的使用其实是非常相似的。区别在于,EMIO的使用相当于,是一个PS + PL的结合使用的例子。所以,EMIO需要分配引脚,以及编译综合生成bit文件。

三、例子

1、新建vivado 工程,create一个block design,添加zynq PS核

EMIO方式模拟SCCB时序进行读写操作详解

2、运行自动连接

EMIO方式模拟SCCB时序进行读写操作详解

3、双击PS IP进行配置,增加三个EMIO,其中两个是SCCB的数据和时钟,另外一个拿来做复位

EMIO方式模拟SCCB时序进行读写操作详解

4、把新增的EMIO连接出来,并把时钟接好

5、增加一个clock IP,修改输出频率为24Mhz,把输出管脚接出

EMIO方式模拟SCCB时序进行读写操作详解

5、create HDL wrapper,生产HDL顶层文件,双击打开,可以看到刚才接出来的EMIO管脚名为gpio_0_tri_io

EMIO方式模拟SCCB时序进行读写操作详解

6、创建约束文件,我的摄像头的SIOD接到了W8,SIOC接到了V8,RESET接到AB11,XCLK接到W11

EMIO方式模拟SCCB时序进行读写操作详解

7、综合,生成bit文件,导出hardware并启动SDK,创建项目,添加如下代码

EMIO_init.h

#ifndef EMIO_INIT_H_

#define EMIO_INIT_H_

#include“xgpiops.h”

int EMIO_SCCB_init(void);

#define SIOD_PIN 54

#define SIOC_PIN 55

#define RESET_PIN 56

#define DIRECTION_INPUT 0

#define DIRECTION_OUTPUT 1

void CLOCK_HIGH(void);

void CLOCK_LOW(void);

void DATA_HIGH(void);

void DATA_LOW(void);

void DATA_INPUT(void);

void DATA_OUTPUT(void);

int GET_DATA(void);

void SCCB_reset(void);

#endif /* EMIO_INIT_H_ */

EMIO_init.c

#include “xgpiops.h”

#include “EMIO_init.h”

static XGpioPs psGpioInstancePtr;

int EMIO_SCCB_init(void)

{

XGpioPs_Config* GpioConfigPtr;

int xStatus;

GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);

if(GpioConfigPtr == NULL)

return XST_FAILURE;

xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr,GpioConfigPtr-》BaseAddr);

if(XST_SUCCESS != xStatus)

print(“EMIO INIT FAILED \n\r”);

XGpioPs_SetDirectionPin(&psGpioInstancePtr, SIOC_PIN,DIRECTION_OUTPUT);

XGpioPs_SetDirectionPin(&psGpioInstancePtr, SIOD_PIN,DIRECTION_OUTPUT);

XGpioPs_SetDirectionPin(&psGpioInstancePtr, RESET_PIN,DIRECTION_OUTPUT);

XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, SIOC_PIN,1);

XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, SIOD_PIN,1);

XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, RESET_PIN,1);//

return xStatus;

}

void SCCB_reset(void)

{

XGpioPs_WritePin(&psGpioInstancePtr,RESET_PIN, 0);

usleep(50*1000);

XGpioPs_WritePin(&psGpioInstancePtr,RESET_PIN, 1);

}

void CLOCK_HIGH(void)

{

XGpioPs_WritePin(&psGpioInstancePtr,SIOC_PIN, 1);

}

void CLOCK_LOW(void)

{

XGpioPs_WritePin(&psGpioInstancePtr,SIOC_PIN, 0);

}

int GET_DATA(void)

{

return XGpioPs_ReadPin(&psGpioInstancePtr,SIOD_PIN);

}

void DATA_INPUT(void)

{

XGpioPs_SetDirectionPin(&psGpioInstancePtr, SIOD_PIN,DIRECTION_INPUT);//

}

void DATA_OUTPUT(void)

{

XGpioPs_SetDirectionPin(&psGpioInstancePtr, SIOD_PIN,DIRECTION_OUTPUT);//

}

void DATA_HIGH(void)

{

XGpioPs_WritePin(&psGpioInstancePtr,SIOD_PIN, 1);

}

void DATA_LOW(void)

{

XGpioPs_WritePin(&psGpioInstancePtr,SIOD_PIN,0);

}

SCCB_ctrl.h

#ifndef SCCB_CTRL_H_

#define SCCB_CTRL_H_

void sccb_start(void);

void sccb_end(void);

void sccb_sendbyte( unsigned char value );

void sccb_senddata(unsigned char subaddr,unsigned char value);

int sccb_readdata(unsigned char addr, unsigned char *value);

#endif /* SCCB_CTRL_H_ */

SCCB_ctrl.c

#include “sleep.h”

#include “EMIO_init.h”

#define OV7670_WRITE_ADDR 0x42

#define OV7670_READ_ADDR 0x43

#define SCCB_DELAY usleep(10)

void sccb_start(void)

{

CLOCK_HIGH();

DATA_HIGH();

SCCB_DELAY;

DATA_LOW();

SCCB_DELAY;

CLOCK_LOW();

SCCB_DELAY;

}

void sccb_end(void)

{

DATA_LOW();

SCCB_DELAY;

CLOCK_HIGH();

SCCB_DELAY;

DATA_HIGH();

SCCB_DELAY;

}

int sccb_sendbyte( unsigned char value )

{

unsigned char tmp = value;

unsigned char i=0,ack;

for(i=0; i《8; i++)

{

if(tmp & 0x80 )

DATA_HIGH();

else

DATA_LOW();

SCCB_DELAY;

CLOCK_HIGH();

SCCB_DELAY;

CLOCK_LOW();

SCCB_DELAY;

tmp《《=1;

}

DATA_HIGH();

DATA_INPUT();

SCCB_DELAY;

CLOCK_HIGH();

ack = GET_DATA();

SCCB_DELAY;

CLOCK_LOW();

SCCB_DELAY;

DATA_OUTPUT();

if(ack==1)

{

return -1;

}

return 0;

}

unsigned char sccb_readbyte( unsigned char addr)

{

unsigned char i=0,data=0;

DATA_HIGH();

DATA_INPUT();

for(i=0; i《8; i++)

{

CLOCK_HIGH();

SCCB_DELAY;

data 《《= 1;

if(GET_DATA())

data |= 1;

SCCB_DELAY;

CLOCK_LOW();

SCCB_DELAY;

}

DATA_OUTPUT();

DATA_HIGH();

SCCB_DELAY;

CLOCK_HIGH();

SCCB_DELAY;

CLOCK_LOW();

SCCB_DELAY;

DATA_HIGH();

return data;

}

int sccb_readdata(unsigned char addr, unsigned char *value)

{

// 两相写

sccb_start();

if(sccb_sendbyte(OV7670_WRITE_ADDR) != 0)

{

sccb_end();

return -1;

}

if(sccb_sendbyte(addr) != 0)

{

sccb_end();

return -1;

}

sccb_end();

SCCB_DELAY;

// 两相读

sccb_start();

if(sccb_sendbyte(OV7670_READ_ADDR) != 0)

{

sccb_end();

return -1;

}

*value = sccb_readbyte(addr);

sccb_end();

return 0;

}

void sccb_senddata(unsigned char addr,unsigned char value)

{

sccb_start();

sccb_sendbyte(OV7670_WRITE_ADDR);

sccb_sendbyte(addr);

sccb_sendbyte(value);

sccb_end();

}

修改main函数,读取PID和VER寄存器,验证是否正确,实际上我读取到的VER是0X73

int main()

{

unsigned char data;

init_platform();

print(“Hello World\n\r”);

EMIO_SCCB_init();

SCCB_reset();

usleep(500*1000);

while(1)

{

//读取PID

data = 0;

if(sccb_readdata(0x0A,&data) != 0)

{

print(“error\n\r”);

}

else

{

if(data != 0x76)

print(“error\n\r”);

}

//读取VER

data = 0;

if(sccb_readdata(0x0B,&data) != 0)

{

print(“error\n\r”);

}

else

{

if(data != 0x73)

print(“error\n\r”);

}

}

cleanup_platform();

return 0;

}

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SCCB
    +关注

    关注

    0

    文章

    11

    浏览量

    11265
  • Vivado
    +关注

    关注

    18

    文章

    790

    浏览量

    65099
收藏 人收藏

    评论

    相关推荐

    IIC总线协议与SCCB协议的区别

    总线支持连续写,故写完地址之后不需要再发送起始信号;这也正是与SCCB最大的不同之处;6、无论读写,应答位总线都需要释放,至于如果不释放会不会对时序产生破坏影响还不清楚,有待验证; (摘自百度)总结
    发表于 08-07 12:43

    ov7725的使用与OV7725 SCCB的接口时序

    ov7725介绍ov7725(OmniVsion_OV7725)是由OV(豪威科技)生产的一款CMOS的摄像头,已经被中国财团收购。OV7725 SCCB的接口时序(OmniVision
    发表于 07-28 08:07

    如何对SCCB协议进行读写操作

    ov7725是什么?ov7725摄像头是由哪些部分组成的?如何对SCCB协议进行读写操作
    发表于 10-20 07:09

    如何使用SPI?如何对SPI的操作时序进行读写

    nRF24L01+ 2.4GHz无线收发器的主要特性有哪些?如何使用SPI?如何对SPI的操作时序进行读写呢?
    发表于 12-20 06:32

    SRAM的简单的读写操作教程

    SRAM的简单的读写操作教程 SRAM的读写时序比较简单,作为异步时序设备,SRAM对于时钟同步的要求不高,可以在低速下运行,下面就介绍S
    发表于 02-08 16:52 140次下载

    SCCB接口时序

    SCCB的总线时序与I2C基本相同,它的响应信号ACK被称为一个传输单元的第9位,分为Dont care和NA。Dont care位由从机产生;NA位由主机产生,由于SCCB不支持多字节的读写
    发表于 03-26 16:00 168次下载
    <b class='flag-5'>SCCB</b>接口<b class='flag-5'>时序</b>

    DS18B20读写操作程序详解

    DS18B20的初始化、读写操作以及程序详解
    发表于 11-06 18:04 2.5w次阅读

    EMIO方式模拟I2C时序对ADV7511进行读写

    创建硬件工程,很简单,PS接出两个EMIO和一个74.25M时钟
    发表于 11-18 13:50 3682次阅读

    SCCB的工作模式及示例代码资料合集免费下载

    如果对OV7620的默认工作模式不满意,就可写SCCB。 对于SCCB操作,首先必需使能IICB,这个在OV7620上需要跳线解决。网上很多人用普通IO口模拟
    发表于 05-13 08:00 3次下载
    <b class='flag-5'>SCCB</b>的工作模式及示例代码资料合集免费下载

    总线的操作时序操作方式详解

    操作时序(timing):各信号有效的先后顺序及配合关系
    的头像 发表于 06-24 16:21 1w次阅读
    总线的<b class='flag-5'>操作</b><b class='flag-5'>时序</b>和<b class='flag-5'>操作</b><b class='flag-5'>方式</b><b class='flag-5'>详解</b>

    软件模拟SPI时序实现25Q64读写操作

    软件模拟SPI时序实现25Q64读写操作单片机采用SPI/IIC通讯协议访问外围电子模块如:显示屏、EEPROM、FLASH、各种电子传感器等等越来越多,掌握SPI/IIC通讯协议访问
    发表于 11-20 12:06 6次下载
    软件<b class='flag-5'>模拟</b>SPI<b class='flag-5'>时序</b>实现25Q64<b class='flag-5'>读写</b><b class='flag-5'>操作</b>

    STM32入门开发: 介绍SPI总线、读写W25Q64(FLASH)(硬件+模拟时序)

    时序,本文示例代码里同时采用模拟时序和硬件时序两种方式读写W25Q64。
    发表于 12-02 09:06 35次下载
    STM32入门开发: 介绍SPI总线、<b class='flag-5'>读写</b>W25Q64(FLASH)(硬件+<b class='flag-5'>模拟</b><b class='flag-5'>时序</b>)

    软件模拟SPI时序实现25Q64读写操作

    软件模拟SPI时序实现25Q64读写操作单片机采用SPI/IIC通讯协议访问外围电子模块如:显示屏、EEPROM、FLASH、各种电子传感器等等越来越多,掌握SPI/IIC通讯协议访问
    发表于 12-22 19:14 15次下载
    软件<b class='flag-5'>模拟</b>SPI<b class='flag-5'>时序</b>实现25Q64<b class='flag-5'>读写</b><b class='flag-5'>操作</b>

    Python对txt进行读写操作

    Python对txt进行读写操作
    的头像 发表于 01-11 15:16 619次阅读

    SCCB IIC接口设计

    SCCB协议是类似于IIC协议,它常用于OV系列摄像头配置接口中。下图为sio_c和sio_d的时序图,具体的时序协议请看《SCCB接口时序
    的头像 发表于 11-06 10:42 261次阅读
    <b class='flag-5'>SCCB</b> IIC接口设计