2577|4

36

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

HC32F4A0-硬件I2C应用-AT24C02 [复制链接]

 

本篇测试硬件I2C读写AT24C02,正好用到的触摸屏是电阻屏,可以将系数存到EEPROM中。

板载AT24C02硬件电路如下图,跟TCA9539挂在一条I2C总线上,该总线上还挂了很多别的外设,在总线出设有上拉电阻。

由于我已经初始化过TCA9539,AT24C02与它共用一条I2C总线。因此,波特率不变的情况下,只需初始化一次就可以了。甚至可以调用TCA9539的读写代码,是一模一样的。

但是为了区分,和方便以后移植,分别写了相关函数。

以下是初始化代码:

/**************************************************************
  * [url=home.php?mod=space&uid=32621]@name[/url] bsp_AT2Cxx_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] 2022-02-09
 **************************************************************/
void bsp_AT2Cxx_Init( void )
{
    uint8_t i;
    int32_t i32Ret = LL_ERR;
    float32_t fErr;
    stc_i2c_init_t stcI2cInit;
    stc_gpio_init_t stcGpioInit;
    
    LL_PERIPH_WE( LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU );
    
    /* Configuration I2C GPIO */
    GPIO_StructInit( &stcGpioInit );
    GPIO_Init( AT24Cxx_I2C_SCL_PORT, AT24Cxx_I2C_SCL_PIN, &stcGpioInit );
    GPIO_Init( AT24Cxx_I2C_SDA_PORT, AT24Cxx_I2C_SDA_PIN, &stcGpioInit );
    GPIO_SetFunc( AT24Cxx_I2C_SCL_PORT, AT24Cxx_I2C_SCL_PIN, GPIO_FUNC_49 );
    GPIO_SetFunc( AT24Cxx_I2C_SDA_PORT, AT24Cxx_I2C_SDA_PIN, GPIO_FUNC_48 );

    /* Enable I2C Peripheral*/
    AT24Cxx_I2C_FCG_ENABLE();

    I2C_DeInit( AT24Cxx_I2Cx );
    I2C_StructInit( &stcI2cInit );
    stcI2cInit.u32Baudrate = 100000UL;
    stcI2cInit.u32SclTime  = 0U;
    stcI2cInit.u32ClockDiv = I2C_CLK_DIV16;

    for ( i = 0U; i < 5U; i++ )
    {
        i32Ret = I2C_Init( AT24Cxx_I2Cx, &stcI2cInit, &fErr );
        if ( LL_OK != i32Ret )
        {
            stcI2cInit.u32ClockDiv--;
        } else
        {
            break;
        }
    }

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

    I2C_Cmd( AT24Cxx_I2Cx, ENABLE );
    
    LL_PERIPH_WP( LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU );
}

   以下是读写AT24C02代码,我是一比一对照IO口模拟时序来写的,并且仅注释了IO口模拟的代码,方便对照。

/**************************************************************
  * @Name    AT24Cxx_I2C_Read
  * @brief
  * @param   ReadAddr: [输入/出]
  * @retval
  * @author  Zachary
  * @Data    2022-02-09
 **************************************************************/
