⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ioi2c.c

📁 我写的用STM32F103的普通IO口做I2C通讯的模块
💻 C
字号:
/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
* File Name          : IOI2C.c
* Author             : liuwenhui
* Version            : V1.0
* Date               : 10/08/2007
* Description        : This file provides all the GPIO firmware functions.
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/

#include "stm32f10x_lib.h"
	  
u8 E0;         //非应答信号标志位
u8 NACK=0;     //错误标志位

#define I2C_SDA GPIO_Pin_2
#define I2C_SCL GPIO_Pin_1

void SetSDAIn(void);
void SetSDAOut(void);

void I2Cdelay(u8 nTim)
{
	int i,j,k;
	for (i=0; i<nTim; i++)	
		for(k=0; k<10; k++)
 			j++;
}

//启动I2C总线子函数
void I2CStart(void)
{
	GPIO_SetBits(GPIOA, I2C_SDA);	 //PA2(SDA)脚=1;3.3V
	GPIO_SetBits(GPIOA, I2C_SCL);	 //PA1(SCL)脚=1;3.3V
	I2Cdelay(5);
	GPIO_ResetBits(GPIOA, I2C_SDA);   //PA2(SDA)脚=0;0v
	I2Cdelay(5);
	GPIO_ResetBits(GPIOA, I2C_SCL);   //PA1(SCL)脚=0;0v
}

//停止I2C总线数据传送子函数
void I2CStop(void)
{

	GPIO_ResetBits(GPIOA, I2C_SDA);   //PA2(SDA)脚=0;0v
	GPIO_SetBits(GPIOA, I2C_SCL);	 //PA1(SCL)脚=1;3.3V
	I2Cdelay(5);
	GPIO_SetBits(GPIOA, I2C_SDA);	 //PA2(SDA)脚=1;3.3V
	I2Cdelay(5);
	GPIO_ResetBits(GPIOA, I2C_SCL);   //PA1(SCL)脚=0;0v
}

//发送应答位子程序
void Ack(void)  
{
	GPIO_ResetBits(GPIOA, I2C_SDA);   //PA2(SDA)脚=0;0v
	GPIO_SetBits(GPIOA, I2C_SCL);	 //PA1(SCL)脚=1;3.3V
	I2Cdelay(5);
	GPIO_SetBits(GPIOA, I2C_SDA);	 //PA2(SDA)脚=1;3.3V
	GPIO_ResetBits(GPIOA, I2C_SCL);   //PA1(SCL)脚=0;0v	
}

//发送非应答位子程序
void NoAck(void)   
{
	GPIO_SetBits(GPIOA, I2C_SDA);	 //PA2(SDA)脚=1;3.3V
	GPIO_SetBits(GPIOA, I2C_SCL);	 //PA1(SCL)脚=1;3.3V
	I2Cdelay(5);
	GPIO_ResetBits(GPIOA, I2C_SDA);   //PA2(SDA)脚=0;0v
	GPIO_ResetBits(GPIOA, I2C_SCL);   //PA1(SCL)脚=0;0v	
}


//应答位检查子程序,若检测不到非应答信号,置位E0
void TestAck(void) 
{
	u8 nSDA = 0;
	GPIO_SetBits(GPIOA, I2C_SDA);	 //PA2(SDA)脚=1;3.3V
	SetSDAIn();
	GPIO_SetBits(GPIOA, I2C_SCL);	 //PA1(SCL)脚=1;3.3V
	E0=0;
	I2Cdelay(1); //短延时
	nSDA= GPIO_ReadInputDataBit(GPIOA, I2C_SDA);  // 读取PA2(SDA)脚状态
	if(nSDA==1)   //如果SDA为1,表明非应答,置位非应答标志E0
		E0=1;
	GPIO_ResetBits(GPIOA, I2C_SCL);   //PA1(SCL)脚=0;0v	
	SetSDAOut();
}

//写一个字节数据子程序,n为待发送的数据
//发送时先假设为从高位往地位的顺序发送
void Write8Bit(u8 n)
{
	u8 i;
	u8 nSDA;
	for(i=8;i>0;i--)
	{
		nSDA=n&0x80;
		if (nSDA==0)
		{
			//SDA脚发0
			GPIO_ResetBits(GPIOA, I2C_SDA);   //PA2(SDA)脚=0;0v
		}
		else
		{
			//SDA脚发1
			GPIO_SetBits(GPIOA, I2C_SDA);	 //PA2(SDA)脚=1;3.3V
		}
		GPIO_SetBits(GPIOA, I2C_SCL);	 //PA1(SCL)脚=1;3.3V
		I2Cdelay(5);
		GPIO_ResetBits(GPIOA, I2C_SCL);   //PA1(SCL)脚=0;0v	
		GPIO_ResetBits(GPIOA, I2C_SDA);   //PA2(SDA)脚=0;0v
		n=n<<1;
	}
}


