2,开发环境:Keil uv5
3,参考文献:https://blog.csdn.net/u011964923/article/details/50966735
最近在移植OV7670带FIFO摄像头到STM32F103,发现在摄像头初始化的地方总是出错,无法读取IDCode,各种尝试,返回的IDCode都是0,
int Sensor_Init(void)
{
uint16_t i = 0;
uint8_t Sensor_IDCode = 0;
FIFO_WE_H();//先置1使能
I2C_Configuration();
if( 0 == I2C_WriteByte ( 0x12, 0x80 , ADDR_OV7670 ) ) /* Reset SCCB */
{
return 1 ;
}
Delay(1500);
if( 0 == I2C_ReadByte( &Sensor_IDCode, 1, 0x0b, ADDR_OV7670 ) ) /* read ID */
{
return 2; /* error*/
}
// while(1){
// USART_OUT(USART1," Code->%d",Sensor_IDCode);
// Delay(500);
//}
if(Sensor_IDCode == OV7670) /* ID = OV7670 */
{
for( i = 0 ; i < OV7670_REG_NUM ; i++ )
{
if( 0 == I2C_WriteByte( OV7670_Reg[i][0], OV7670_Reg[i][1] , ADDR_OV7670 ) )
{
return 3;
}
}
}
else /* NO ID */
{
//led();
return 4;
}
return 0;
}
int I2C_ReadByte(uint8_t *pBuffer, uint16_t length, uint8_t ReadAddress, uint8_t DeviceAddress)
{
if(!I2C_Start())
{
return DISABLE;
}
I2C_SendByte( DeviceAddress ); /* 器件地址 */
if( !I2C_WaitAck() )
{
I2C_Stop();
return DISABLE;
}
I2C_SendByte( ReadAddress ); /* 设置低起始地址 */
I2C_WaitAck();
I2C_Stop();
if(!I2C_Start())
{
return DISABLE;
}
I2C_SendByte( DeviceAddress + 1 ); /* 器件地址 */
if(!I2C_WaitAck())
{
I2C_Stop();
return DISABLE;
}
while(length)
{
*pBuffer = I2C_ReceiveByte();
if(length == 1)
{
I2C_NoAck();
}
else
{
I2C_Ack();
}
pBuffer++;
length--;
}
I2C_Stop();
return ENABLE;
}
static int I2C_ReceiveByte(void)
{
uint8_t i = 8;
uint8_t ReceiveByte = 0;
SDA_H;
while(i--)
{
ReceiveByte <<= 1;
SCL_L;
I2C_delay();
SCL_H;
I2C_IN();
I2C_delay();
if(SDA_read)
{
ReceiveByte |= 0x01;
}
}
SCL_L;
I2C_OUT();
return ReceiveByte;
}
#define SDA_read SCCB_PORT->IDR & SCCB_PIN_SDL
在查找问题的过程中,引脚初始化的时候由于没仔细检查,走了很多弯路。
确认引脚接线正确,程序里面写个while循环,之后用示波器测量SCL(SIOC)引脚波形,发现波形正确, 但是为什么无法读取IDCode呢,于是用示波器测量SDA(SIOD)引脚的电平,发现都是高电平,于是怀疑是不是stm32的引脚没有配置正确或者是损坏了,于是手动设置SDA引脚对应的IO口的电平,检测是否有变化,这么一测问题就出来了我SDA引脚接的是PB3,但是检测PB3都是高电平,很是困惑,于是换一个IO口试试,换到PB4,这回又总是低电平,难道PB4也出问题了??经过查找资料,发现这篇文章:点击打开链接,乖乖,居然是这个原因!!!于是main函数中加入这句:
void disableJTAG()
{
/*开启GPIOB的外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);
//GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE); //屏蔽所有作为JTAG口的GPIO口
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //屏蔽PB口上IO口JTAG功能
}
这下终于正常了。
需要注意一点就是,该摄像头初始化的时候,只需要接3跟数据线即可,即SCL,SDA,OE(使能)脚,当然还有VCC,GND,即可,读取FIFO数据的时候则需要把其他的数据线接上。
于是把整个工程打包,分享给大家,希望能够帮助大家,下载之后,按照工程说明连好线之后,工程直接运行就能把摄像头初始化,非常方便^_^点击下载工程