打印
[N32G430]

国民技术N32G430 I2C1 Master的设置

[复制链接]
441|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
呐咯密密|  楼主 | 2024-6-28 11:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
I2C1 Master的设置

1、将PB6 PB7 初始化为I2C1 的 master 模式,然后往AT24C02里写五个数据,然后读出来。

2、在Common里增加i2c.c i2c.h文件

i2c.c

#include "main.h"
#include "i2c.h"
/**
* PB6 PB7   初始化为I2C1  i2c master 模式
* PB10 PB11 初始化为I2C2  i2c slaver 模式
*/

#define I2CT_FLAG_TIMEOUT ((uint32_t)0x1000)
#define I2CT_LONG_TIMEOUT ((uint32_t)(10 * I2CT_FLAG_TIMEOUT))
#define I2C_SLAVE_ADDR    0xA0

static __IO uint32_t I2CTimeout;
static CommCtrl_t Comm_Flag = C_READY;  


static void CommTimeOut_CallBack(ErrCode_t errcode)
{
    max_print("...ErrCode:%d\r\n", errcode);
   
#if (COMM_RECOVER_MODE == MODULE_SELF_RESET)
    IIC_SWReset();
#elif (COMM_RECOVER_MODE == MODULE_RCC_RESET)
    IIC_RCCReset();
#elif (COMM_RECOVER_MODE == SYSTEM_NVIC_RESET)
    SystemNVICReset();
#endif
}


static void Delay(uint32_t nCount)
{
    uint32_t tcnt;
    while (nCount--)
    {
        tcnt = 48000 / 5;
        while (tcnt--){;}
    }
}

static void Delay_us(uint32_t nCount)
{
    uint32_t tcnt;
    while (nCount--)
    {
        tcnt = 48 / 5;
        while (tcnt--){;}
    }
}


MI_BOOL i2c1_init(void)
{
    /** GPIO configuration and clock enable */
    GPIO_InitType GPIO_InitStructure;
    I2C_InitType I2C_InitStructure;
    #if PROCESS_MODE == 1 // interrupt
    NVIC_InitType NVIC_InitStructure;
    #endif

    /** enable peripheral clk*/
    RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_I2C1);
    /* I2C1 Reset */
    RCC_APB1_Peripheral_Reset(RCC_APB1_PERIPH_I2C1);
    RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);

    GPIO_Structure_Initialize(&GPIO_InitStructure);
    GPIO_InitStructure.Pin            = GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_SLOW;
    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_OD;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_I2C1;
    GPIO_InitStructure.GPIO_Pull      = GPIO_PULL_UP;
    GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);

    /** I2C periphral configuration */
    RCC_APB1_Peripheral_Reset(RCC_APB1_PERIPH_I2C1);
    I2C_InitStructure.BusMode     = I2C_BUSMODE_I2C;
    I2C_InitStructure.DutyCycle   = I2C_FMDUTYCYCLE_2;
    I2C_InitStructure.OwnAddr1    = 0xff;
    I2C_InitStructure.AckEnable   = I2C_ACKEN;
    I2C_InitStructure.AddrMode    = I2C_ADDR_MODE_7BIT;
    I2C_InitStructure.ClkSpeed    = 400000;  //400K
    I2C_Initializes(I2C1, &I2C_InitStructure);
   
    I2C_ON(I2C1);
    return MI_TRUE;
}

/**
* i2c1 挂着一个AT24C02
* 我们写入一个字节,读一个字节
* 验证iic读写的函数即可。
*/

MI_BOOL i2c_master_send_bytes_by_addr(MI_U8 slave_addr,MI_U8 reg_addr,MI_U8 *w_data,MI_U16 len)
{
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BUSY))
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_BUSY);
    }

    /** Send START condition */
    I2C_Generate_Start_Enable(I2C1);
    /** Test on EV5 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_MODE_FLAG))  /*EV5*/
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_MODE);
    }

    /** Send slave address for write */
    I2C_7bit_Addr_Send(I2C1, slave_addr, I2C_DIRECTION_SEND);
    /** Test on EV6 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_TXMODE_FLAG))
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_TXMODE);

    }

    I2C_Data_Send(I2C1, reg_addr);
    /** Test on EV8 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDED))
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_SENDED);
    }

     /** While there is data to be written */
    while (len--)
    {
        /** Send the current byte */
        I2C_Data_Send(I2C1, *w_data);
        /** Point to the next byte to be written */
        w_data++;
        /** Test on EV8 and clear it */
        I2CTimeout = I2CT_LONG_TIMEOUT;
        while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDED))
        {
            if ((I2CTimeout--) == 0)
                CommTimeOut_CallBack(MASTER_SENDED);
        }
    }
    /** Send STOP condition */
    I2C_Generate_Stop_Enable(I2C1);
    return MI_TRUE;
}

