最近调试i2c遇到一些问题,在此备忘,总结一句话,还是要特别注意时序,哪怕一个高低点平的错误都可能导致程序工作不正常
另外对于stm32 提供的i2c固件例程一直没有调好,特别烦人
#include "SystemInit.h"
#include <stdint.h>
#include "stm32_eval_i2c_ee.h"
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Send_Byte(u8 txd);
u8 IIC_Read_Byte(unsigned char ack);
u8 IIC_Wait_Ack(void);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
__IO uint32_t timeremain = 0;
void delay_us(__IO uint32_t arg)
{
volatile uint16_t i = 0;
#if 0
while(arg--)
{
for(i = 5; i > 0; i--);
}
#else
timeremain = arg;
EnableTimer2();
while(timeremain)
{
}
#endif
}
/*
#define SDA_IN() {IIC_SDA_PORT->CRH&=0XFFFF0FFF;IIC_SDA_PORT->CRH|=8<<12;}
#define SDA_OUT() {IIC_SDA_PORT->CRH&=0XFFFF0FFF;IIC_SDA_PORT->CRH|=3<<12;}
*/
#define Set_IIC_SCL {GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_PIN);}
#define Clr_IIC_SCL {GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_PIN);}
#define Set_IIC_SDA {GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_PIN);}
#define Clr_IIC_SDA {GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA_PIN);}
#define READ_SDA (GPIO_ReadInputDataBit(IIC_SDA_PORT, IIC_SDA_PIN))
#define IIC_SCL_PORT GPIOD
#define IIC_SCL_CLK RCC_APB2Periph_GPIOD
#define IIC_SCL_PIN GPIO_Pin_8
#define IIC_SDA_PORT GPIOD
#define IIC_SDA_CLK RCC_APB2Periph_GPIOD
#define IIC_SDA_PIN GPIO_Pin_9
void SDA_IN()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}
void SDA_OUT()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}
#define Set_IIC_SCL {GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_PIN);}
#define Clr_IIC_SCL {GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_PIN);}
#define Set_IIC_SDA {GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_PIN);}
#define Clr_IIC_SDA {GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA_PIN);}
#define READ_SDA (GPIO_ReadInputDataBit(IIC_SDA_PORT, IIC_SDA_PIN))
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( IIC_SCL_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
Set_IIC_SCL;
Set_IIC_SDA;
}
/*
#define Set_IIC_SCL_2 {GPIO_SetBits(GPIOD,GPIO_Pin_8);}
#define Clr_IIC_SCL_2 {GPIO_ResetBits(GPIOD,GPIO_Pin_8);}
#define Set_IIC_SDA_2 {GPIO_SetBits(GPIOD,GPIO_Pin_9);}
#define Clr_IIC_SDA_2 {GPIO_ResetBits(GPIOD,GPIO_Pin_9);}
*/
void IIC_Start(void)
{
SDA_OUT();
Set_IIC_SDA;
Set_IIC_SCL;
delay_us(4);
Clr_IIC_SDA;
delay_us(4);
Clr_IIC_SCL;
}
void IIC_Stop(void)
{
SDA_OUT();
//Set_IIC_SCL;
//delay_us(4);
Clr_IIC_SDA;
delay_us(4);
Set_IIC_SCL;
delay_us(4);
Set_IIC_SDA;
delay_us(4);
}
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN();
Set_IIC_SDA;
delay_us(4);
//SDA_IN();
Set_IIC_SCL;
delay_us(4);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
Clr_IIC_SCL;
//delay_us(4);
//SDA_OUT();
return 0;
}
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
Clr_IIC_SCL;
for(t=0;t<8;t++)
{
if ((txd&0x80)>>7)
Set_IIC_SDA
else
Clr_IIC_SDA;
txd<<=1;
delay_us(2);
Set_IIC_SCL;
delay_us(2);
Clr_IIC_SCL;
delay_us(2);
}
}
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();
for(i=0;i<8;i++ )
{
Clr_IIC_SCL;
delay_us(2);
Set_IIC_SCL;
delay_us(2);
receive<<=1;
if(READ_SDA)receive++;
} /*
if (!ack)
IIC_NAck();
else
IIC_Ack();
*/
return receive;
}
u8 EE_TYPE = 0;
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
IIC_Send_Byte(0XA0);
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1);
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();
return temp;
}
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
IIC_Start();
IIC_Send_Byte(0XA0);
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr);
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite);
IIC_Wait_Ack();
IIC_Stop();
}
void time2callback()
{
if (timeremain > 0) timeremain--;
if (timeremain == 0)
{
DisableTimer2();
}
}
/**
* @fn void main(int argc, char** argv)
* @brief main, system entry function
* @param argc: input params count
* @param argv: input params
* @return none
*/
void main(int argc, char** argv)
{
InitSystem;
InitTimer2();
RegTimer2Callback(time2callback);
int data, addr, readdata;
IIC_Init();
while(1)
{
data = 0xff;
addr = 0x1;
readdata = 0;
for (addr = 0; addr < 16; addr++)
{
AT24CXX_WriteOneByte(addr, data);
delay_us(5 * 100);
}
for (addr = 0; addr < 16; addr++)
{
readdata = AT24CXX_ReadOneByte(addr);
// printf("read data = %X\n", readdata);
}
delay_us(10000);
}
}
uint32_t sEE_TIMEOUT_UserCallback(void)
{
/* Use application may try to recover the communication by resetting I2C
peripheral (calling the function I2C_SoftwareResetCmd()) then re-start
the transmission/reception from a previously stored recover point.
For simplicity reasons, this example only shows a basic way for errors
managements which consists of stopping all the process and requiring system
reset. */
printf("Communication ERROR!");
/* Block communication and all processes */
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
/*******************************************************************************
* Function Name : assert_failed
* Description : Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* Input : - file: pointer to the source file name
* - line: assert_param error line source number
* Output : None
* Return : None
*******************************************************************************/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{}
}
#endif