历史上的今天
返回首页

历史上的今天

今天是:2024年08月29日(星期四)

正在发生

2019年08月29日 | STM32F429 >> 12. I²C 通讯(Code)

2019-08-29 来源:eefocus

硬件I²C

在此我们使用硬件I²C 通讯,即使用I²C 外设帮助我们控制数据的发送和时钟的规律跳变。

若是使用模拟I²C 即是51 风格的编程,用程序手动控制两根总线的数据和时钟变化。


编程指南

初始化I²C GPIO引脚;

初始化I²C;

根据事件相应顺序编写相应的读/写操作程序;

编写页写入程序;(非必要)

编写缓冲区buffer 写入程序。(非必要)

bsp_i2c.h

/**

  ******************************************************************************

  * @file    bsp_i2c.h

  * @author  Waao

  * @version V1.0.0

  * @date    15-Jan-2019

  * @brief   This file contains some board support package's functions for the configuration of the I2C.

  *            

  ******************************************************************************

  * @attention

  *

  * None

*

  ******************************************************************************

  */

#ifndef _BSP_I2C_H_

#define _BSP_I2C_H_


#include

#include

#include

#include



//=========================== I2C ==================================

#define I2C_SCL_GPIO_PORT       GPIOB

#define I2C_SCL_GPIO_PIN        GPIO_Pin_6

#define I2C_SCL_GPIO_PINSOURCE  GPIO_PinSource6

#define I2C_SCL_GPIO_AF         GPIO_AF_I2C1

#define I2C_SCL_GPIO_CLK        RCC_AHB1Periph_GPIOB //AHB1


#define I2C_SDA_GPIO_PORT       GPIOB

#define I2C_SDA_GPIO_PIN        GPIO_Pin_7

#define I2C_SDA_GPIO_PINSOURCE  GPIO_PinSource7

#define I2C_SDA_GPIO_AF         GPIO_AF_I2C1

#define I2C_SDA_GPIO_CLK        RCC_AHB1Periph_GPIOB //AHB1


#define I2C_                    I2C1

#define I2C_CLK                 RCC_APB1Periph_I2C1 //APB1

#define I2C_SPEED               400000

#define I2C_OWN_ADDRESS         0X01 /*This address just need to be differenent with the address of 

                                       the device which communicated with the master.*/


//========================== EEPROM ==================================

#define EEPROM_SCL_GPIO_PORT    GPIOB

#define EEPROM_SCL_GPIO_PIN     GPIO_Pin_6


#define EEPROM_SDA_GPIO_PORT    GPIOB

#define EEPROM_SDA_GPIO_PIN     GPIO_Pin_7


#define EEPROM_W_ADDRESS        0XA0  

#define EEPROM_R_ADDRESS        0XA1


#define TIMEOUT                 (uint32_t)(0X1000)

#define LONG_TIMEOUT            (uint32_t)(10*TIMEOUT)

#define I2C_PageSize            8


void I2C_FINAL_Config(void);

void I2C_EE_WaitEepromStandByState(void);

uint32_t I2C_TRANSMIT_Byte(u8 WriteAddr, u8* data);

uint8_t I2C_EE_PageWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint8_t NumByteToWrite);

void I2C_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite);

uint32_t I2C_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead);



#endif



bsp_i2c.c

/**

  ******************************************************************************

  * @file    bsp_i2c.c

  * @author  Waao

  * @version V1.0.0

  * @date    15-Jan-2019

  * @brief   This file contains some board support package's functions for the configuration of the I2C.

  *            

  ******************************************************************************

  * @attention

  *

  * None

*

  ******************************************************************************

  */

#include



uint32_t timeout;



/**

  * @brief  Configure the I2C_GPIO

  * @param  None

  * @retval None

  */

void I2C_GPIO_Config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(I2C_SCL_GPIO_CLK, ENABLE);

RCC_AHB1PeriphClockCmd(I2C_SDA_GPIO_CLK, ENABLE);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;

GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN;

GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN;

GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);

GPIO_PinAFConfig(I2C_SCL_GPIO_PORT, I2C_SCL_GPIO_PINSOURCE, I2C_SCL_GPIO_AF);

GPIO_InitStructure.GPIO_Pin = I2C_SDA_GPIO_PIN;

GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure);

GPIO_PinAFConfig(I2C_SDA_GPIO_PORT, I2C_SDA_GPIO_PINSOURCE, I2C_SDA_GPIO_AF);

}