MI_BOOL i2c_master_receive_bytes_by_addr(MI_U8 slave_addr,MI_U8 reg_addr,MI_U8 *r_data,MI_U16 len)
{
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BUSY))
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_BUSY);
    }

    I2C_PEC_Position_Set(I2C1, I2C_PEC_POS_CURRENT);
    I2C_Acknowledg_Enable(I2C1);
   
    /** Send START condition */
    I2C_Generate_Start_Enable(I2C1);

    /** Test on EV5 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_MODE_FLAG))
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_MODE);
    }

    /** Send slave address for write */
    I2C_7bit_Addr_Send(I2C1, slave_addr, I2C_DIRECTION_SEND);
    /** Test on EV6 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_TXMODE_FLAG))
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_TXMODE);
    }

    I2C_ON(I2C1);
    /** Send the slave's internal address to write to */
    I2C_Data_Send(I2C1, reg_addr);
    /** Test on EV8 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDED))
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_SENDED);
    }
    I2C_Generate_Stop_Enable(I2C1);

    /** Send STRAT condition a second time */
    I2C_Generate_Start_Enable(I2C1);
    /** Test on EV5 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_MODE_FLAG))
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_MODE);
    }

    /** Send slave address for read */
    I2C_7bit_Addr_Send(I2C1, slave_addr, I2C_DIRECTION_RECV);
    /* Test on EV6 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_Flag_Status_Get(I2C1, I2C_FLAG_ADDRF))    //EV6
    {
        if ((I2CTimeout--) == 0)
            CommTimeOut_CallBack(MASTER_RECVD);
    }

    /** While there is data to be read */
    if (len == 1)
    {
        /** Disable Acknowledgement */
        I2C_Acknowledg_Disable(I2C1);
        /** clear ADDR */
        (void)(I2C1->STS1);
        (void)(I2C1->STS2);
        /** Generates START condition to close communication */
        I2C_Generate_Start_Enable(I2C1);
    }
    else
    {
        /** clear ADDR */
        (void)(I2C1->STS1);
        (void)(I2C1->STS2);
    }

    while (len)
    {
        if (len <= 2)
        {
            /** One byte */
            if (len == 1)
            {
                /** Wait until RXNE flag is set */
                I2CTimeout = I2CT_LONG_TIMEOUT;
                while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG))
                {
                    if ((I2CTimeout--) == 0)
                        CommTimeOut_CallBack(MASTER_RECVD);
                }
                /** Read data from DAT */
                *r_data = I2C_Data_Recv(I2C1);
                /** Point to the next location where the byte read will be saved */
                r_data++;
                /** Decrement the read bytes counter */
                len--;
                 /** Generates STOP condition to release SCL/SDA line */
                I2C_Generate_Stop_Enable(I2C1);   
            
            }
            /** 2 Last bytes */
            else
            {   
                /** Wait until RXNE flag is set */
                I2CTimeout = I2CT_LONG_TIMEOUT;
                while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG))
                {
                    if ((I2CTimeout--) == 0)
                        CommTimeOut_CallBack(MASTER_RECVD);
                }
                /** Disable Acknowledgement */
                I2C_Acknowledg_Disable(I2C1);
                              
                /** Read data from DAT */
                *r_data = I2C_Data_Recv(I2C1);
                /** Point to the next location where the byte read will be saved */
                r_data++;
                /** Decrement the read bytes counter */
                len--;
               
                /** Generates START condition to close communication */
                I2C_Generate_Start_Enable(I2C1);
               
                while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG))
                {
                    if ((I2CTimeout--) == 0)
                        CommTimeOut_CallBack(MASTER_RECVD);
                }                                                
                /** Read data from DAT */
                *r_data = I2C_Data_Recv(I2C1);              
                /** Point to the next location where the byte read will be saved */
                r_data++;
                /** Decrement the read bytes counter */
                len--;
               
                /** Generates STOP condition to release SCL/SDA line */
                I2C_Generate_Stop_Enable(I2C1);
            }
        }
        else
        {
            /** Test on EV7 and clear it */
            I2CTimeout = I2CT_LONG_TIMEOUT;
            while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG))
            {
                if ((I2CTimeout--) == 0)
                    CommTimeOut_CallBack(MASTER_RECVD);
            }
            /** Read a byte from the EEPROM */
            *r_data = I2C_Data_Recv(I2C1);
            /** Point to the next location where the byte read will be saved */
            r_data++;
            /** Decrement the read bytes counter */
            len--;
            if (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BYTEF))
            {
                /** Read a byte from the EEPROM */
                *r_data = I2C_Data_Recv(I2C1);
                /** Point to the next location where the byte read will be saved */
                r_data++;
                /** Decrement the read bytes counter */
                len--;
            }
        }
    }

    return MI_TRUE;
}

