现在在捣鼓这个ov7670 v2.2 带fifo的摄像头,目前通过sccb进行读写测试时,写摄像头有应答,可以; 但是读出来的数据全部是0xff,
SCCB->SCL 外部已经加了上4.7K拉电阻
SCCB->SDA 外部已经加了上4.7K拉电阻
程序如下:
#define SCCB_ID
0X42
//OV7670的ID
#define SCCB_SEND_ACK
(0x10)
#define SCCB_SEND_NACK
(0x11)
#define SCCB_STATE_NACK
(0x20)
#define SCCB_STATE_ACK
(0x21)
#define SCCB_SCL GPIOEout(2) // 定义 I2C-SCL 为 GPIOE_Pin_2
#define SCCB_SDA GPIOEout(3) // 定义 I2C-SDA 为 GPIOE_Pin_3
#define SCCB_SCL_L (SCCB_SCL=0) //#define I2C1_SCL_L GPIOB->BSRRL = GPIO_Pin_6
#define SCCB_SCL_H (SCCB_SCL=1) //#define I2C1_SCL_H GPIOB->BSRRH = GPIO_Pin_6
#define SCCB_SDA_L (SCCB_SDA=0) //#define I2C1_SDA_L GPIOB->BSRRL = GPIO_Pin_7
#define SCCB_SDA_H (SCCB_SDA=1) //#define I2C1_SDA_H GPIOB->BSRRH = GPIO_Pin_7
#define SCCB_SDA_IN() GPIOEin(3)
#define SCCB_SDA_OUT() GPIOEout(3)
#define SCCB_SDA_READ ((GPIOE->IDR) & GPIO_Pin_3)
void SCCB_Delay(u16 i)
{
while(i--);
}
#define SCCB_Delay_5us SCCB_Delay(8)
#define SCCB_Delay_3us SCCB_Delay(6)
#define SCCB_Delay_2us SCCB_Delay(4)
#define SCCB_Delay_1us SCCB_Delay(2)
void SCCB_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
//SCCB SCL->
E2, SDA->
E3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOE, &GPIO_InitStructure);
SCCB_SCL_H;
SCCB_Delay_5us;
SCCB_Delay_5us;
SCCB_SDA_H;
SCCB_Delay_5us;
}
/**********************************************************
启动子程序
在 SCL 高电平期间 SDA 发生负跳变【从高到低】
scl为高电平期间,sda产生一个下降沿
**********************************************************/
u8 SCCB_Start(void)
{
u8 i;
SCCB_SDA_H;
SCCB_SCL_H;
SCCB_Delay_5us;
i=0;
while((SCCB_SDA_READ == 1) && (i<250))
//如果SCCB_SDA=1,表示被控器无应答或损坏
{
i++;
//计时开始,
if(i==249)
//如果计时到了249,器件还没有应答则自动退出
return (SCCB_STATE_NACK);
}
SCCB_SDA_L;
SCCB_Delay_5us;
i=0;
while((SCCB_SDA_READ == 1) && (i<250))
//如果SCCB_SDA=1,表示被控器无应答或损坏
{
i++;
//计时开始,
if(i==249)
//如果计时到了249,器件还没有应答则自动退出
return (SCCB_STATE_NACK);
}
SCCB_SCL_L;
SCCB_Delay_2us;
return SCCB_STATE_ACK;
//SUCCESS;
}
/**********************************************************
停止子函数
在 SCL 高电平期间 SDA 发生正跳变 【从低到高】
scl高电平期间,sda产生一上升沿
**********************************************************/
void SCCB_Stop(void)
{
SCCB_SDA_L;
SCCB_Delay_1us;
SCCB_SCL_H;
SCCB_Delay_5us;
SCCB_SDA_H;
SCCB_Delay_3us;
}
/**********************************************************
//读一字节 ack: SCCB_SEND_ACK 时应答,SCCB_SEND_NACK 时不应答
**********************************************************/
u8 SCCB_ReadByte(unsigned char ack)
//【非常好】
{
u8 i = 0,Read_Data=0;
SCCB_SDA_H;
SCCB_SDA_IN();
//设置SDA为输入
for(i=0;i<8;i++) // 循环移入8个位
{
SCCB_Delay_1us; //5us
SCCB_SCL_L;
SCCB_Delay_5us;
SCCB_SCL_H;
SCCB_Delay_5us;
Read_Data <<= 1;
if(SCCB_SDA_READ) //读SDA
{
Read_Data++;
}
}
SCCB_SCL_L;
SCCB_Delay_3us; //5us
SCCB_SDA_OUT();
//设置SDA为输出
SCCB_Delay_3us; //5us
if(ack == SCCB_SEND_ACK)
SCCB_SDA_L; //发送应答
else
SCCB_SDA_H; //发送非应答
SCCB_Delay_2us; //5us
SCCB_SCL_H;
SCCB_Delay_5us;
SCCB_SCL_L;
SCCB_Delay_1us; //5us
return (Read_Data);
}
/**********************************************************
//向总线写一字节,并返回有无应答
**********************************************************/
unsigned char SCCB_WriteByte(unsigned char write_data)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(write_data & 0x80)
SCCB_SDA_H;
else
SCCB_SDA_L;
SCCB_Delay_1us;
SCCB_SCL_H; //置时钟线为高,通知被控器开始接收数据位
SCCB_Delay_5us;
SCCB_SCL_L;
write_data <<= 1;
}
SCCB_SDA_IN();
//设置SDA为输入
SCCB_Delay_2us;
SCCB_SDA_H;
SCCB_Delay_2us;
SCCB_SCL_H;
SCCB_Delay_3us;
i=0;
while((SCCB_SDA_READ == 1) && (i<250))
//如果SCCB_SDA=1,表示被控器无应答或损坏
{
i++;
//计时开始,
if(i==249)
//如果计时到了249,器件还没有应答则自动退出
return (SCCB_STATE_NACK);
}
SCCB_SCL_L;
SCCB_Delay_2us;
SCCB_SDA_OUT();
//设置SDA为输出
return (SCCB_STATE_ACK);
}
//写寄存器
//返回值:SCCB_STATE_ACK->成功; SCCB_STATE_NACK->失败.
u8 SCCB_WR_Reg(u8 reg,u8 data)
{
u8 res = SCCB_STATE_NACK;
SCCB_Start();
//启动SCCB传输
res=SCCB_WriteByte(SCCB_ID);
//写器件ID
if(SCCB_STATE_NACK == res)
res=1;
if(SCCB_STATE_NACK == SCCB_WriteByte(reg))
res=1;
if(SCCB_STATE_NACK == SCCB_WriteByte(data))
res=1;
SCCB_Stop();
return res;
}
//读寄存器
//返回值:读到的寄存器值
u8 SCCB_RD_Reg(u8 reg)
{
u8 val=0;
SCCB_Start();
//启动SCCB传输
printexp(USART1, "DCMI_id",SCCB_WriteByte(SCCB_ID),16)
;
//写器件ID
//SCCB_WriteByte(reg);
//写寄存器地址
printexp(USART1, "DCMI_reg",SCCB_WriteByte(reg),16)
;
SCCB_Stop();
SCCB_Delay_5us;
//设置寄存器地址后,才是读
SCCB_Start();
//SCCB_WriteByte(SCCB_ID|0X01);
//发送读命令
printexp(USART1, "SCCB_ID|0X01",SCCB_WriteByte(SCCB_ID|0X01),16)
;
val=SCCB_ReadByte(SCCB_SEND_NACK);
//读取数据
SCCB_Stop();
printexp(USART1, "SCCB_val",val,16)
;
return val;
}
//初始化成功返回0,否则返回1
u8 Cam_Init(void)
{
u8 temp;
u16 i=0;
GPIO_InitTypeDef GPIO_InitStructure;
DCMI_InitTypeDef DCMI_InitStructure;
//DMA_InitTypeDef DMA_InitStructure;
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
//DCMI
//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
//DMA2
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE, ENABLE);//使能DCMI的GPIO时钟
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);
//DCMI D0
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI);
//DCMI D1
GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI);
//DCMI D2
GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI);
//DCMI D3
GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI);
//DCMI D4
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
//DCMI D5
GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI);
//DCMI D6
GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI);
//DCMI D7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//---------------------------------------控制信号引脚定义---------------------------------------
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4| GPIO_Pin_6| GPIO_Pin_8;
//DCMI 2->WRST, 3->RRST, 4->WEN, 6->RCLK, 8->OE(CS)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
//SYSCFG->CMPCR = 0x00000001;
//使用IO 补偿单元,
//当GPIO 速度超过50M 的时候要考虑使用此设置
GPIO_Init(GPIOA, &GPIO_InitStructure);
//--------------VSYNC IN ---------------------------------
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
//DCMI VSYNC
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
//同步信号检测IO
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
//GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
//SYSCFG->CMPCR = 0x00000001;
GPIO_Init(GPIOB, &GPIO_InitStructure);
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
DCMI_Init(&DCMI_InitStructure);
/*
DMA_DeInit(DMA2_Stream1);
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = FSMC_LCD_ADDRESS;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
*/
SCCB_Init();
//初始化SCCB 的IO口
temp = SCCB_WR_Reg(0x12,0x80);
if(SCCB_STATE_NACK == temp)
return 1;
//复位SCCB
delay_ms(50);
//读取产品型号
temp=SCCB_RD_Reg(0x0b); //就是这里,通过SCcB读取时,数据总是0xff,不知道河谷????
printexp(USART1, "DCMI_0X0B",temp,16)
; //读取的数据发回给电脑查看
if(temp!=0x73)
return 2;
temp=SCCB_RD_Reg(0x0a);
if(temp!=0x76)
return 2;
//初始化序列
for(i=0;i<sizeof(ov7670_init_reg_tbl)/sizeof(ov7670_init_reg_tbl[0])/2;i++)
{
SCCB_WR_Reg(ov7670_init_reg_tbl
[0],ov7670_init_reg_tbl[1]);
delay_ms(2);
}
return 0x00; //OK
}
一周热门 更多>