/**

  * @brief  Configure the I2C

  * @param  None

  * @retval None

  */

void I2C_Config(void)

{

I2C_InitTypeDef I2C_InitStructure;

RCC_APB1PeriphClockCmd(I2C_CLK, ENABLE);

I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_InitStructure.I2C_OwnAddress1 = I2C_OWN_ADDRESS;

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_Init(I2C_, &I2C_InitStructure);

I2C_Cmd(I2C_, ENABLE);

}



/**

  * @brief  Configure the I2C and I2C_GPIO

  * @param  None

  * @retval None

  */

void I2C_FINAL_Config(void)

{

I2C_GPIO_Config();

I2C_Config();

}



/**

* @brief  Error prompt function: When the program meet a error, this function will tell you the error code.

  * @param  None

* @retval None

  */

uint32_t TIME_OUT_CallBack(u8 STATE)

{

printf("The program has error, the error code is %dn", STATE);

return 0;

}



/**

  * @brief  Waiting the EEPROM to be ready.

  * @param  None

  * @retval None

  */

void I2C_EE_WaitEepromStandByState(void)

{

uint16_t SR1_tmp = 0;

do

{

I2C_GenerateSTART(I2C_, ENABLE);

SR1_tmp = I2C_ReadRegister(I2C_, I2C_Register_SR1);

I2C_Send7bitAddress(I2C_, EEPROM_W_ADDRESS, I2C_Direction_Transmitter);

}

while(!(I2C_ReadRegister(I2C_, I2C_Register_SR1) & 0x0002));

I2C_ClearFlag(I2C_, I2C_FLAG_AF);

I2C_GenerateSTOP(I2C_, ENABLE);

}



/**

  * @brief  Transmit a Byte to EEPROM through the I2C peripherals.

  * @param  data: The data you want to transmit.

  * @retval None

  */

uint32_t I2C_TRANSMIT_Byte(u8 WriteAddr, u8* data)