i2c.h

#ifndef __I2C_H__
#define __I2C_H__
#include "type.h"

#define NON_REENTRANT

typedef enum
{
    FAILED = 0,
    PASSED = !FAILED
} Status;

typedef enum
{
    C_READY = 0,
    C_START_BIT,
    C_STOP_BIT
}CommCtrl_t;

typedef enum
{
    MASTER_OK = 0,
    MASTER_BUSY,
    MASTER_MODE,
    MASTER_TXMODE,
    MASTER_RXMODE,
    MASTER_SENDING,
    MASTER_SENDED,
    MASTER_RECVD,
    MASTER_BYTEF,
    MASTER_BUSERR,
    MASTER_UNKNOW,
    SLAVE_OK = 20,
    SLAVE_BUSY,
    SLAVE_MODE,
    SLAVE_BUSERR,
    SLAVE_UNKNOW,

}ErrCode_t;

#define MODULE_SELF_RESET       1
#define MODULE_RCC_RESET        2
#define SYSTEM_NVIC_RESET       3
#define COMM_RECOVER_MODE       0

MI_BOOL i2c1_init(void);
MI_BOOL i2c_master_send_bytes_by_addr(MI_U8 slave_addr,MI_U8 reg_addr,MI_U8 *w_data,MI_U16 len);
MI_BOOL i2c_master_receive_bytes_by_addr(MI_U8 slave_addr,MI_U8 reg_addr,MI_U8 *r_data,MI_U16 len);

#endif
 MI_U8 w_read[5] = {0x50,0x60,0x70,0xf4,0x68};
        SysTick_Delay_Ms(5000);
        i2c1_init();
        i2c_master_send_bytes_by_addr(0xa0,0x00,w_read,5);
        SysTick_Delay_Us(5000);

        MI_U8 r_data[5] = {0};
        i2c_master_receive_bytes_by_addr(0xa0,0x00,r_data,5);


使用特权

评论回复
沙发
结合国际经验| | 2024-8-31 20:01 | 只看该作者
为了完成你的任务,我们需要在 STM32 上配置 I2C1 作为 Master,并实现与 AT24C02 EEPROM 的读写操作。

使用特权

评论回复
板凳
结合国际经验| | 2024-8-31 20:01 | 只看该作者
需要确保 I2C1_ADDRESS 与 EEPROM 的实际地址一致。

使用特权

评论回复
地板
结合国际经验| | 2024-8-31 20:01 | 只看该作者
目前你使用的是轮询模式进行 I2C 操作。如果系统对延迟较敏感,考虑使用中断模式来提高效率和响应性。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:苏州澜宭自动化科技嵌入式工程师
简介:本人从事磁编码器研发工作,负责开发2500线增量式磁编码器以及17位、23位绝对值式磁编码器,拥有多年嵌入式开发经验,精通STM32、GD32、N32等多种品牌单片机,熟练使用单片机各种外设。

497

主题

3881

帖子

47

粉丝