2003|3

36

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

HC32F4A0-I2C应用 [复制链接]

 

HC32F4A0-Keil环境搭建与点灯 - 国产芯片交流 - 电子工程世界-论坛 (eeworld.com.cn)

HC32F4A0-串口中断接收与中断发送 - 国产芯片交流 - 电子工程世界-论坛 (eeworld.com.cn)

上篇讲了串口及其中断的使用,本篇主要是使用芯片内部I2C控制器对TCA9539这个IO扩展芯片进行控制,使LED点亮。也方便下篇点亮LCD液晶和触摸屏做准备,液晶屏的复位管脚和触摸的中断管脚使用了TCA9539扩展出来的IO。

以下是板载TCA9539的硬件原理图和TCA9539地址确认图:

 

从上图可知,TCA9539的A0、A1管脚接地,TCA9539的第3至第7位是固定值,第0位位读写控制位,只有第1、2位可有硬件设置,由此可知TCA9539的从机地址位0x74。且TCA9539在一条I2C总线上最多只能由4片。

以下是HC32F4A0的时序图:

 从该时序图中可知,通过开始条件、地址传送、数据传送、停止条件这几个步骤,即可完成一次正常通信,TCA9539的驱动代码也是严格按照这个顺序进行的。以下是TCA9539的读写时序图;对比代码和时序图,可以帮我们更好的理解HC32F4A0的I2C的使用。

以下是I2C的配置代码:

#define TCA9539_I2C_FCG_ENABLE()		FCG_Fcg1PeriphClockCmd( FCG1_PERIPH_I2C1, ENABLE )

#define TCA9539_I2C_SCL_PIN				GPIO_PIN_03
#define TCA9539_I2C_SCL_PORT			GPIO_PORT_D
#define TCA9539_I2C_SDA_PIN				GPIO_PIN_10
#define TCA9539_I2C_SDA_PORT			GPIO_PORT_F
#define TCA9539_INT_PIN					GPIO_PIN_01
#define TCA9539_INT_PORT				GPIO_PORT_I
#define TCA9539_RST_PIN					GPIO_PIN_13
#define TCA9539_RST_PORT				GPIO_PORT_C

/**************************************************************
  * [url=home.php?mod=space&uid=32621]@name[/url] bsp_TCA9539_Init
  * [url=home.php?mod=space&uid=159083]@brief[/url] * @param   None
  * @retval
  * [url=home.php?mod=space&uid=1315547]@author[/url] Zachary
  * [url=home.php?mod=space&uid=34591]@data[/url] 2023-02-19
 **************************************************************/
void bsp_TCA9539_Init( void )
{
    float32_t fErr;
    int32_t i32Ret = LL_ERR;
    stc_gpio_init_t GPIO_InitStruct = { 0 };
    stc_i2c_init_t I2C_InitStruct = { 0 };

    LL_PERIPH_WE( LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU );

	GPIO_ResetPins( TCA9539_RST_PORT, TCA9539_RST_PIN );
    GPIO_StructInit( &GPIO_InitStruct );
    GPIO_InitStruct.u16PinDir = PIN_DIR_OUT;				/* --方向 输入或输出--- */
    GPIO_InitStruct.u16PinOutputType = PIN_OUT_TYPE_NMOS;	/* --正常CMOS电平输出或NMOS开漏输出--- */
    GPIO_Init( TCA9539_RST_PORT, TCA9539_RST_PIN, &GPIO_InitStruct );
    delay_ms( 5 );
    GPIO_SetPins( TCA9539_RST_PORT, TCA9539_RST_PIN );

    GPIO_StructInit( &GPIO_InitStruct );
    GPIO_Init( TCA9539_I2C_SCL_PORT, TCA9539_I2C_SCL_PIN, &GPIO_InitStruct );
    GPIO_Init( TCA9539_I2C_SDA_PORT, TCA9539_I2C_SDA_PIN, &GPIO_InitStruct );

    GPIO_SetFunc( TCA9539_I2C_SCL_PORT, TCA9539_I2C_SCL_PIN, GPIO_FUNC_49 );
    GPIO_SetFunc( TCA9539_I2C_SDA_PORT, TCA9539_I2C_SDA_PIN, GPIO_FUNC_48 );

    TCA9539_I2C_FCG_ENABLE();

    I2C_InitStruct.u32Baudrate = 100000UL;
    I2C_InitStruct.u32ClockDiv = I2C_CLK_DIV16;
    I2C_InitStruct.u32SclTime = 0UL;
    for ( uint8_t i = 0U; i < 5U; i++ )
    {
        i32Ret = I2C_Init( TCA9539_I2Cx, &I2C_InitStruct, &fErr );
        if ( LL_OK != i32Ret )
        {
            I2C_InitStruct.u32ClockDiv--;
        }
        else
        {
            break;
        }
    }

    if ( LL_OK == i32Ret )
    {
        I2C_BusWaitCmd( TCA9539_I2Cx, ENABLE );
    }

    I2C_Cmd( TCA9539_I2Cx, ENABLE );

    LL_PERIPH_WP( LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU );
}

 

