STM32F1 I2C(IIC)最简单的轮询 读写EEPROM 库函数3.5

lgh1230306 2017-03-16 09:43:26
这几天刚开始搞STM32F103ZET6 的I2C,看完数据手册和一些视频教程(有原子的的和刘凯老师的),最后发现向我这种C都不怎么样的人来说抄袭他们的源代码就有点困难了,只能自己边参考边自己敲,所以直接就用51的思维做了个最简单的读写E2PROM程序,
第一天, 参考别人的敲了1个多小时, 开始仿真,发现再怎么样都调试不通(变量没有值),而且还容易死,然后开始各种找原因,
第二天 ,已经渐渐放弃了库函数操作,开始用寄存器吧,操作了一天,还是不成功(操作寄存器非常有好处,就是可以把所有库函数的意思都能搞明白是怎么回事),寄存器操作收获非常大,然后
第三天 ,又回归库函数操作,就在第一天的源代码上面加上串口打印,“坚决”不在线仿真,后来惊奇的串口打印出来了,有数据了。
后来分析失败的原因:
第一:在线仿真肯定是得不到数据的,首先我一步一步执行,I2C的读写时序要求非常高,超过时间就自动死,只能重新上电解决
第二:第一次写入数据后,想在写入的话,一定要加延时(也可以用定时器-中断,SYSTICK来解决这个延时时间),否则不成功,注意:不能在写入函数里面延时,而是在停止信号发生后才延时的哦,因为STM32自身配置的时钟非常准,发送期间根本不需要咱们去参与其中的;咱们刚写入的数据其实是写入到了E2PROM的缓冲区,还没等到它从缓冲区一个一个移位到具体存储空间时,咱们读或者写就会出错的,所以一定得 “延时”!!!


源代码贴上来,直用标准库例程,main.c的代码直接用下面的复制粘贴就可以了

/**
******************************************************************************
* @file Project/STM32F10x_StdPeriph_Template/main.c
* @author MCD Application Team
* @version V3.5.0
* @date 08-April-2011
* @brief Main program body
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE 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 FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#define STM32_CPU_I2C_OWNADR 0xB0
#define E2PROM_ADDR 0xA0

/******************************************************************************************************************************************************************/
void RCC_COF()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO|RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

}
void USART1_GPIO_init()
{


GPIO_InitTypeDef USARTx_GPIO_InitStruct;

USART_InitTypeDef USARTx_InitStruct;

USARTx_GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
USARTx_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 ;
USARTx_GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &USARTx_GPIO_InitStruct);

USARTx_GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
USARTx_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 ;
USARTx_GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &USARTx_GPIO_InitStruct);


USARTx_InitStruct.USART_BaudRate = 9600;
USARTx_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USARTx_InitStruct.USART_Mode = USART_Mode_Tx |USART_Mode_Rx ;
USARTx_InitStruct.USART_Parity = USART_Parity_No;
USARTx_InitStruct.USART_StopBits = USART_StopBits_1;
USARTx_InitStruct.USART_WordLength = USART_WordLength_8b;

USART_Init(USART1, &USARTx_InitStruct);

USART_Cmd(USART1, ENABLE);

}


/**************************************************************************************************************************************************/
void I2C2_GPIO_INIT()
{
I2C_InitTypeDef I2C2_InitStruct;
GPIO_InitTypeDef I2C2_GPIO_InitStruct;

I2C2_GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD ;
I2C2_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 |GPIO_Pin_11 ;
I2C2_GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init( GPIOB, &I2C2_GPIO_InitStruct);

I2C2_InitStruct.I2C_Ack = I2C_Ack_Enable ;
I2C2_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ;
I2C2_InitStruct.I2C_ClockSpeed = 200000;
I2C2_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2 ;
I2C2_InitStruct.I2C_Mode = I2C_Mode_I2C ;
I2C2_InitStruct.I2C_OwnAddress1 = STM32_CPU_I2C_OWNADR ;
I2C_Init( I2C2, &I2C2_InitStruct);
I2C_Cmd( I2C2, ENABLE);

}


void I2C2_SENDDATA_24Cxx(u8 I2C2_SlaveAddress,uint8_t I2C2_Data_ADDR,uint8_t I2C2_Data)
{

I2C_GenerateSTART(I2C2, ENABLE);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));