void AT24Cxx_I2C_Read( uint16_t u16DevAddr, const uint8_t *pu8Reg, uint8_t u8RegLen, uint8_t *pu8Buf, uint32_t u32Len )
{
    int32_t i32Ret;
    I2C_SWResetCmd( AT24Cxx_I2Cx, ENABLE );
    I2C_SWResetCmd( AT24Cxx_I2Cx, DISABLE );
    i32Ret = I2C_Start( AT24Cxx_I2Cx, I2C_TIMEOUT );
    if( LL_OK == i32Ret )
    {
        i32Ret = I2C_TransAddr( AT24Cxx_I2Cx, u16DevAddr, I2C_DIR_TX, I2C_TIMEOUT );
        if ( LL_OK == i32Ret )
        {
            i32Ret = I2C_TransData( AT24Cxx_I2Cx, pu8Reg, u8RegLen, I2C_TIMEOUT );
            if ( LL_OK == i32Ret )
            {
                i32Ret = I2C_Restart( AT24Cxx_I2Cx, I2C_TIMEOUT );
                if ( LL_OK == i32Ret )
                {
                    if ( 1UL == u32Len )
                    {
                        I2C_AckConfig( AT24Cxx_I2Cx, I2C_NACK );
                    }
                    i32Ret = I2C_TransAddr( AT24Cxx_I2Cx, u16DevAddr, I2C_DIR_RX, I2C_TIMEOUT );    /* ---7位从机地址传送+传输方向--- */
                    if ( LL_OK == i32Ret )
                    {
                        i32Ret = I2C_MasterReceiveDataAndStop( AT24Cxx_I2Cx, pu8Buf, u32Len, I2C_TIMEOUT );     /* ---开始数据接收--- */
                    }
                    I2C_AckConfig( AT24Cxx_I2Cx, I2C_ACK );
                }
            }
        }
    }
    if ( LL_OK != i32Ret )
    {
        I2C_Stop( AT24Cxx_I2Cx, I2C_TIMEOUT );
    }
    
//    i2c_start();
//    i2c_send_onebyte( add_h );      //发送器件地址0XA0,写数据
//    i2c_wait_ack();
//    i2c_send_onebyte( add_l ); //发送低地址
//    i2c_wait_ack();
//    i2c_start();
//    i2c_send_onebyte( 0XA1 + ( ( ReadAddr / 256 ) << 1 ) ); //进入接收模式
//    i2c_wait_ack();
//    temp = i2c_read_onebyte( 0 );
//    i2c_stop();                       //产生一个停止条件
//    return temp;
}


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

    I2C_SWResetCmd( AT24Cxx_I2Cx, ENABLE );
    I2C_SWResetCmd( AT24Cxx_I2Cx, DISABLE );
    i32Ret = I2C_Start( AT24Cxx_I2Cx, I2C_TIMEOUT );
    if( LL_OK == i32Ret )
    {
        i32Ret = I2C_TransAddr( AT24Cxx_I2Cx, u16DevAddr, I2C_DIR_TX, I2C_TIMEOUT );
        if( LL_OK == i32Ret )
        {
            if ( LL_OK == i32Ret )
            {
                i32Ret = I2C_TransData( AT24Cxx_I2Cx, pu8Reg, u8RegLen, I2C_TIMEOUT );
                if ( LL_OK == i32Ret )
                {
                    i32Ret = I2C_TransData( AT24Cxx_I2Cx, pu8Buf, u32Len, I2C_TIMEOUT );
                }
            }
        }
    }
    I2C_Stop( AT24Cxx_I2Cx, I2C_TIMEOUT );

//    i2c_start();

//    i2c_send_onebyte( add_h );          //写

//    i2c_wait_ack();
//    i2c_send_onebyte( add_l );          //发送低地址
//    i2c_wait_ack();
//    i2c_send_onebyte( DataToWrite );   //发送字节
//    i2c_wait_ack();
//    i2c_stop();                        //产生一个停止条件
//    delay_ms( 2 );
}

因为已经实现了液晶显示,所以直接使用液晶来显示读写情况,没有液晶则可以使用串口打印。

液晶显示读写代码,使用到了sprintf函数,打包要显示的数据。

sprintf( DispBuf1, "WirteBuf:%d,%d,%d,%d,%d,%d,%d,%d", WriteBuf[0], WriteBuf[1], \
WriteBuf[2], WriteBuf[3], WriteBuf[4], WriteBuf[5], WriteBuf[6], WriteBuf[7] );
LCD_ShowString( 10, 500, lcddev.width, lcddev.height, 24, ( uint8_t *)DispBuf1, WHITE, BLACK );  
AT24Cxx_I2C_Write( AT24Cxx_Addr, &Reg, 0x01, WriteBuf, 0x08 );
delay_ms( 10 );
AT24Cxx_I2C_Read( AT24Cxx_Addr, &Reg, 0x01, ReadBuf, 0x08 );  
sprintf( DispBuf2, "ReadBuf:%d,%d,%d,%d,%d,%d,%d,%d", ReadBuf[0], ReadBuf[1], \
ReadBuf[2], ReadBuf[3], ReadBuf[4], ReadBuf[5], ReadBuf[6], ReadBuf[7] );
LCD_ShowString( 10, 550, lcddev.width, lcddev.height, 24, ( uint8_t *)DispBuf2, WHITE, BLACK );

以下是main.c中测试代码:

