STM32外设驱动篇——AT24C02(I2C接口)

SOC:STM32F103RCT6

软件平台:STM官方库V3.5.0

开发工具:Keil


1. 摘要

  本文章将给出STM32F103RCT6控制AT24C02的代码。如有疑问和错误,欢迎留言告之。


2.硬件连接

AT24C02使用I2C进行数据访问,板子上使用STM32的I2C控制器2和AT24C02进行连接。

具体来说,PB10作为SCL和AT24C02相连,PB11作为SDL和AT24C02相连。

这里就不给出硬件连接图了,比较简单。


3. AT24C022C访问代码(轮询)

I2C这里使用轮询方法,不是中断,请留意。

首先,给出I2C控制器的初始化代码,和读写代码,一共三个函数,对应三个功能。

注意:这里是使用I2C控制器2。

#include "stm32f10x.h"
#include "stm32f10x_i2c.h"
#include <stdio.h>

void I2C2_Init(I2C_InitTypeDef* I2C_InitStruct)
{
	GPIO_InitTypeDef GPIO_InitStruct; 

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 	
	
	/* 配置IO管脚 */
	GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_10 | GPIO_Pin_11;   	 
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;   	 
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_Init(GPIOB, &GPIO_InitStruct); 
   
   	I2C_Init(I2C2, I2C_InitStruct);
	I2C_Cmd(I2C2, ENABLE);
	
	// 配置NVIC
/*	NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn   ;				//I2C事件中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;	//抢占优先级1 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;			//子优先级2 
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能中断通道
	NVIC_Init(&NVIC_InitStructure);  	  						//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 */

	//I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE); //打开事件中断
}

/* i2c 写一个字节*/
/* Byte Write */
void I2C2_WriteByte(uint8_t DeviceAddress, uint8_t MemoryAddress, uint8_t Data)
{
	while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));   	//等待I2C空闲 

	//start
	I2C_GenerateSTART(I2C2, ENABLE);
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS ); 
	
	//device address
	I2C_Send7bitAddress(I2C2, DeviceAddress, I2C_Direction_Transmitter); //写模式
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS ); 	
	//printf("address over\r\n") ; 

	//memory address
	I2C_SendData(I2C2, MemoryAddress);
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS ); 
			
	//data
   	I2C_SendData(I2C2, Data);
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS ); 	

	//stop
	I2C_GenerateSTOP(I2C2, ENABLE); 
}

/* i2c 读一个字节*/
/* Random Read */
uint8_t I2C2_ReadByte(uint8_t DeviceAddress, uint8_t MemoryAddress)
{
	uint8_t	Data;
	
	while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));   	//等待I2C空闲  
	//start
	I2C_GenerateSTART(I2C2, ENABLE);
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS ); //ev5 

	//device address
	I2C_Send7bitAddress(I2C2, DeviceAddress, I2C_Direction_Transmitter);  //写模式
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS ); 	//ev6 
	 
	//memory address
	I2C_SendData(I2C2,  MemoryAddress);
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS ) ; 
																		  
	//start
	I2C_GenerateSTART(I2C2, ENABLE);
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS ) ; 	

	//device address
	I2C_Send7bitAddress(I2C2, DeviceAddress, I2C_Direction_Receiver); //读模式
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS ) ;
	
	/* 按照manual的图273,先读取数据,关闭ACK应答,最后发出STOP*/   	
	while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS ); 	/* 等待读取事件,再读取数据 */
   	Data = I2C_ReceiveData(I2C2); 
        I2C_AcknowledgeConfig(I2C2, DISABLE); //关闭应答和停止条件产生  
	printf("received\r\n");
	I2C_GenerateSTOP(I2C2, ENABLE); 
	
	I2C_AcknowledgeConfig(I2C2, ENABLE); 

	return Data;
}
 

接着给出相应的AT24C02访问代码

#include "stm32f10x.h"
#include "stm32f10x_i2c.h"
#include "i2c.h"
#include "delay.h"
#include <stdio.h>

/* 从AT24CXX的指定地址开始读出一个字节 */
uint8_t AT24CXX_ReadByte(uint8_t ReadAddr)
{
	return I2C2_ReadByte(0xA0, ReadAddr);
}  

/* 向AT24CXX的指定地址开始写入一个字节 */
void AT24CXX_WriteByte(uint8_t WriteAddr, uint8_t Data)
{
	I2C2_WriteByte(0xA0, WriteAddr, Data);
}

void AT24CXX_test(void)
{
	uint8_t i;
   	I2C_InitTypeDef I2C_InitStructure; 

	I2C_InitStructure.I2C_ClockSpeed 	=  200000;	   //200kHZ
   	I2C_InitStructure.I2C_Mode 			=  I2C_Mode_I2C;
   	I2C_InitStructure.I2C_DutyCycle 	=  I2C_DutyCycle_2;	//根据datasheet,Tlow/Thigh = 2
   	I2C_InitStructure.I2C_OwnAddress1 	=  0xA0; 		
   	I2C_InitStructure.I2C_Ack 		 	=  I2C_Ack_Enable;
   	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	
	I2C2_Init(&I2C_InitStructure);

	for(i = 0; i < 10; i++){	
		AT24CXX_WriteByte(i, 100 + i);
		/* NOTE: 根据datasheet,两次字节写之间必须延迟5ms,也就是stop和start之间的间隔时间*/
		delay_ms(6);  
	}
	printf("Write completed \r\n");

	for(i = 0; i < 10; i++){	
		printf("%d ", AT24CXX_ReadByte(i));
	    delay_ms(6);
	}
	printf("\r\n");
}

注意:两次访问间隔必须大于5ms,这是datasheet规定的。

如果不加延时,第二次写入时候,写入设备地址后,无法接受到ACK,程序陷入死循环。


备注:

2013.11.22 轮询版本程序


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值