I2C_Send7bitAddress( I2C2, I2C2_SlaveAddress , I2C_Direction_Transmitter);
while(!I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ));

I2C_SendData( I2C2, I2C2_Data_ADDR );
while(!I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData( I2C2, I2C2_Data );
while(!I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

I2C_GenerateSTOP(I2C2, ENABLE);

}




uint8_t I2C2_RECIVEDATA24Cxx(u8 I2C2_SlaveAddress,uint8_t I2C2_Data_ADDR )
{
I2C_AcknowledgeConfig( I2C2, ENABLE);
I2C_GenerateSTART(I2C2, ENABLE);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)){;}

I2C_Send7bitAddress( I2C2, I2C2_SlaveAddress , I2C_Direction_Transmitter);
while(!I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED )){;}

I2C_SendData( I2C2, I2C2_Data_ADDR );

I2C_GenerateSTART(I2C2, ENABLE);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)){;}

I2C_Send7bitAddress( I2C2,I2C2_SlaveAddress , I2C_Direction_Receiver );
while(!I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED )){;}

I2C_AcknowledgeConfig( I2C2, DISABLE);
I2C_GenerateSTOP( I2C2, ENABLE);
while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED)){;}

return I2C_ReceiveData(I2C2);

}

void I2C_delay(unsigned int I2C_time)
{
while(I2C_time -- );
}


int main()
{
uint8_t E2PROM_data;

RCC_COF();
I2C2_GPIO_INIT();
USART1_GPIO_init();

USART_SendData(USART1,0xFF);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
USART_ClearFlag(USART1, USART_FLAG_TC);

I2C_delay(50000);

I2C2_SENDDATA_24Cxx(0xA0,0x00,0x66); //写入数据
I2C_delay(50000); //切记:一定得延时
I2C2_SENDDATA_24Cxx(0xA0,0x01,0x77);
I2C_delay(50000);
I2C2_SENDDATA_24Cxx(0xA0,0x02,0x88);
I2C_delay(50000);
I2C2_SENDDATA_24Cxx(0xA0,0x03,0x99);
I2C_delay(50000);
I2C2_SENDDATA_24Cxx(0xA0,0xFF,0xAA);
I2C_delay(50000);

E2PROM_data = I2C2_RECIVEDATA24Cxx(E2PROM_ADDR,0x00); //读取数据

USART_SendData(USART1, E2PROM_data);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
USART_ClearFlag(USART1, USART_FLAG_TC);
I2C_delay(50000); //延时
E2PROM_data = I2C2_RECIVEDATA24Cxx(E2PROM_ADDR,0x01);

USART_SendData(USART1, E2PROM_data);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
USART_ClearFlag(USART1, USART_FLAG_TC);
I2C_delay(50000);
E2PROM_data = I2C2_RECIVEDATA24Cxx(E2PROM_ADDR,0x02);

USART_SendData(USART1, E2PROM_data);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
USART_ClearFlag(USART1, USART_FLAG_TC);
I2C_delay(50000);
E2PROM_data = I2C2_RECIVEDATA24Cxx(E2PROM_ADDR,0x03);

USART_SendData(USART1, E2PROM_data);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
USART_ClearFlag(USART1, USART_FLAG_TC);
I2C_delay(50000);
E2PROM_data = I2C2_RECIVEDATA24Cxx(E2PROM_ADDR,0xFF);

USART_SendData(USART1, E2PROM_data);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
USART_ClearFlag(USART1, USART_FLAG_TC);

I2C_delay(50000);

while(1)
{

}
}


...全文
1704 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
MULTISENSOR 2017-07-18
  • 打赏
  • 举报
回复
硬件i2c是最鸡肋的,因为一致性跟软件模拟不在一个档次上。 注意一个8个字节,超过8个会覆盖,要手动写另外的一页。 每一页之间写要有几ms间隔,不然写失败。 读,没问题,一次可以将全部256字节读出来。
lgh1230306 2017-03-16
  • 打赏
  • 举报
回复
不知道,怎么得,发帖跟大家分享下,竟然扣了我40分,好无语

6,125

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 硬件设计
社区管理员
  • 硬件设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