历史上的今天
今天是:2024年12月22日(星期日)
2021年12月22日 | STM32F429--I2C通信(读写EEPROM,串口返回测试数据)
2021-12-22 来源:eefocus
一、I2C介绍
I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息,SDA数据线和SCL时钟信号线。
主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。
如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;
如果主机要接收从器件的数据,首先由主器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下.主机负责产生定时时钟和终止数据传送。
二、I2C的通信状态
总线空闲—SDA和SCL都为高电平
数据的有效位规定
SCL为高电平期间,数据线SDA上必须保持稳定
只有SCL为低电平期间,数据线SDA才允许变化

I2C的起始和终止信号
SCL线为高电平期间,SDA线由高电平—>低电平,表示起始信号
SCL线为高电平期间,SDA线由低电平—>高电平,表示终止信号

3.I2C字节的传送与应答
每一个字节是8位,先传最高位(MSB),每传一个字节后面必须跟随一个应答位(即一帧有9位)。

三、须知
下面代码用到了串口返回读取的数据信息,此处用到了串口一

用到的库函数


主发送器通讯过程

主接收器

四、程序部分
bsp_i2c_eeprom.h
#ifndef __BSP_I2C_EEPROM_H
#define __BSP_I2C_EEPROM_H
#include "stm32f4xx.h"
#define I2C_OWN_ADDR 0x77 /*主机的八位地址,只要不和从机重复*/
#define I2C_SPEED 400000 /*快速模式最高400khz*/
#define EEPROM_ADDR (0x50<<1) //0xA0,
//引脚定义,移植时修改此处即可,野火的I2C口为PB6和PB7
/*******************************************************/
#define EEPROM_I2C I2C1
#define EEPROM_I2C_CLK RCC_APB1Periph_I2C1
#define EEPROM_SCL_GPIO_PORT GPIOB
#define EEPROM_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB
#define EEPROM_SCL_PIN GPIO_Pin_6
#define EEPROM_SCL_AF GPIO_AF_I2C1
#define EEPROM_SCL_SOURCE GPIO_PinSource6
#define EEPROM_SDA_GPIO_PORT GPIOB
#define EEPROM_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB
#define EEPROM_SDA_PIN GPIO_Pin_7
#define EEPROM_SDA_AF GPIO_AF_I2C1
#define EEPROM_SDA_SOURCE GPIO_PinSource7
/************************************************************/
void EEPROM_GPIO_Config(void);
void EEPROM_I2C_ModeConfig(void);
void EEPROM_Byte_Write(uint8_t* pData,uint8_t addr);
uint8_t EEPROM_Byte_Read(uint8_t addr);
#endif /* __BSP_I2C_EEPROM_H */
bsp_i2c_eeprom.c
#include "./i2c/bsp_i2c_eeprom.h"
void Wait_for_EEPROM(void);
//1.初始化GPIO
void EEPROM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(EEPROM_SCL_GPIO_CLK|EEPROM_SDA_GPIO_CLK,ENABLE);
/* 连接SCL*/
GPIO_PinAFConfig(EEPROM_SCL_GPIO_PORT,EEPROM_SCL_SOURCE,EEPROM_SCL_AF);
/* 连接 SDA*/
GPIO_PinAFConfig(EEPROM_SDA_GPIO_PORT,EEPROM_SDA_SOURCE,EEPROM_SDA_AF);
/* GPIO初始化 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 配置SCL引脚为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = EEPROM_SCL_PIN ;
GPIO_Init(EEPROM_SCL_GPIO_PORT, &GPIO_InitStructure);
/* 配置SDA引脚为复用功能 */
GPIO_InitStructure.GPIO_Pin = EEPROM_SDA_PIN;
GPIO_Init(EEPROM_SDA_GPIO_PORT, &GPIO_InitStructure);
}
//2.初始化I2C模式
void EEPROM_I2C_ModeConfig(void)
{
I2C_InitTypeDef I2C_InitStruct;
/* 使能 I2C时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2 ;
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C ;
I2C_InitStruct.I2C_OwnAddress1 = I2C_OWN_ADDR;
I2C_Init(EEPROM_I2C,&I2C_InitStruct);
I2C_Cmd(EEPROM_I2C,ENABLE);
}
//3.byte write 函数
void EEPROM_Byte_Write(uint8_t* pData,uint8_t addr)
{
I2C_GenerateSTART(EEPROM_I2C,ENABLE);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS )
{
//....
}
I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS )
{
}
I2C_SendData(EEPROM_I2C,addr);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS )
{
}
I2C_SendData(EEPROM_I2C,*pData);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS )
{
}
I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
}
//4.random read
uint8_t EEPROM_Byte_Read(uint8_t addr)
{
uint8_t readTemp;
Wait_for_EEPROM();
I2C_GenerateSTART(EEPROM_I2C,ENABLE);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS )
{
//....
}
I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS )
{
}
I2C_SendData(EEPROM_I2C,addr);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS )
{
}
I2C_GenerateSTART(EEPROM_I2C,ENABLE);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS )
{
//....
}
I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Receiver);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS )
{
}
I2C_AcknowledgeConfig(EEPROM_I2C,DISABLE);
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS )
{
}
readTemp = I2C_ReceiveData(EEPROM_I2C);
I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
return readTemp;
}
//5.等待EEPROM内部写完毕
void Wait_for_EEPROM(void)
{
do
{
I2C_GenerateSTART(EEPROM_I2C,ENABLE);
// while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS )
// {
// //....
// }
I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
}while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_ADDR) == RESET);
//等待ADDR = 1 才执行下面的语句
I2C_ClearFlag(EEPROM_I2C,I2C_FLAG_AF);
I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_BUSY) == SET);
//总线空闲,执行下面的语句
}
bsp_debug_usart.h
#ifndef __DEBUG_USART_H
#define __DEBUG_USART_H
#include "stm32f4xx.h"
#include //引脚定义 /*******************************************************/ #define DEBUG_USART USART1 #define DEBUG_USART_CLK RCC_APB2Periph_USART1 #define DEBUG_USART_BAUDRATE 115200 //串口波特率 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_CLK RCC_AHB1Periph_GPIOA #define DEBUG_USART_RX_PIN GPIO_Pin_10 #define DEBUG_USART_RX_AF GPIO_AF_USART1 #define DEBUG_USART_RX_SOURCE GPIO_PinSource10 #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_CLK RCC_AHB1Periph_GPIOA #define DEBUG_USART_TX_PIN GPIO_Pin_9 #define DEBUG_USART_TX_AF GPIO_AF_USART1 #define DEBUG_USART_TX_SOURCE GPIO_PinSource9 #define DEBUG_USART_IRQHandler USART1_IRQHandler #define DEBUG_USART_IRQ USART1_IRQn /************************************************************/ void Debug_USART_Config(void); void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch); void Usart_SendString( USART_TypeDef * pUSARTx, char *str); void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch); #endif /* __USART1_H */ bsp_debug_usart.c #include "./usart/bsp_debug_usart.h" /** * @brief 配置嵌套向量中断控制器NVIC * @param 无 * @retval 无 */ static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 嵌套向量中断控制器组选择 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
下一篇:STM32看门狗--窗口看门狗
史海拾趣
|
Linux是单体内核,即将图形、驱动及文件系统等功能全在操作系统内核中实现,运行在内核状态和同一地址空间,其优点是减少了进程间通信和状态切换的系统开销,获得较高的运行效率;缺点是内核比较庞大! WinCE是微内核,即在内核中实现基本功能, ...… 查看全部问答> |
|
void vSetMotorTimer(unsigned short uiTime)// uiTime us { RCAP2LH = uiTime; } //重新载入定时数据 void vUpdateMotorTimer(void) { T2LH=RCAP2L ...… 查看全部问答> |
|
有没有人研究过mini2440的BSP,其BSP是如何识别128M/256M等flash的? 因为我使用的是QQ2440,但是我发现最新的mini2440的BSP更新了很多驱动,我想移进去QQ2440使用,但是可惜烧写进去后不能启动。 我觉得想搞好这个bsp必须先知道如何使用其他flash时需要修改的代码,哪位高手知道的,麻烦指导下。… 查看全部问答> |
|
我是初学,最近被此问题困扰了好多天, 打开inputPanel后,改变输入法,inputPanel的高度会改变,此时如何捕获该事件。 我使用C#,开发环境vs 2005,.net CF 2.0。 希望解释能详细些,我是初学。 还有我的 ...… 查看全部问答> |
|
研究了N就,PG128128A资料到底怎么驱动,谁有能提供详细资料 12864及以下的我会,就是不会PG128128A的 邮箱 zoujun224@qq.com… 查看全部问答> |
|
请教大家有没有用过 5V和3.3V接口电压转换芯片,我需要DSP2812外接DS18B20和其他几个5V峰值的转速信号,需要做电平转换,但是不知道使用什么样的接口电压转换芯片,需要方向控制的就不要介绍了,比如:SN74LVC164245。我需要的是自动双向转换电平的 ...… 查看全部问答> |




