你好,我使用stm32f103c8t6的最小系统板来驱动OV7670(无FIFO无晶振),在读取OV7670的ID号时,只返回0xFF(或者说是OV7670完全没有反应),以下是我的代码,麻烦大家抽空帮我看一下,谢谢啦!
注:1、SCL和SDA均已加上拉电阻. 2、我尝试使用“不会游泳的企鹅”的时钟代码接在OV7670的MCLK上,但仍然无法读取数据(我没发现我的OV7670上有XCLK)
#include "stm32f10x.h" // Device header
#include "stdbool.h"
#define SCCB_SCL GPIO_Pin_9
#define SCCB_In_SDA GPIO_Pin_10
#define SCCB_Out_SDA GPIO_Pin_10
//us延时
void delay_us(u16 time)
{
u16 i=0;
while(time--)
{
i=5; //自己定义
while(i--) ;
}
}
//初始化SCCB
void SCCB_Init ( void )
{
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA , ENABLE );
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ;
GPIO_InitStructure.GPIO_Pin = SCCB_SCL | SCCB_In_SDA ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init ( GPIOA , &GPIO_InitStructure ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 1 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) 1 ) ;
}
//SCCB起始信号
void SCCB_Start ( void )
{
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) 1 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 1 ) ;
delay_us ( 10 );
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) 0 ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 0 ) ;
}
//SCCB结束信号
void SCCB_Stop ( void )
{
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) 0 ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 1 ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) 1 ) ;
delay_us ( 10 ) ;
}
//SCCB主机产生应答(NA位)0:继续;1:结束
//SCCB只能用结束,因为SCCB不可连续读
void SCCB_NoAck ( uint8_t AckBit )
{
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) AckBit ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 1 ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 0 ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) 0 ) ;
}
/*
SCCB发送字节
返回值: 0为接收成功
1为接收失败
*/
bool SCCB_SendByte ( uint8_t Data )
{
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 0 ) ;
delay_us ( 5 ) ;
bool res = 0 ;
uint8_t Byte = 0 ;
for ( uint8_t i = 0 ; i < 8 ; i++ )
{
Byte = Data & ( 0x80>>i ) ;
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) Byte ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 1 ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 0 ) ;
}
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) 1 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 1 ) ;
if ( GPIO_ReadInputDataBit ( GPIOA , SCCB_In_SDA ) == 0 )
res = 0 ;
else if ( GPIO_ReadInputDataBit ( GPIOA , SCCB_In_SDA ) == 1 )
res = 1 ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 0 ) ;
return res ;
}
uint8_t SCCB_ReadByte ( void )
{
uint8_t RxData = 0x00 , temp = 0 ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 0 ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 1 ) ;
for ( char i = 0 ; i < 8 ; i++ )
{
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 1 ) ;
delay_us ( 10 ) ;
temp = GPIO_ReadInputDataBit ( GPIOA , SCCB_In_SDA ) ;
RxData = ( RxData << 1 ) | temp ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 0 ) ;
delay_us ( 10 ) ;
}
return RxData ;
}
uint8_t Receive_Ack ( void )
{
uint8_t AckBit ;
GPIO_WriteBit ( GPIOA ,SCCB_Out_SDA , ( BitAction ) 1 ) ;
delay_us ( 10 ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 1 ) ;
delay_us ( 10 ) ;
AckBit = GPIO_ReadInputDataBit ( GPIOA , SCCB_In_SDA ) ;
GPIO_WriteBit ( GPIOA ,SCCB_SCL , ( BitAction ) 0 ) ;
return AckBit ;
}
#include "stm32f10x.h" // Device header
#include "SCCB.h"
#include "Delay.h"
#define OV7670_Address 0x42
void SendTo_OV7670 ( uint8_t reg , uint8_t Data )
{
SCCB_Start ( ) ;
SCCB_SendByte ( OV7670_Address ) ;
delay_us ( 100 ) ;
SCCB_SendByte ( reg ) ;
delay_us ( 100 ) ;
SCCB_SendByte ( Data ) ;
delay_us ( 100 ) ;
SCCB_Stop ( ) ;
}
uint8_t Read_OV7670 ( uint8_t reg )
{
uint8_t Data = 0 ;
SCCB_Start ( ) ;
SCCB_SendByte ( OV7670_Address ) ;
delay_us ( 100 ) ;
SCCB_SendByte ( reg ) ;
delay_us ( 100 ) ;
SCCB_Stop ( ) ;
delay_us ( 100 ) ;
SCCB_Start ( ) ;
SCCB_SendByte ( OV7670_Address |0x01 ) ;
delay_us ( 100 ) ;
Data = SCCB_ReadByte ( ) ;
SCCB_NoAck ( 1 ) ;
delay_us ( 100 ) ;
SCCB_Stop ( ) ;
return Data ;
}
uint8_t OV7670_Init ( void )
{
uint8_t temp = 0 ;
SCCB_Init ( ) ;
SendTo_OV7670 ( 0x12 , 0x80 ) ; //复位OV7670
Delay_s ( 3 ) ;
SendTo_OV7670 ( 0x11 , 0x9F ) ; //设置外部时钟
SendTo_OV7670 ( 0x6B , 0x00 ) ;
temp = Read_OV7670 ( 0x0A ) ;
return temp ;
}
#include "stm32f10x.h"
#include "SCCB.h"
#include "OLED.h"
#include "OV7670.h"
#include "MyI2C.h"
int main()
{
OLED_Init ( ) ;
delay_us ( 1000 ) ;
delay_us ( 1000 ) ;
delay_us ( 1000 ) ;
delay_us ( 1000 ) ;
delay_us ( 1000 ) ;
delay_us ( 1000 ) ;
uint8_t a = OV7670_Init ( ) ;
OLED_ShowHexNum ( 1 , 1 , a , 2 ) ;
while(1)
{
}
}
以上便是我写的代码,麻烦了,谢谢!