1,开发板:STM32F103C8T6最小系统开发板。
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数据的时候则需要把其他的数据线接上。
于是把整个工程打包,分享给大家,希望能够帮助大家,下载之后,按照工程说明连好线之后,工程直接运行就能把摄像头初始化,非常方便^_^