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
测试工程代码:
|