以下是使用I2C读写TCA9539的代码,根据代码联系上述读写时序图,可以清楚的理解该外设的使用,代码均有注释,可以看出是一步步按照时序图走的。

/**************************************************************
  * @Name    TCA9539_I2C_Write
  * @brief
  * @param   u16DevAddr: [输入/出]
**			 pu8Reg: [输入/出]
**			 u8RegLen: [输入/出]
**			 pu8Buf: [输入/出]
**			 u32Len: [输入/出]
  * @retval
  * @author  Zachary
  * @Data    2023-02-19
 **************************************************************/
void TCA9539_I2C_Write( uint16_t u16DevAddr, const uint8_t *pu8Reg, uint8_t u8RegLen, const uint8_t *pu8Buf, uint32_t u32Len )
{
    int32_t i32Ret;

    I2C_SWResetCmd( TCA9539_I2Cx, ENABLE );
    I2C_SWResetCmd( TCA9539_I2Cx, DISABLE );
    i32Ret = I2C_Start( TCA9539_I2Cx, I2C_TIMEOUT );                                    /* ---起始信号--- */
    if ( LL_OK == i32Ret )
    {
        i32Ret = I2C_TransAddr( TCA9539_I2Cx, u16DevAddr, I2C_DIR_TX, I2C_TIMEOUT );    /* ---7位从机地址传送+传输方向--- */

        if ( LL_OK == i32Ret )
        {
            i32Ret = I2C_TransData( TCA9539_I2Cx, pu8Reg, u8RegLen, I2C_TIMEOUT );      /* ---TCA9539寄存器地址传送--- */
            if ( LL_OK == i32Ret )
            {
                i32Ret = I2C_TransData( TCA9539_I2Cx, pu8Buf, u32Len, I2C_TIMEOUT );    /* ---数据传送--- */
            }
        }
    }
    I2C_Stop( TCA9539_I2Cx, I2C_TIMEOUT );
}
/**************************************************************
  * @Name    TCA9539_I2C_Read
  * @brief
  * @param   u16DevAddr: [输入/出]
**			 pu8Reg: [输入/出]
**			 u8RegLen: [输入/出]
**			 pu8Buf: [输入/出]
**			 u32Len: [输入/出]
  * @retval
  * @author  Zachary
  * @Data    2023-02-19
 **************************************************************/
void TCA9539_I2C_Read( uint16_t u16DevAddr, const uint8_t *pu8Reg, uint8_t u8RegLen, uint8_t *pu8Buf, uint32_t u32Len )
{
    int32_t i32Ret;
    I2C_SWResetCmd( TCA9539_I2Cx, ENABLE );
    I2C_SWResetCmd( TCA9539_I2Cx, DISABLE );
    i32Ret = I2C_Start( TCA9539_I2Cx, I2C_TIMEOUT );                                    /* ---起始信号--- */
    if ( LL_OK == i32Ret )
    {
        i32Ret = I2C_TransAddr( TCA9539_I2Cx, u16DevAddr, I2C_DIR_TX, I2C_TIMEOUT );    /* ---7位从机地址传送+传输方向--- */

        if ( LL_OK == i32Ret )
        {
            i32Ret = I2C_TransData( TCA9539_I2Cx, pu8Reg, u8RegLen, I2C_TIMEOUT );      /* ---TCA9539寄存器地址传送--- */
            if ( LL_OK == i32Ret )
            {
                i32Ret = I2C_Restart( TCA9539_I2Cx, I2C_TIMEOUT );                      /* ---重新开始--- */
                if ( LL_OK == i32Ret )
                {
                    if ( 1UL == u32Len )
                    {
                        I2C_AckConfig( TCA9539_I2Cx, I2C_NACK );
                    }

                    i32Ret = I2C_TransAddr( TCA9539_I2Cx, u16DevAddr, I2C_DIR_RX, I2C_TIMEOUT );    /* ---7位从机地址传送+传输方向--- */
                    if ( LL_OK == i32Ret )
                    {
                        i32Ret = I2C_MasterReceiveDataAndStop( TCA9539_I2Cx, pu8Buf, u32Len, I2C_TIMEOUT );     /* ---开始数据接收--- */
                    }
                    I2C_AckConfig( TCA9539_I2Cx, I2C_ACK );
                }
            }
        }
    }

    if ( LL_OK != i32Ret )
    {
        ( void )I2C_Stop( TCA9539_I2Cx, I2C_TIMEOUT );
    }
}

   以下是TCA9539的IO配置代码和IO口读写代码,可以将IO口配置位输出或输入:

