STM32 模拟I2C (STM32F051)

/**
  ******************************************************************************
  * @file      i2c simu.c
  * @brief     simulation function
  * @CPU       STM32F051
  * @compiler  Keil uVision V4.74
  * @author    MetalSeed
  * @copyright WSHHB
  * @version   V1.0.0
  * @date      18-Sept-2014
  * @modifydate20-Sept-2014
  ******************************************************************************
  * @attention
  */

#include "boardAPI.h"
#include "i2cSimu.h"
#include "delay.h"
#include "uart.h"

GPIO_InitTypeDef        GPIO_InitStructure;  

/**
  * @brief  IIC Init
  * @param  A:
  * @retval None
  */
void IIC_Init(void)
{
	RCC_AHBPeriphClockCmd(	RCC_AHBPeriph_GPIOF, ENABLE );
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT ;   //ÍÆÍìÊä³ö
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOF, &GPIO_InitStructure);
	GPIO_SetBits(GPIOF,GPIO_Pin_6|GPIO_Pin_7); 	//PB10,PB11 Êä³ö¸ß
}

/**
  * @brief  Set SDA Pin as Output Mode
  * @retval None
  */
void SDA_OUT()
{
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOF, &GPIO_InitStructure);
}  

/**
  * @brief  Set SDA Pin as Input Mode
  * @retval None
  */
void SDA_IN()
{
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;// !!!
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOF, &GPIO_InitStructure);
} 

/**
  * @brief  read input voltage from SDA pin
  * @retval None
  */
BYTE SDA_READ()
{
  return GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_7);
}

/**
  * @brief  output high form SDA pin
  * @retval None
  */
void IIC_SDA_1()
{
  GPIO_SetBits(GPIOF, GPIO_Pin_7);
}

/**
  * @brief  output low form SDA pin
  * @retval None
  */
void IIC_SDA_0()
{
  GPIO_ResetBits(GPIOF, GPIO_Pin_7);
}

/**
  * @brief  output high form SCL pin
  * @retval None
  */
void IIC_SCL_1()
{
GPIO_SetBits(GPIOF, GPIO_Pin_6);
}

/**
  * @brief  output LOW form SCL pin
  * @retval None
  */
void IIC_SCL_0()
{
GPIO_ResetBits(GPIOF, GPIO_Pin_6);
}

/**
* @brief  Simulate IIC conmunication :Create Start signal
  * @retval None
  */
void IIC_Start(void)
{
	SDA_OUT();     //sda output
	IIC_SDA_1();
	IIC_SCL_1();
	delayus(4);
 	IIC_SDA_0();   //START:when CLK is high,DATA change form high to low
	delayus(4);
	IIC_SCL_0();   //hold scl line, prepare to transmit data
}	  

/**
  * @brief  Simulate IIC conmunication : Create Stop signal
  * @retval None
  */
void IIC_Stop(void)
{
	SDA_OUT();    //sda output mode
	IIC_SCL_0();
	IIC_SDA_0();  //STOP:when CLK is high DATA change form low to high
 	delayus(4);
	IIC_SCL_1();
	IIC_SDA_1();  //indicate transmit over
	delayus(4);
}

/**
* @brief  Simulate IIC conmunication : wait for target device's ACK
* @retval ACK (0) : receive success
* @retval NACK(1) : receive unsuccess
  */
