1. 程式人生 > >stm32硬體I2C測試例程,親測可用

stm32硬體I2C測試例程,親測可用

        對於stm32的硬體I2C確實有不盡人意的地方。但是還是可以實現的,畢竟使用stm32的硬體I2C確實比使用IO口來模擬簡單的多。下面的程式程式碼是使用stm32F03ZET6的I2C1(PB6,PB7)和AT24C02的EEPROM來測試的。希望對於需要的朋友有幫助。

i2c.c

#include "iic.h"
#include "stm32f10x.h"
#include "usart.h"

u16 timeout=TIMEOUT;
/*i2c的初始化*/
void IIC1_Init()
{

	GPIO_InitTypeDef GPIO_InitStruct;
	I2C_InitTypeDef I2C_InitStruct;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	//GPIO的配置
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_OD;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	//IIC的配置
	
	I2C_InitStruct.I2C_Ack=I2C_Ack_Enable;
	I2C_InitStruct.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;
	I2C_InitStruct.I2C_ClockSpeed=10000;
	I2C_InitStruct.I2C_DutyCycle=I2C_DutyCycle_2;
	I2C_InitStruct.I2C_Mode=I2C_Mode_I2C;
	I2C_InitStruct.I2C_OwnAddress1=0x55;
	I2C_Init(I2C1,&I2C_InitStruct);
	
	I2C_Cmd(I2C1,ENABLE);
	
	
}

/*寫入一個位元組*/
void IIC_WriteByte(u8 addr,u8 data)
{
	I2C_EE_WaitEepromStandbyState();
	I2C_GenerateSTART(I2C1,ENABLE);//傳送起始訊號
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))//檢測	EV5事件
	{
		  if((timeout--)==0)
			printf("EV5 Fail");
	}	timeout=1000;
	
	I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter);//傳送7位EEPROM的硬體地址
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))//檢測EV6事件
	{
		  if((timeout--)==0)
			printf("EV6 Fail");
	}	timeout=1000;
	
	I2C_SendData(I2C1,addr);//傳送操作的記憶體地址
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))//檢測EV8事件
	{
		  if((timeout--)==0)
			printf("EV8 Fail");
	}	timeout=1000;	
	
	I2C_SendData(I2C1,data);//要寫入的資料(一個位元組)
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))//檢測EV8事件
	{
		  if((timeout--)==0)
			printf("EV8 Fail");
	}	timeout=1000;
	
	
	I2C_GenerateSTOP(I2C1,ENABLE);//傳送結束訊號
	
}

/*讀取一個位元組*/
u8 IIC_ReadByte(u8 addr)
{
	u8 readtemp;
	I2C_EE_WaitEepromStandbyState();//等待EEPROM釋放匯流排
	
	I2C_GenerateSTART(I2C1,ENABLE);
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))//5
	{
		  if((timeout--)==0)
			printf("EV5 Fail");
	}	timeout=1000;
	
	I2C_Send7bitAddress(I2C1,0xA1,I2C_Direction_Transmitter);
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))//6
	{
		  if((timeout--)==0)
			printf("EV6 Fail");
	}	timeout=1000;
	
	
	I2C_SendData(I2C1,addr);
  while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS )
  {
 		  if((timeout--)==0)
			printf("EV8 Fail");
	}	timeout=1000;
	
	I2C_GenerateSTART(I2C1,ENABLE);
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))
	{
		  if((timeout--)==0)
			printf("EV5 Fail");
	}	timeout=1000;
	
	I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Receiver);
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
	{
		  if((timeout--)==0)
			printf("EV6 Fail");
	}	timeout=1000;
	
	I2C_AcknowledgeConfig(I2C1,DISABLE);

  /* 檢測 EV7 事件 */
  while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS )
  {
 	  if((timeout--)==0)
			printf("EV7 Fail");
	}	timeout=1000;
  
  /* 讀取接收資料 */
  readtemp = I2C_ReceiveData(I2C1);
   
  /* 停止訊號 */
  I2C_GenerateSTOP(I2C1,ENABLE);
  
  return readtemp;
}


/*等待eeprom釋放匯流排*/
void I2C_EE_WaitEepromStandbyState(void)      
{
  do
  {
    I2C_GenerateSTART(I2C1, ENABLE);
    while(I2C_GetFlagStatus(I2C1,I2C_FLAG_SB)==ERROR);//檢測EV5事件
		I2C_Send7bitAddress(I2C1,0xA1,I2C_Direction_Transmitter);
  }while(I2C_GetFlagStatus(I2C1,I2C_FLAG_ADDR)==ERROR);//
    I2C_ClearFlag(I2C1, I2C_FLAG_AF);//清楚標誌位
    I2C_GenerateSTOP(I2C1, ENABLE); //結束訊號
}

/*	向eeprom中寫入n個數據*/
void I2C_WriteNumData(u8 addr,u8 *str, u8 numToWrite)
{
	if((addr+numToWrite)>255)//避免寫入的資料超過總的記憶體
	{
		printf("refuse to write\n");
		printf("please enter less than %d char\n",(255-addr));
	}
	else
	{
	 printf("allow to write\n");
	 while(numToWrite)
	 {
		 IIC_WriteByte(addr,*str);
		 addr++;
		 str++;
		 numToWrite--;
	 }
	 printf("write success\n");
 }
}

void I2C_ReadNumData(u8 addr,u8 *str,u8 numToRead)
{
	while(numToRead)
	{
		*str=IIC_ReadByte(addr);
		addr++;
		str++;
		numToRead--;
	}
	
}

usart.c

#include "usart.h"
#include "stm32f10x.h"


void USART1_Init()
{
	
	GPIO_InitTypeDef  GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	NVIC_InitTypeDef  NVIC_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	USART_InitStruct.USART_BaudRate=115200;
	USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
	USART_InitStruct.USART_Parity=USART_Parity_No;
	USART_InitStruct.USART_StopBits=USART_StopBits_1;
	USART_InitStruct.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&USART_InitStruct);	
	USART_Cmd(USART1,ENABLE);
}



void USART1_SendByte(u8 data)
{
	USART_SendData(USART1,data);
	while(!USART_GetFlagStatus(USART1,USART_FLAG_TXE));	
}


void USART1_SendStr(u8 *str)
{
	unsigned int i=0;
	for(i=0;*str!='\0';i++)
	{
		USART1_SendByte(*str);
		str++;
	}
	while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));
}
	
int fputc(int ch, FILE *f)
{
		/* 傳送一個位元組資料到串列埠 */
		USART_SendData(USART1, (uint8_t) ch);
		
		/* 等待發送完畢 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);		
	
		return (ch);
}
	

main.c

#include "stm32f10x.h"
#include "usart.h"
#include "iic.h"
#include <stdio.h>

int main()
{
   u8 a[10]={9,8,7,6,5,4,3,2,1,0};
   u8 b[10]={0};
   u8 i=0;
   USART1_Init();
   IIC1_Init();
  	I2C_WriteNumData(125,a,10);
	
	I2C_ReadNumData(125,b,10);
	for(i=0;i<10;i++)
	{
		printf("%d\t",b[i]);
	}
   
}