/**************************************************************
  * @Name    TCA9539_WritePin
  * @brief
  * @param   u8Port: [输入/出]
**			 u8Pin: [输入/出]
**			 u8PinState: [输入/出]
  * @retval
  * @author  Zachary
  * @Data    2023-02-19
 **************************************************************/
void TCA9539_WritePin( uint8_t u8Port, uint8_t u8Pin, uint8_t u8PinState )
{
    uint8_t u8TempData[2];

    u8TempData[0] = u8Port + TCA9539_REG_OUTPUT_PORT0;
    TCA9539_I2C_Read( TCA9539_I2C_ADDR, &u8TempData[0], 1U, &u8TempData[1], 1U );
    if ( 0U == u8PinState )
    {
        u8TempData[1] &= ( uint8_t )( ~u8Pin );
    }
    else
    {
        u8TempData[1] |= u8Pin;
    }
    TCA9539_I2C_Write( TCA9539_I2C_ADDR, &u8TempData[0], 1U, &u8TempData[1], 1U );
}

/**************************************************************
  * @Name    TCA9539_ReadPin
  * @brief   
  * @param   u8Port: [输入/出] 
**			 u8Pin: [输入/出] 
**			 pu8PinState: [输入/出] 
  * @retval
  * @author  Zachary
  * @Data    2023-02-19
 **************************************************************/
void TCA9539_ReadPin( uint8_t u8Port, uint8_t u8Pin, uint8_t *pu8PinState )
{
    uint8_t u8TempData[2];

	u8TempData[0] = u8Port + TCA9539_REG_INPUT_PORT0;
	TCA9539_I2C_Read( TCA9539_I2C_ADDR, &u8TempData[0], 1U, &u8TempData[1], 1U );
	if (0U != (u8TempData[1] & u8Pin))
    {
		*pu8PinState = 0x01U;
	}
    else
    {
		*pu8PinState = 0x00U;
	}
}

/**************************************************************
  * @Name    TCA9539_ConfigPin
  * @brief   
  * @param   u8Port: [输入/出] 
**			 u8Pin: [输入/出] 
**			 u8Dir: [输入/出] 
  * @retval
  * @author  Zachary
  * @Data    2023-02-19
 **************************************************************/
void TCA9539_ConfigPin( uint8_t u8Port, uint8_t u8Pin, uint8_t u8Dir)
{
    uint8_t u8TempData[2];

	u8TempData[0] = u8Port + TCA9539_REG_CONFIG_PORT0;
	TCA9539_I2C_Read( TCA9539_I2C_ADDR, &u8TempData[0], 1U, &u8TempData[1], 1U );
	if ( TCA9539_DIR_OUT == u8Dir )
    {
		u8TempData[1] &= (uint8_t)(~u8Pin);
	}
    else
    {
		u8TempData[1] |= u8Pin;
	}
	TCA9539_I2C_Write( TCA9539_I2C_ADDR, &u8TempData[0], 1U, &u8TempData[1], 1U );
}

以下是main.c测试代码,我们将板载LED2所对应的管脚配置为输出,并且在主循环中每500ms反转一次。

/**************************************************************
  * @Name    SysInit
  * @brief
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-02-13
 **************************************************************/
static void SysInit( void )
{
    bsp_SetSysClk();
	CLK_GetClockFreq( &sysclk );	/* ---检查时钟是否正确--- */
	delay_init( 240 );				/* ---系统滴答定时器初始化--- */
    bsp_Gpio_Init();				/* ---初始化Gpio--- */
	bsp_TCA9539_Init();
	TCA9539_ConfigPin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_DIR_OUT );
}

/**************************************************************
  * @Name    main
  * @brief
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2022-02-13
 **************************************************************/
int32_t main( void )
{
    SysInit();
    while( 1 )
    {
        LED10_TOGGLE();
        LED11_TOGGLE();
		TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_PIN_SET );
        delay_ms( 500 );
        TCA9539_WritePin( TCA9539_IO_PORT1, TCA9539_IO_PIN7, TCA9539_PIN_RESET );
		delay_ms( 500 );
    }
}

以下是测试视频:

a95b6c7e9ff3fe2f14261b318f0e9f7d

 

以下是代码附件:

HC32F4A0_I2C.7z (1.06 MB, 下载次数: 12)

最新回复

开张就搞i2c,可以呀,楼主大佬!   详情 回复 发表于 2023-3-5 07:27
点赞 关注
 
 

回复
举报

6471

帖子

10

TA的资源

版主

沙发
 

硬件IIC的配置最大支持什么速度?

点评

400Kbps  详情 回复 发表于 2023-3-5 18:55
个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

回复

6972

帖子

11

TA的资源

版主

板凳
 

开张就搞i2c,可以呀,楼主大佬!

 
 
 

回复

36

帖子

1

TA的资源

一粒金砂(中级)

4
 
秦天qintian0303 发表于 2023-3-5 00:48 硬件IIC的配置最大支持什么速度?

400Kbps

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表