BYTE IIC_Wait_Ack(void)
{
	BYTE ucErrTime = 0;
	SDA_IN();      //set as input mode
	IIC_SDA_1();
  delayus(1);
	IIC_SCL_1();
  delayus(1);
	while(SDA_READ())
	{
		ucErrTime++;
		if(ucErrTime > 250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL_0(); //release scl line
	return 0;
} 

/**
  * @brief  Simulate IIC conmunication : make an ACK
  * @retval None
  */
void IIC_Ack(void)
{
	IIC_SCL_0();
	SDA_OUT();
	IIC_SDA_0();
	delayus(2);
	IIC_SCL_1();
	delayus(2);
	IIC_SCL_0();
}

/**
  * @brief  Simulate IIC conmunication : don't make an ACK
  * @retval None
  */
void IIC_NAck(void)
{
	IIC_SCL_0();
	SDA_OUT();
	IIC_SDA_1();
	delayus(2);
	IIC_SCL_1();
	delayus(2);
	IIC_SCL_0();
}					 				     

/**
  * @brief  Simulate IIC conmunication : Transmit one byte Data
  * @param  txd: data to be transmit
  * @retval None
  */
void IIC_Send_Byte(BYTE txd)
{
  BYTE i;
  SDA_OUT();
  IIC_SCL_0();//push down scl  to start transmit data
  for(i = 0; i < 8; ++i)
  {
    if(txd & 0x80)
    {
      IIC_SDA_1();
    }
    else
    {
      IIC_SDA_0();
    }
    txd <<= 1;
    delayus(2);
    IIC_SCL_1();
    delayus(2);
    IIC_SCL_0();
    delayus(2);
  }
} 	  

//¶Á1¸ö×Ö½Ú£¬ack=1ʱ£¬·¢ËÍACK£¬ack=0£¬·¢ËÍnACK
/**
  * @brief  Simulate IIC conmunication : Receive one byte Data
  * @param  ack: Whether transmit ACK
  * @retval the data have been receive
  */
BYTE IIC_Read_Byte(unsigned char ack)
{
	unsigned char i, res = 0;
	SDA_IN();               //SDA input mode
  for(i = 0; i < 8; ++i )
	{
    IIC_SCL_0();
    delayus(2);
    IIC_SCL_1();
    res <<= 1;
    if(SDA_READ())
    {
      res++;
    }
		delayus(1);
  }
  if (!ack)
  {
    IIC_NAck();//make NACK
  }
  else
  {
    IIC_Ack(); //make ACK
  }
  return res;
}

/*JUST SOME TEST FUNTION DEMO*/
BYTE ReadData()
{
	BYTE temp=0;
  IIC_Start();  

  IIC_Send_Byte(0x80);
	IIC_Wait_Ack(); 

  IIC_Send_Byte(0xf5);
	IIC_Wait_Ack();	    

  IIC_Start();
	IIC_Send_Byte(0XA1);
	IIC_Wait_Ack();	 

  temp=IIC_Read_Byte(0);
  IIC_Stop();
	return temp;
}

void WriteData(BYTE DataToWrite)
{
  IIC_Start();
  IIC_Send_Byte(0x80);
  if( IIC_Wait_Ack() == 0)
  {
     printf("Recieve ACK \n");
  }    

  IIC_Send_Byte(0xf5);
	IIC_Wait_Ack(); 	 										  		   

  IIC_Send_Byte( DataToWrite );
	IIC_Wait_Ack();  		    	   

  IIC_Stop();
	delayms(10);
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-10-24 22:07:38

STM32 模拟I2C (STM32F051)的相关文章

STM32模拟I2C

之前为了测试, 拿最小板做了一个I2C的主发跟主读, 一开始当然是尝试用硬件I2C, 结果弄了很久, 时间紧迫, 只好用了模拟, 结果发现, 哎, 真特么挺好用的, 现在1片儿顶过去5片儿. 硬件I2C, 用库函数的方法如下: void WriteData2OBD(u8 TxLength){      u8 Tx_Idx=0;    I2C_GenerateSTART(I2C2, ENABLE);                  //起始信号      while(!I2C_CheckEven

【转载】GPIO模拟i2c通信

I2C总线的通信过程(见图4-8)主要包含三个主要阶段:起始阶段.数据传输阶段和终止阶段. 1. 起始阶段 在I2C总线不工作的情况下,SDA(数据线)和SCL(时钟线)上的信号均为高电平.如果此时主机需要发起新的通信请求,那么需要首先通过SDA和SCL发出起始标志.当SCL为高电平时,SDA电平从高变低,这一变化表示完成了通信的起始条件. 在起始条件和数据通信之间,通常会有延时要求,具体的指标会在设备厂商的规格说明书中给出. 2. 数据传输阶段 I2C总线的数据通信是以字节(8位)作为基本单位

S5PV210之GPIO模拟I2c时序之pcf8591与at24xx linux3.0.8驱动

目录:一. 说明 二. 驱动程序说明及问题 三. 案例一       四. 案例二 一. 说明 mini210开发板上带了at24c08, 看了linux内核自带的at24.c的驱动程序,编译下载到看发板,读写都行:通过增加一些调试信息,对linux i2c驱动其中的编写方法之一有了一定了解,在我的另外一篇博文有详细说明.但同时对在linux下GPIO模拟i2c产生了兴趣,于是就写这篇博文来记录驱动编写过程中遇到的问题.如果想了解了i2c时序,请google或百度一下. 本篇博文通过misc驱动

STM32F10x_模拟I2C读写_硬件I2C读写

STM32F10x_模拟I2C读写EEPROM STM32F10x_硬件I2C读写EEPROM(标准外设库版本) STM32F10x_硬件I2C主从通信(轮询发送,中断接收)

gpio模拟i2c驱动

前段时间做项目,需要gpio模拟i2c通信,最后参考了一些资料,然后编写了一个程序.现在发出来,以免以后忘记,也为一些需要的朋友提供参考.不喜勿喷哈. /* 说明:该程序是基于atmel公司的sama5d35 MCU 用其中两个GPIO引脚模拟i2c通信. * 其中两个引脚连接到了hd1650上面.然后检测按键扫描的驱动 * */ 该程序可以作为gpio模拟i2c程序的参考.不同的平台,函数实现不同,但是i2c通信的时序和原理是相同的.希望对一些朋友有帮助. 1 #include<linux/i

STM32F207 两路ADC连续转换及GPIO模拟I2C给Camera Sensor初始化参数

1.为了更好的方便调试,串口必须要有的,主要打印一些信息,当前时钟.转换后的电压值和I2C读出的数据. 2.通过GPIO 模拟I2C对镁光的MT9V024进行参数初始化.之前用我以前公司SP0A19芯片,是I2C是8位宽的,而镁光的地址是8位,而数据位是16个字节, 其实不管是8位还是16位,每次发送都是8个字节然后一个应答位,所以只要稍微改下代码即可. 3.实现两路ADC连续转换,两路ADC转换:一路是检测锂电池电压:一路是检测压力传感器,其实都是检测电压,当检测到压力为零,并累计多长时间后进

触摸按键--模拟I2C驱动TS12芯片

TS12芯片驱动 使用模拟I2C驱动TS12完成触摸按键检测功能: #include "stm8s.h" #include "global.h" #include "drv_key.h" uint8_t KeyByte; /******************************************************************************* // Function: I2C_Int // Descripti

GPIO模拟I2C

之前在学习I2C驱动,想了想应该先深刻理解下I2C协议.个人觉得理解I2C协议最好的方法就是实践,而最好的实践方式就是用GPIO来模拟I2C协议进行试验,直观深刻. 先看下I2C时序图: 根据时序图,用两个gpio分别模拟sda和scl即可.在这之前自然需要先对gpio进行输入输出的配置.这里只从写数据角度来描述这一过程.读数据同理即知. 先配置gpio,包括sda.scl.供电gpio等额外功能gpio. gpio_config(GPIO_SDA, GPIO_OUTPUT); gpio_con

模拟I2C协议学习点滴之原理框架

I2C是一种串行总线协议. 目前几种常用的串行总线有UART.SPI和I2C协议.UART协议的总线只有两条,发送(Transmit:TX)和接收(Receive:RX),没有时钟信号,这就要求两位数据的间隔要相同,它传送数据有严格的规定,每个数据以相同的位串形式传送,每个位串由起始位.数据位.奇偶位校验和停止位组成.SPI有三线和四线模式,四条总线分别为SCLK(时钟).MISO(主器件数据输入,从器件数据输出).MOSI(主器件数据输出,从器件数据输入).SS(从器件使能信号),SPI总线由