{

I2C_GenerateSTART(I2C_, ENABLE);

timeout = TIMEOUT;

while(!I2C_CheckEvent(I2C_, I2C_EVENT_MASTER_MODE_SELECT)) //EV5

{

timeout--;

if(timeout == 0)

return TIME_OUT_CallBack(0);

}

//Transmit the address which the EEPROM has.

I2C_Send7bitAddress(I2C_, EEPROM_W_ADDRESS, I2C_Direction_Transmitter);

timeout = TIMEOUT;

while(!I2C_CheckEvent(I2C_, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //EV6_TRANSMITTER

{

timeout--;

if(timeout == 0)

return TIME_OUT_CallBack(1);

}

//Transmit the internal address with the ROM of the EEPROM

I2C_SendData(I2C_, WriteAddr);

timeout = TIMEOUT;

while(!I2C_CheckEvent(I2C_, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) //EV8_TRANSMITTING

{

timeout--;

if(timeout == 0)

return TIME_OUT_CallBack(2);

}

//Transmit the real data

I2C_SendData(I2C_, *data);

timeout = TIMEOUT;

while(!I2C_CheckEvent(I2C_, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) //EV8_TRANSMITTING

{

timeout--;

if(timeout == 0)

return TIME_OUT_CallBack(3);

}

I2C_GenerateSTOP(I2C_, ENABLE);

printf("Transmit successfully!"); 

return 1;

}



/**

  * @brief  Transmit a page of data to EEPROM through the I2C 

  * @param  pBuffer: The pointer of the buffer.

* WriteAddr: Write address.

* NumByteToWrite: The number of bytes what we write.

  * @retval None

  */

uint8_t I2C_EE_PageWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint8_t NumByteToWrite)

{

timeout = LONG_TIMEOUT;

//Check whether the I2C bus is busy or not

while(I2C_GetFlagStatus(I2C_, I2C_FLAG_BUSY))

{

timeout--;

if(timeout-- == 0)

return TIME_OUT_CallBack(8);

}

I2C_GenerateSTART(I2C_, ENABLE);

timeout = TIMEOUT;

while(!I2C_CheckEvent(I2C_, I2C_EVENT_MASTER_MODE_SELECT)) //EV5

{

timeout--;

if(timeout == 0)

return TIME_OUT_CallBack(9);

}

I2C_Send7bitAddress(I2C_, EEPROM_W_ADDRESS, I2C_Direction_Transmitter);

timeout = TIMEOUT;

while(!(I2C_CheckEvent(I2C_, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))) //EV6_TRANSMISTTING

{

timeout--;

if(timeout == 0)

return TIME_OUT_CallBack(10);

}

I2C_SendData(I2C_, WriteAddr);

timeout = TIMEOUT;

while(!(I2C_CheckEvent(I2C_, I2C_EVENT_MASTER_BYTE_TRANSMITTED))) //EV8_2

{

timeout--;

if(timeout == 0)

return TIME_OUT_CallBack(11);

}

for(;NumByteToWrite>0;NumByteToWrite--)

{

I2C_SendData(I2C_, *pBuffer);

pBuffer++;

timeout = TIMEOUT;

while(!(I2C_CheckEvent(I2C_, I2C_EVENT_MASTER_BYTE_TRANSMITTED))) //EV8_2

{

timeout--;

if(timeout == 0)

return TIME_OUT_CallBack(12);

}

}

I2C_GenerateSTOP(I2C_, ENABLE);

return 1;

}



/**

  * @brief  Transmit the data to EEPROM from the buffer

  * @param  pBuffer: The pointer of the buffer.

* WriteAddr: Write address.

* NumByteToWrite: The number of bytes what we write.

  * @retval None

  */

void I2C_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)

{

u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

//One page can full with 8 bytes data utmostly

Addr = WriteAddr % I2C_PageSize;

count = I2C_PageSize - Addr;

NumOfPage = NumByteToWrite / I2C_PageSize;

NumOfSingle = NumByteToWrite % I2C_PageSize;

//We can write the data directly to a new page

if(Addr == 0)

{

//The data can't make full of a page

if(NumOfPage == 0)

{

I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);

I2C_EE_WaitEepromStandByState();

}

else

{

//We should make full of the whole page one by one

while(NumOfPage--)

{

I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);

I2C_EE_WaitEepromStandByState();

推荐阅读

史海拾趣

问答坊 | AI 解惑

电感设计软件

电感设计软件,从别处下载的.…

查看全部问答>

一篇关于SDRAM不错的文章

一篇关于SDRAM不错的文章…

查看全部问答>

紧急求助:DM9000网卡程序异常?

我在2440上移植了DM9000A的网卡,系统运行后能够被PING通。可是一运行IE就报如下错误: Data Abort: Thread=97d9aab4 Proc=81d96340 \'device.exe\' AKY=ffffffff PC=02b52178(dm9isa.dll+0x00002178) RA=02b52174(dm9isa.dll+0x00002174) BVA=06 ...…

查看全部问答>

高分! 在51里的串口接收中如何加入超时处理?

我现在需要用到2051接收来自PC的数据(长度不定,但长度信息是在接收的第一个字节里),打算用方式1,定时器2,串口超时了就表示接收已经完成,现在问题是:如何实现串口的超时处理? 是用另外一个定时器?还是在等待RI的过程中DJNZ某数以实现计时 ...…

查看全部问答>

arm-linux平台上摄像头 quick capture interface的中断问题

我需要在pxa271平台上通过quick capture interface来获取摄像头图像,程序是从别的操作系统移植过来的,所以CIF寄存器初始化设置的逻辑应该没有问题,现在的问题是只要我设置了Start of Frame的中断,即 CICR0置位 ~(CICR0_SOFM), 再enable CIF接 ...…

查看全部问答>

怎么设置IP呀 ?

我是菜鸟, 我想知道怎么在WinCE里面设置IP. 察了半天都说修改注册表. 可我连注册表都打不开呀. 我是用 VS2003做得开发.我想在程序里面进行修改. 高手能否提供一个修改注册表得函数, 或者API之类得, 感激不尽啊!!!!…

查看全部问答>

用8962的GPIO采集单总线数据不成功

  源例程,寻求帮助!!!谢谢     GPIO管脚能否配置采样速率? [ 本帖最后由 bjmonsoon 于 2011-1-13 19:35 编辑 ]…

查看全部问答>

关于PB5.0查看函数源码的问题

       我在PB5.0下要修改代码,但是有的函数在其他文件里(例如在根目录下),我想看一下某个函数的实现体,我在函数上点击右键选择Go To Definition of \"函数名\", 但是出现对话框说要去project中的setting中设置, 我 ...…

查看全部问答>