/**
  ************************************* Copyright ******************************
  *
  *                 (C) Copyright 2022,Zachary ,HPU, China.
  *                            All Rights Reserved
  *
  * FileName   : main.c
  * Version    : v1.0
  * Author     : Zachary
  * Date       : 2023-02-13
  * Description: This is a template project of HC32F4A0
											---Zachary,in Zhejiang Hanpu.
  ******************************************************************************
 */

/* Includes --------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "main.h"
#include "bsp_Gpio.h"
#include "bsp_TCA9539.h"
#include "bsp_NT35510.h"
#include "bsp_AT24Cxx.h"
/* --- Typedef -----------------------------------------------------------*/
/* --- Define ------------------------------------------------------------*/
/* --- Macro -------------------------------------------------------------*/
/* --- Variables ---------------------------------------------------------*/
stc_clock_freq_t sysclk;
uint8_t Reg = 0x00;
uint8_t ReadBuf[8];
uint8_t WriteBuf[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
char DispBuf1[50], DispBuf2[50];
/* --- Functions ---------------------------------------------------------*/
static void SysInit( void );
static void bsp_SetSysClk( void );
static void LCD_Test( void );
/*------------------------------------------------------------------------*/
/**************************************************************
  * @Name    main
  * @brief
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2022-02-13
 **************************************************************/
int32_t main( void )
{
    SysInit();
    sprintf( DispBuf1, "WirteBuf:%d,%d,%d,%d,%d,%d,%d,%d", WriteBuf[0], WriteBuf[1], \
    WriteBuf[2], WriteBuf[3], WriteBuf[4], WriteBuf[5], WriteBuf[6], WriteBuf[7] );
    LCD_ShowString( 10, 500, lcddev.width, lcddev.height, 24, ( uint8_t *)DispBuf1, WHITE, BLACK );
    
    AT24Cxx_I2C_Write( AT24Cxx_Addr, &Reg, 0x01, WriteBuf, 0x08 );
    delay_ms( 10 );
    AT24Cxx_I2C_Read( AT24Cxx_Addr, &Reg, 0x01, ReadBuf, 0x08 );
    
    sprintf( DispBuf2, "ReadBuf:%d,%d,%d,%d,%d,%d,%d,%d", ReadBuf[0], ReadBuf[1], \
    ReadBuf[2], ReadBuf[3], ReadBuf[4], ReadBuf[5], ReadBuf[6], ReadBuf[7] );
    LCD_ShowString( 10, 550, lcddev.width, lcddev.height, 24, ( uint8_t *)DispBuf2, WHITE, BLACK );
    
    
    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 );
    }
}

/**************************************************************
  * @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 );
    bsp_NT35510_Init();
    LCD_Test();
    
}

/**************************************************************
  * @Name    LCD_Test
  * @brief   
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-03-04
 **************************************************************/
static void LCD_Test( void )
{
    LCD_Clear( RED );
    delay_ms( 500 );
    LCD_Clear( GREEN );
    delay_ms( 500 );
    LCD_Clear( BLACK );
    delay_ms( 500 );
    LCD_Clear( BLUE );
    delay_ms( 500 );
    LCD_Clear( YELLOW );
    delay_ms( 500 );
    LCD_Clear( MAGENTA );
    delay_ms( 500 );
    LCD_Draw_Circle( 200, 200, 100, BLACK );
    LCD_ShowString( 300, 300, lcddev.width, lcddev.height, 24, ( uint8_t * )"hello world", BLACK, MAGENTA );
}

/**************************************************************
  * @Name    SetSysClk
  * @brief	 参考自官方工程
  * @param   None
  * @retval
  * @author  Zachary
  * @Data    2023-02-13
 **************************************************************/