//读一个字节数据子程序
u8 Read8Bit(void)   
{
    u8 temp,rbyte=0;
	u8 nSDA = 0x68;
	for(temp=8;temp>0;temp--)
	{
		GPIO_SetBits(GPIOA, I2C_SDA);	 //PA2(SDA)脚=1;3.3V
		SetSDAIn();
		GPIO_SetBits(GPIOA, I2C_SCL);	 //PA1(SCL)脚=1;3.3V
		I2Cdelay(1); //短延时
		rbyte=rbyte<<1;
		nSDA= GPIO_ReadInputDataBit(GPIOA, I2C_SDA);  // 读取PA2(SDA)脚状态
		rbyte=rbyte|nSDA;
		GPIO_ResetBits(GPIOA, I2C_SCL);   //PA1(SCL)脚=0;0v	
		SetSDAOut();

		I2Cdelay(10); //延时
	}
	return(rbyte);
}


// 写1个字节数据到24C02子程序
void WriteOneByteI2C(u8 *Wdata,u8 SlaveAddress, u8 Address)
{    
	//Wdata为待发送字节,SlaveAddress为I2C外围器件的寻址地址,Address为数据写入地址
	u8 i;
	I2CStart(); //启动

	Write8Bit(SlaveAddress); //写入器件的寻址地址
	// 应答检查前一定要延时
	for(i=0;i<255;i++)
		I2Cdelay(0xef);
	TestAck();    //应答检查
	if(E0==1)
	{
		NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
		return;
	}

 	Write8Bit(Address); //写入器件的寻址地址
	// 应答检查前一定要延时
	for(i=0;i<255;i++)
		I2Cdelay(0xef);
	TestAck();    //应答检查
	if(E0==1)
	{
		NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
		return;
	}
 
	Write8Bit(*Wdata); //写一个字节
	// 应答检查前一定要延时
	for(i=0;i<255;i++)
		I2Cdelay(0xef);
	TestAck();    //应答检查
	if(E0==1)
	{
		NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
		return;
	}
	I2CStop();     //全部发送完则停止
} 

// 读24C02中的1个字节数据子程序
void ReadOneByteI2C(u8 *Rdata,u8 SlaveAddress,u8 Address) 
{   //Wdata为待发送字节,SlaveAddress为I2C外围器件的寻址地址,Address为数据写入地址
	u8 i;

	I2CStart(); //启动
	Write8Bit(0xa0); //写入器件的寻址地址
	// 应答检查前一定要延时
	for(i=0;i<255;i++)
		I2Cdelay(0xef);
	TestAck();    //应答检查
	if(E0==1)
	{
		NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
		return;
	}
	Write8Bit(Address); //写入器件的寻址地址
	// 应答检查前一定要延时
	for(i=0;i<255;i++)
		I2Cdelay(0xef);
	TestAck();    //应答检查
	if(E0==1)
	{
		NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
		return;
	}
	I2CStart(); //重新启动
	Write8Bit(SlaveAddress); //写入器件的寻址地址
	// 应答检查前一定要延时
	for(i=0;i<255;i++)
		I2Cdelay(0xef);
	TestAck();    //应答检查
	if(E0==1)
	{
		NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
		return;
	}

	*Rdata=Read8Bit(); //读入一个字节
	Ack();           //应答

	NoAck();   //非应答
	I2CStop();    //停止
}

void SetSDAIn(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

  /* Enable GPIOC clock */
  /* Enable GPIOA clock */

  /* Configure PC.06, PC.07, PC.08 and PC.09 as output push-pull */
  GPIO_InitStructure.GPIO_Pin =  I2C_SDA;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void SetSDAOut(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

  /* Enable GPIOC clock */
  /* Enable GPIOA clock */

  /* Configure PC.06, PC.07, PC.08 and PC.09 as output push-pull */
  GPIO_InitStructure.GPIO_Pin =  I2C_SDA;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -