硬件实现IIC协议读取EEPROM

摘要:
我也相信TMD。无论如何,我在董事会工作了很长时间,我不知道为什么。Wildfire STM32-MINI始终坚持EV5,无论代码是否首先被项目目录弄脏(板是Wildfire STM32MINI)。串行端口相关代码:bsp_usart。h#ifndef_USART_h#定义__USART_h#include“stm32f10x.h”#include<标准。小时>/***串行端口宏定义。连接到不同串行端口的总线和IO是不同的,

我TMD也是服了,反正我板子搞了半天也不成功我也不知道为什么,野火STM32-MINI,一直卡EV5,不管了 先代码沾上

1

2 工程目录(板子为野火STM32 MINI)

串口相关代码:

bsp_usart.h

#ifndef __USART_H
#define	__USART_H


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

/**
  * 串口宏定义,不同的串口挂载的总线和IO不一样,移植时需要修改这几个宏
	* 1-修改总线时钟的宏,uart1挂载到apb2总线,其他uart挂载到apb1总线
	* 2-修改GPIO的宏
  */

// 串口1-USART1
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd

#define  DEBUG_USART_TX_GPIO_PORT         GPIOA
#define  DEBUG_USART_TX_GPIO_PIN          GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler

void USART_Config(void);

#endif /* __USART_H */

bsp_usart.c

 

#include "./usart/bsp_usart.h"


 /**
  * @brief  USART GPIO 配置,工作参数配置
  * @param  无
  * @retval 无
  */
void USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	// 打开串口GPIO的时钟
	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);

	// 打开串口外设的时钟
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

	// 将USART Tx的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  // 将USART Rx的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);

	// 配置串口的工作参数
	// 配置波特率
	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
	// 配置 针数据字长
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	// 配置停止位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	// 配置校验位
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	// 配置硬件流控制
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	// 配置工作模式,收发一起
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	// 完成串口的初始化配置
	USART_Init(DEBUG_USARTx, &USART_InitStructure);

	// 使能串口
	USART_Cmd(DEBUG_USARTx, ENABLE);
}


///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
		/* 发送一个字节数据到串口 */
		USART_SendData(DEBUG_USARTx, (uint8_t) ch);

		/* 等待发送完毕 */
		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);

		return (ch);
}

///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
		/* 等待串口输入数据 */
		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(DEBUG_USARTx);
}

bsp_i2c_ee.h

#ifndef __I2C_EE_H
#define	__I2C_EE_H


#include "stm32f10x.h"
#include "bsp_usart.h"

#define  EEPROM_ADDR  0xA0


void I2C_EE_Config(void);
void EEPROM_Byte_Write(uint8_t addr,uint8_t data);
void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite);
void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead);
void EEPROM_WaitForWriteEnd(void);


#endif /* __I2C_EE_H */

bsp_i2c_ee.c

#include "bsp_i2c_ee.h"



void I2C_EE_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	I2C_InitTypeDef  I2C_InitStructure;

	// 打开IIC GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

	// 打开IIC 外设的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

	// 将IIC SCL SDA的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);



	// 配置IIC的工作参数
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable  ;//使能应答
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ;//使用7位地址模式
	I2C_InitStructure.I2C_ClockSpeed = 400000; //配置SCL时钟频率
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2 ;
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C ;
	I2C_InitStructure.I2C_OwnAddress1 = 0x5f; //这是STM32 IIC自身设备地址,只要是总线上唯一即可

	I2C_Init(I2C1,&I2C_InitStructure);

	// 使能串口
	I2C_Cmd (I2C1, ENABLE);
}


//向EEPROM写入一个字节

void EEPROM_Byte_Write(uint8_t addr,uint8_t data)
{
	//产生起始信号
	I2C_GenerateSTART(I2C1,ENABLE);

	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);

	//EV5事件被检测到,发送设备地址
	I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);

  while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);

	//EV6事件被检测到,发送要操作的存储单元地址
	I2C_SendData (I2C1,addr);

	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR);

  //EV8事件被检测到,发送要存储的数据
	I2C_SendData (I2C1,data);

	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR);

	//数据传输完成
	I2C_GenerateSTOP(I2C1,ENABLE);

}



//向EEPROM写入多个字节(页写入),每次写入不能超过8个字节

void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite)
{
	//产生起始信号
	I2C_GenerateSTART(I2C1,ENABLE);

	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);

	//EV5事件被检测到,发送设备地址
	I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);

  while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);

	//EV6事件被检测到,发送要操作的存储单元地址
	I2C_SendData (I2C1,addr);

	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR);


	while(numByteToWrite)
	{
		//EV8事件被检测到,发送要存储的数据
		I2C_SendData (I2C1,*data);

		while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR);

		data++;
		numByteToWrite--;

	}
	//数据传输完成
	I2C_GenerateSTOP(I2C1,ENABLE);

}



//从EEPROM读取数据

void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead)
{
	//产生起始信号
	I2C_GenerateSTART(I2C1,ENABLE);

	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);

	//EV5事件被检测到,发送设备地址
	I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);

  while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);

	//EV6事件被检测到,发送要操作的存储单元地址
	I2C_SendData (I2C1,addr);

	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR);


	//第二次起始信号
	//产生起始信号
	I2C_GenerateSTART(I2C1,ENABLE);

	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);

	//EV5事件被检测到,发送设备地址
	I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Receiver);

  while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR);


	while(numByteToRead)
	{
		if(numByteToRead == 1)
		{
			//如果为最后一个字节
			I2C_AcknowledgeConfig (I2C1,DISABLE);
		}

		//EV7事件被检测到	
		while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED ) == ERROR);

		//EV7事件被检测到,即数据寄存器有新的有效数据	
		*data = I2C_ReceiveData(I2C1);

		data++;

		numByteToRead--;

	}


	//数据传输完成
	I2C_GenerateSTOP(I2C1,ENABLE);

	//重新配置ACK使能,以便下次通讯
	I2C_AcknowledgeConfig (I2C1,ENABLE);

}


//等待EEPROM内部时序完成
void EEPROM_WaitForWriteEnd(void)
{

	do
	{
		//产生起始信号
		I2C_GenerateSTART(I2C1,ENABLE);

		while(I2C_GetFlagStatus (I2C1,I2C_FLAG_SB) == RESET);

		//EV5事件被检测到,发送设备地址
		I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
	}
	while(I2C_GetFlagStatus (I2C1,I2C_FLAG_ADDR) == RESET );

	//EEPROM内部时序完成传输完成
	I2C_GenerateSTOP(I2C1,ENABLE);
}

main.c

#include "stm32f10x.h"
#include "./usart/bsp_usart.h"
#include "./i2c/bsp_i2c_ee.h"


uint8_t readData[10]={0};
uint8_t writeData[8]={4,5,6,7,8,9,10,11};
 /**
  * @brief  主函数
  * @param  无
  * @retval 无
  */
int main(void)
{
	 uint8_t i=0;
   USART_Config();
	 printf("这是一个IIC通讯实验
");

	 I2C_EE_Config();
   //向 EEPROM 11地址写入0x55,
   EEPROM_Byte_Write(11,0x55);
	 EEPROM_WaitForWriteEnd();
	 //读出 EEPROM 11地址的内容,保存到readData中(数组的第一个址位)
	 EEPROM_Read(11,readData,1);
	 printf("%x",readData[0]);

		//addr%8 == 0 ,即为地址对齐
	EEPROM_Page_Write(16,writeData,8);

	//等待写入操作完成
	EEPROM_WaitForWriteEnd();

	//读取数据
	EEPROM_Read(16,readData,8);
	for(i=0;i<8;i++)
	{
		printf("%d ",readData[i]);
	}
    while(1);
}
/*********************************************END OF FILE**********************/

免责声明:文章转载自《硬件实现IIC协议读取EEPROM》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇邮件hMailServer +Foxmail 安装使用教程CAS 单点登陆下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

EEPROM类库的使用---断电不丢失的存储芯片

EEPROM(Electrically Erasable Programmable Read-Only Memory),电可擦可编程只读存储器——一种掉电后数据不丢失的存储芯片。 EEPROM可以在不使用文件和文件系统的情况下用来固化一些数据,常见的比如用来保存SSID或者Password,保存用户设置等数据,这样就可以不用每次都通过烧写程序来改变系统运...

STM32 定时器级联

根据参考手册给出的主/ 从定时器的例子 其实就是主定时器产生一个触发信号,让从定时器去接收这个触发信号,通过这个触发信号来让从定时器工作。  下面我们来看看我设置的从定时器 只需要配置 TIMx->SMCR 的TS[2:0] (Trigger selection)   选择是哪一个触发信号来触发从定时器工作 和位 SMS[2:0](Slave...

BLDC 无刷电机FOC驱动 STM32官方培训资料

STM32 PMSM FOC SDK V3.2 培训讲座一http://v.youku.com/v_show/id_XNTM2NjgxMjU2.html?from=s1.8-1-1.2STM32 PMSM FOC SDK V3.2 培训讲座二http://v.youku.com/v_show/id_XNT ... -87.3.6-2.1-1-1-5-0ST...

STM32---喜提点灯

一:编译第一个程序 intmain()  //主函数 { } voidSystemInit()  //在执行主函数前,会被调用。不进行实现。在启动文件中被调用 { } ; Reset handler Reset_Handler PROC EXPORT Reset_Handler...

菜鸟学STM32之跑马灯

微信公众号:小樊Study关注共同学习,问题或建议,请公众号留言!!! 作为一名程序员,在初步学习编程想必都绕不开一个最为基础的入门级示例“Hello World”,那么,在学习单片机时,最基础的入门示例是什么呢?没错,那就是“点亮一盏LED灯”本次将通过一个经典的跑马灯程序,带大家开启 STM32F4 之旅,通过本次的学习,你将了解到 STM32F4 的...

【代码更新】IIC协议建模——读写EEPROM

  案例采用明德扬设计思想完成。IIC协议是非常常用的接口协议,在电子类岗位招聘要求中经常出现它的身影。关于IIC协议这里只做简要介绍,详细信息请自行百度或查阅相关Datasheet,网上资料非常多。该篇博文主要讲如何使用verilog来描述IIC协议,以读写EEPROM为例带领大家了解下明德扬四段式状态机规范和优势,另外还有一些自己在设计过程中总结的经验...