static void bsp_SetSysClk( void )
{
    stc_clock_xtal_init_t stcXtalInit;
    stc_clock_pll_init_t stcPLLHInit;

    LL_PERIPH_WE( LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | \
                  LL_PERIPH_EFM | LL_PERIPH_SRAM );		/* ---解保护相关外设--- */

    /* PCLK0, HCLK  Max 240MHz */
    /* PCLK1, PCLK4 Max 120MHz */
    /* PCLK2, PCLK3 Max 60MHz  */
    /* EX BUS Max 120MHz */
    CLK_SetClockDiv( CLK_BUS_CLK_ALL, \
                     ( CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | \
                       CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 | \
                       CLK_HCLK_DIV1 ) );				/* ---外设总线分频--- */

    CLK_XtalStructInit( &stcXtalInit );
    /* Config Xtal and enable Xtal */
    stcXtalInit.u8Mode   = CLK_XTAL_MD_OSC;			/* ---选择外部晶振--- */
    stcXtalInit.u8Drv    = CLK_XTAL_DRV_ULOW;		/* ---晶振驱动能力 有源晶振驱动能力强--- */
    stcXtalInit.u8State  = CLK_XTAL_ON;
    stcXtalInit.u8StableTime = CLK_XTAL_STB_2MS;	/* ---晶振稳定等待周期--- */
    CLK_XtalInit( &stcXtalInit );

    CLK_PLLStructInit( &stcPLLHInit );				/* ---锁相环寄存器初始化--- */
    /* VCO = (8/1)*120 = 960MHz*/
    stcPLLHInit.u8PLLState = CLK_PLL_ON;
    stcPLLHInit.PLLCFGR = 0UL;
    stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLN = 120UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL;
    CLK_PLLInit( &stcPLLHInit );

    /* Highspeed SRAM set to 0 Read/Write wait cycle */
    SRAM_SetWaitCycle( SRAM_SRAMH, SRAM_WAIT_CYCLE0, SRAM_WAIT_CYCLE0 );

    /* SRAM1_2_3_4_backup set to 1 Read/Write wait cycle */
    SRAM_SetWaitCycle( ( SRAM_SRAM123 | SRAM_SRAM4 | SRAM_SRAMB ), SRAM_WAIT_CYCLE1, SRAM_WAIT_CYCLE1 );

    /* 0-wait @ 40MHz */
    EFM_SetWaitCycle( EFM_WAIT_CYCLE5 );

    /* 4 cycles for 200 ~ 250MHz */
    GPIO_SetReadWaitCycle( GPIO_RD_WAIT4 );

    CLK_SetSysClockSrc( CLK_SYSCLK_SRC_PLL );

    LL_PERIPH_WP( LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | \
                  LL_PERIPH_EFM | LL_PERIPH_SRAM );		/* ---保护相关外设--- */
}

测试视频:

736f099f0a463d5c9d3e2835cfd88127

测试工程代码:

HC32F4A0_AT24C02.7z (1.09 MB, 下载次数: 12)

最新回复

单片机C中把两个字符串拼接可以哪个函数?   详情 回复 发表于 2023-3-22 17:06
点赞 关注
 
 

回复
举报

7608

帖子

2

TA的资源

五彩晶圆(高级)

沙发
 

好原始,还要一堆sprintf。。。

点评

可以直接取出入到OLED上吗?我感觉也有点小麻烦,而且还吃内存。  详情 回复 发表于 2023-3-22 11:15
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

6972

帖子

11

TA的资源

版主

板凳
 
freebsder 发表于 2023-3-21 10:43 好原始,还要一堆sprintf。。。

可以直接取出入到OLED上吗?我感觉也有点小麻烦,而且还吃内存。

点评

可以啊,又不是很难。实现了显示一个字符,新建一个函数,传入参数为指针,将数组首地址传进去,在函数中将数组中的数据+0x30转为ascii码,挨个显示就行了。 sprintf只是将数据拼接起来,我觉得用起来很方便。比  详情 回复 发表于 2023-3-22 11:33
 
 
 

回复

36

帖子

1

TA的资源

一粒金砂(中级)

4
 
lugl4313820 发表于 2023-3-22 11:15 可以直接取出入到OLED上吗?我感觉也有点小麻烦,而且还吃内存。

可以啊,又不是很难。实现了显示一个字符,新建一个函数,传入参数为指针,将数组首地址传进去,在函数中将数组中的数据+0x30转为ascii码,挨个显示就行了。

sprintf只是将数据拼接起来,我觉得用起来很方便。比如显示浮点是,也可以直接用,现在单片机这么强大,跟何况我现在用的是240MHz的ARM单片机,又不是8051。一般我用到液晶,基本上就是用来做人机界面的。

 
 
 

回复

6471

帖子

10

TA的资源

版主

5
 

单片机C中把两个字符串拼接可以哪个函数?

个人签名

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

 
 
 

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

查找数据手册?

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
快速回复 返回顶部 返回列表