【IAR工程】STM8S208RB基于ST标准库软硬件I2C方式实现读写AT24Cxx

【IAR工程】STM8S208RB基于ST标准库软硬件I2C方式实现读写AT24Cxx


✨通过软件延时模拟I2C通讯时序实现数据的传输相比于硬件外设接口实现方式来说更灵活一些,不受引脚限制,如果不是作为频繁主要的调度运行任务,还是推荐使用软件方式更加灵活一些。相比于新手上而言,使用软件方式更为简单容易一些,硬件上实现也是它的优点,速度快,占用资源少。硬件I2C通信线路需要严格控制,如果外部环境干扰大,通信的可靠性会降低;

🍁硬件I2C接口注意事项

2.3.1版本中的内容进行替换,否则程序会卡死在里面。

  • 🔖I2C请中断函数
void I2C_ClearITPendingBit(I2C_ITPendingBit_TypeDef ITPendingBit)
{
  u8 tmp1 = 0;
  u8 tmp2 = 0;
  u16 tmp3 = 0;

  /* Check the parameters */
  assert_param(IS_I2C_ITPENDINGBIT_OK(ITPendingBit));

  /* Check the clear flag methodology index */
  tmp3 = ((u16)ITPendingBit & (u16)0x0F00);
  
  /* Clear the flag directly in the SR2 register */
  if(tmp3 == 0x0100)
  {
	/* Clear the selected I2C flag */
      I2C->SR2 = (u8)(~(u8)ITPendingBit);
  }
  /* Flags that need a read of SR1 register and a dummy write in CR2 register to be cleared */
  else if(tmp3 == 0x0200)
  {
      /* Read the SR1 register */
      tmp1 = I2C->SR1;
      /* Dummy write in the CR2 register */
      I2C->CR2 = I2C->CR2;
  }
  /* Flags that need a read of SR1 register followed by a read of SR3 register to be cleared */
  else if(tmp3 == 0x0300)
  {
	  /* 2 variables are used to avoid any compiler optimization */
      /* Read the SR1 register */
      tmp1 = I2C->SR1;
      /* Read the SR3 register */
      tmp2 = I2C->SR3;
  }
  /* Flags that need a read of SR1 register followed by a read of DR register to be cleared */
  else if(tmp3 == 0x0400)
  {
      /* 2 variables are used to avoid any compiler optimization */
      /* Read the SR1 register */
      tmp1 = I2C->SR1;
      /* Read the DR register */
      tmp2 = I2C->DR;
  }
}

🛠I2C接口和配置

  • 对于STM8S208RB单片机,默认的硬件I2C接口引脚在SCL:PE1、SDA:PE2引脚上。如果想将硬件I2C引脚切换到PB4和PB5引脚上,需要配置OPTION Byte选项字节,激活AFR6,来完成切换。
    在这里插入图片描述

📓针对软件I2C读取AT24Cxx

🔖采用的是软件I2C实现,可以读写:AT24C01、T24C02、AT24C04、AT24C08、AT24C16、AT24C32、AT24C64、AT24C128、AT24C256 。

  • 通过2个按键控制操作EEPROM器件读和写。
    在这里插入图片描述

  • at24cxx.c

#include "at24cxx.h"
#include "delay.h"


/*******************************************************************************
* 函 数 名         : AT24CXX_Init
* 函数功能	: AT24CXX初始化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void AT24CXX_Init( void )
{
    IIC_Init();//IIC初始化
}

/*******************************************************************************
* 函 数 名         : AT24CXX_ReadOneByte
* 函数功能	 : 在AT24CXX指定地址读出一个数据
* 输    入         : ReadAddr:开始读数的地址
* 输    出         : 读到的数据
*******************************************************************************/
u8 AT24CXX_ReadOneByte( u16 ReadAddr )
{
    u8 temp = 0;
    IIC_Start();
    if( EE_TYPE > AT24C16 )
    {
        IIC_Send_Byte( 0XA0 );	 //发送写命令
        IIC_Wait_Ack();
        IIC_Send_Byte( ReadAddr >> 8 ); //发送高地址
    }
    else
    {
        IIC_Send_Byte( 0XA0 + ( ( ReadAddr / 256 ) << 1 ) ); //发送器件地址0XA0,写数据
    }
    IIC_Wait_Ack();
    IIC_Send_Byte( ReadAddr % 256 ); //发送低地址
    IIC_Wait_Ack();
    IIC_Start();
    IIC_Send_Byte( 0XA1 );         //进入接收模式
    IIC_Wait_Ack();
    temp = IIC_Read_Byte( 0 );
    IIC_Stop();//产生一个停止条件
    return temp;
}

/*******************************************************************************
* 函 数 名         : AT24CXX_WriteOneByte
* 函数功能	 : 在AT24CXX指定地址写入一个数据
* 输    入         : WriteAddr  :写入数据的目的地址
		  DataToWrite:要写入的数据
* 输    出         : 无
*******************************************************************************/
void AT24CXX_WriteOneByte( u16 WriteAddr, u8 DataToWrite )
{
    IIC_Start();
    if( EE_TYPE > AT24C16 )
    {
        IIC_Send_Byte( 0XA0 );	  //发送写命令
        IIC_Wait_Ack();
        IIC_Send_Byte( WriteAddr >> 8 ); //发送高地址
    }
    else
    {
        IIC_Send_Byte( 0XA0 + ( ( WriteAddr / 256 ) << 1 ) ); //发送器件地址0XA0,写数据
    }
    IIC_Wait_Ack();
    IIC_Send_Byte( WriteAddr % 256 ); //发送低地址
    IIC_Wait_Ack();
    IIC_Send_Byte( DataToWrite );   //发送字节
    IIC_Wait_Ack();
    IIC_Stop();//产生一个停止条件
    delay_ms( 10 );
}

/*******************************************************************************
* 函 数 名      : AT24CXX_WriteLenByte
* 函数功能	: 在AT24CXX里面的指定地址开始写入长度为Len的数据
		 用于写入16bit或者32bit的数据
* 输    入    : WriteAddr  :写入数据的目的地址
		 DataToWrite:要写入的数据
	  Len        :要写入数据的长度2,4
* 输    出    : 无
*******************************************************************************/
void AT24CXX_WriteLenByte( u16 WriteAddr, u32 DataToWrite, u8 Len )
{
    u8 t;
    for( t = 0; t < Len; t++ )
    {
        AT24CXX_WriteOneByte( WriteAddr + t, ( DataToWrite >> ( 8 * t ) ) & 0xff );
    }
}

/*******************************************************************************
* 函 数 名         : AT24CXX_ReadLenByte
* 函数功能	 : 在AT24CXX里面的指定地址开始读出长度为Len的数据
		 用于读出16bit或者32bit的数据
* 输    入         : ReadAddr   :开始读出的地址
		 :要读出数据的长度2,4
* 输    出   : 读取的数据
*******************************************************************************/
u32 AT24CXX_ReadLenByte( u16 ReadAddr, u8 Len )
{
    u8 t;
    u32 temp = 0;
    for( t = 0; t < Len; t++ )
    {
        temp <<= 8;
        temp += AT24CXX_ReadOneByte( ReadAddr + Len - t - 1 );
    }
    return temp;
}

/*******************************************************************************
* 函 数 名         : AT24CXX_Check
* 函数功能	 : 检查AT24CXX是否正常
* 输    入         : 无
* 输    出         : 1:检测失败,0:检测成功
*******************************************************************************/
u8 AT24CXX_Check( void )
{
    u8 temp;
    temp = AT24CXX_ReadOneByte( 255 ); //避免每次开机都写AT24CXX
    if( temp == 0x36 )return 0;
    else//排除第一次初始化的情况
    {
        AT24CXX_WriteOneByte( 255, 0X36 );
        temp = AT24CXX_ReadOneByte( 255 );
        if( temp == 0X36 )return 0;
    }
    return 1;
}

/*******************************************************************************
* 函 数 名         : AT24CXX_Read
* 函数功能	 : 在AT24CXX里面的指定地址开始读出指定个数的数据
* 输    入         : ReadAddr :开始读出的地址 对24c02为0~255
		 pBuffer  :数据数组首地址
		 NumToRead:要读出数据的个数
* 输    出         : 无
*******************************************************************************/
void AT24CXX_Read( u16 ReadAddr, u8 *pBuffer, u16 NumToRead )
{
    while( NumToRead )
    {
        *pBuffer++ = AT24CXX_ReadOneByte( ReadAddr++ );
        NumToRead--;
    }
}

/*******************************************************************************
* 函 数 名         : AT24CXX_Write
* 函数功能	 : 在AT24CXX里面的指定地址开始写入指定个数的数据
* 输    入         : WriteAddr :开始写入的地址 对24c02为0~255
		 pBuffer  :数据数组首地址
		 NumToRead:要读出数据的个数
* 输    出         : 无
*******************************************************************************/
void AT24CXX_Write( u16 WriteAddr, u8 *pBuffer, u16 NumToWrite )
{
    while( NumToWrite-- )
    {
        AT24CXX_WriteOneByte( WriteAddr, *pBuffer );
        WriteAddr++;
        pBuffer++;
    }
}


  • at24cxx.h
#ifndef _at24cxx_H
#define _at24cxx_H

#include "stm8s.h"
#include "iic.h"


#define AT24C01		127
#define AT24C02		255
#define AT24C04		511
#define AT24C08		1023
#define AT24C16		2047
#define AT24C32		4095
#define AT24C64	    8191
#define AT24C128	16383
#define AT24C256	32767  

//根据所使用的是24cxx容量不同,选择定义EE_TYPE为AT24C32
#define EE_TYPE AT24C02

u8 AT24CXX_ReadOneByte(u16 ReadAddr);							//指定地址读取一个字节
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite);		//指定地址写入一个字节
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len);//指定地址开始写入指定长度的数据
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len);					//指定地址开始读取指定长度数据
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite);	//从指定地址开始写入指定长度的数据
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead);   	//从指定地址开始读出指定长度的数据

u8 AT24CXX_Check(void);  //检查器件
void AT24CXX_Init(void); //初始化IIC

#endif

  • 🌿主程序代码
/**************************************************************************************

本例采用的是软件I2C实现,可以读取:AT24C01、T24C02、AT24C04、AT24C08、AT24C16、AT24C32、AT24C64、AT24C128、AT24C256  
实验现象:	LED1指示灯闪烁,打开串口助手,如果AT24Cxx检测正常则在串口助手上显示,操作K1键进行
			数据写入,每按下一次K1键数据加1写入,按下K2键进行读取,这些结果均可在串口助手上显示。
		  
接线说明:	1,STM8S单片机-->LED1
		   		PC7-->LED1
                                PC7-->LED2
			2,STM8S单片机-->独立按键模块
			  	PG0-->K1
				PG1-->K2
			3,STM8S单片机-->24Cxx模块
			  	PE1-->SCL
				PE2-->SDA 

注意事项:	1,程序下载完成后再次按下STM8S单片机上的复位按钮RST即可运行程序。
		2,24Cxx芯片的IIC分别SCL:PE1和SDA:PE2引脚上。
-------------------------------------------------
  按键K1,每按一次,向24Cxx芯片数值加1.通过串口1打印写入的数值。
  按键K2,读取前面写入的数值,通过串口打印读取的数值。
				

		
***************************************************************************************/



#include "stm8s.h"      /*  添加库函数头文件 */
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "at24cxx.h"

/* 主函数 */
int main(void)
{
	u8 i=0;
	u8 k=0;
	
  	disableInterrupts();    //关闭系统中断
    //内部时钟为1分频 = 16Mhz
    CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
	USART1_Init(9600);//初始化USART2 , 并设置波特率为9600
    LED_Init();
	enableInterrupts();     //使能系统中断
	KEY_Init();
	AT24CXX_Init();
	while(AT24CXX_Check())  //检测AT24C02是否正常
	{
		printf("AT24Cxx检测不正常!\r\n");
		delay_ms(500);
	}
	printf("AT24Cxx检测正常!\r\n");
	
    while(1)
    {
		if(KEY1==0)
		{
			delay_ms(20);
			if(KEY1==0)
			{
			  	k++;
				if(k>254)
				{
					k=254;
				}
				AT24CXX_WriteOneByte(0,k);
				printf("写入的数据是:%d\r\n",k);
			}
			while(KEY1==0);	
		}
		if(KEY2==0)
		{
			delay_ms(20);
			if(KEY2==0)
			{
			  	k=AT24CXX_ReadOneByte(0);
				printf("读取的数据是:%d\r\n",k);	
			}
			while(KEY2==0);	
		}
		
	  	i++;
		if(i%20==0)
		{
		  	LED1_TOGGLE;
		}
		delay_ms(10);
    }
}
//是一个宏定义;在固件库中,它的作用就是检测传递给函数的参数是否是有效的参数
void assert_failed(u8* file, u32 line)
{ 
    while (1)
    {
          
    }
}

✅硬件I2C接口读取AT24C02

🔰只能实现针对小于1KB容量的AT24Cxx读写,也就是AT24C32以下的型号读取。

在这里插入图片描述

  • 🌿i2c_ee.c内容
/******************** 
 * 文件名  :i2c_ee.c
 * 描述    :I2C 总线配置读写函数库    
    |--------------------|
    |  I2C_SCL-PE1       |
    |  I2C_SDA-PE2       |
    |--------------------|

*****************************************/

/* Includes ------------------------------------------------------------------*/
#include "i2c_ee.h"

/*******************************************************************************
* Function Name  : I2C_EE_Init
* Description    : Initializes peripherals used by the I2C EEPROM driver.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EEInit(void)
{
   u8 Input_Clock = 0x0;
  /* Get system clock frequency */
  Input_Clock = CLK_GetClockFreq()/1000000;	
  /* I2C Peripheral Enable */
  I2C_Cmd(ENABLE);
  /* Apply I2C configuration after enabling it */
  I2C_Init(I2C_Speed, I2C1_SLAVE_ADDRESS7, I2C_DUTYCYCLE_2,\
            I2C_ACK_CURR, I2C_ADDMODE_7BIT, Input_Clock);
}

 /*******************************************************************************
* Function Name  : I2C_EE_ByteWrite
* Description    : Writes one byte to the I2C EEPROM.
* Input          : - pBuffer : pointer to the buffer  containing the data to be 
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_ByteWrite(u8* pBuffer, u16 WriteAddr)
{
  /* Send STRAT condition */
  I2C_GenerateSTART(ENABLE);

  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT));  

  /* Send EEPROM address for write */
  I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);
  
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));
      
  /* Send Address (on 2 bytes) of first byte to be written & wait event detection */
  I2C_SendData((u8)(WriteAddr >> 8)); /* MSB */
  /* Test on EV8 and clear it */
  while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING));
  I2C_SendData((u8)(WriteAddr)); /* LSB */
  /* Test on EV8 and clear it */
  while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING));
 
  /* Send the byte to be written */
  I2C_SendData(*pBuffer); 
   
  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  
  /* Send STOP condition */
  I2C_GenerateSTOP(ENABLE);
}

/*******************************************************************************
* Function Name  : I2C_EE_PageWrite
* Description    : Writes more than one byte to the EEPROM with a single WRITE
*                  cycle. The number of byte can't exceed the EEPROM page size.
* Input          : - pBuffer : pointer to the buffer containing the data to be 
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the EEPROM.
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_PageWrite(u8* pBuffer, u16 WriteAddr, u8 NumByteToWrite)
{
  /* While the bus is busy */
  while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
  
  /* Send START condition */
  I2C_GenerateSTART(ENABLE);
  
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT)); 
  
  /* Send EEPROM address for write */
  I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);

  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));
  I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);  

  /* Send Address (on 2 bytes) of first byte to be written & wait event detection */
  I2C_SendData((u8)(WriteAddr >> 8)); /* MSB */
  /* Test on EV8 and clear it */
  while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING));
  I2C_SendData((u8)(WriteAddr)); /* LSB */
  /* Test on EV8 and clear it */
  while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING));  


  /* While there is data to be written */
  while(NumByteToWrite--)  
  {
    /* Send the current byte */
    I2C_SendData(*pBuffer); 

    /* Point to the next byte to be written */
    pBuffer++; 
  
    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  }

  /* Send STOP condition */
  I2C_GenerateSTOP(ENABLE);
}

/*******************************************************************************
* Function Name  : I2C_EE_BufferRead
* Description    : Reads a block of data from the EEPROM.
* Input          : - pBuffer : pointer to the buffer that receives the data read 
*                    from the EEPROM.
*                  - ReadAddr : EEPROM's internal address to read from.
*                  - NumByteToRead : number of bytes to read from the EEPROM.
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_BufferRead(u8* pBuffer, u16 ReadAddr, u8 NumByteToRead)
{  
    /* While the bus is busy */
  while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
  
  /* Generate start & wait event detection */
    I2C_GenerateSTART(ENABLE);
  /* Test on EV5 and clear it */
  while (!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT));
  
  /* Send slave Address in write direction & wait detection event */
    I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);
   /* Test on EV6 and clear it */
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));
    I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);
    
   /* Send Address of first byte to be read & wait event detection */
    I2C_SendData((u8)(ReadAddr >> 8)); /* MSB */
    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    I2C_SendData((u8)(ReadAddr)); /* LSB */
  /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  
  /* Send STRAT condition a second time */  
  I2C_GenerateSTART(ENABLE);
    /* Test on EV5 and clear it */
   while (!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT));
  
  /* Send slave Address in read direction & wait event */
    I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_RX);
   /* Test on EV6 and clear it */
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));
    I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);
  
  /* While there is data to be read */
  while(NumByteToRead)  
  {
    if(NumByteToRead == 1)
    {
      /* Disable Acknowledgement */
      I2C_AcknowledgeConfig(I2C_ACK_NONE);
      
      /* Send STOP Condition */
      I2C_GenerateSTOP(ENABLE);
    }

    /* Test on EV7 and clear it */
    if(I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED))  
    {      
      /* Read a byte from the EEPROM */
      *pBuffer = I2C_ReceiveData();

      /* Point to the next location where the byte read will be saved */
      pBuffer++; 
      
      /* Decrement the read bytes counter */
      NumByteToRead--;        
    }   
  }

  /* Enable Acknowledgement to be ready for another reception */
  I2C_AcknowledgeConfig(I2C_ACK_CURR);
}



uint8_t I2C_ReadRegister_SR1()
{
  uint8_t temp;
  temp=I2C->SR1;
  return temp;
}

void I2C_EE_WaitEepromStandbyState(void)      
{
  u8 SR1_Tmp = 0;
  do
  {
    /* Send START condition */
    I2C_GenerateSTART(ENABLE);
    /* Read I2C1 SR1 register */
    SR1_Tmp =I2C_ReadRegister_SR1();
    /* Send EEPROM address for write */
    I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);;
  }while(!(I2C_ReadRegister_SR1()&0x02));
  
  /* Clear AF flag */
  I2C_ClearFlag(I2C_FLAG_ACKNOWLEDGEFAILURE);
}



/*******************************************************************************
* Function Name  : I2C_EE_BufferWrite
* Description    : Writes buffer of data to the I2C EEPROM.
* Input          : - pBuffer : pointer to the buffer  containing the data to be 
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the EEPROM.
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)
{
  u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

  Addr = WriteAddr % Page_Byte_Size ; 
  count = Page_Byte_Size  - Addr;
  NumOfPage =  NumByteToWrite / Page_Byte_Size ;
  NumOfSingle = NumByteToWrite % Page_Byte_Size ;
 
  /* If WriteAddr is I2C_PageSize aligned  */
  if(Addr == 0) 
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage == 0) 
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_PageSize */
    else  
    {
      while(NumOfPage--)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, Page_Byte_Size ); 
    	I2C_EE_WaitEepromStandbyState();
        WriteAddr +=  Page_Byte_Size ;
        pBuffer += Page_Byte_Size ;
      }

      if(NumOfSingle!=0)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
        I2C_EE_WaitEepromStandbyState();
      }
    }
  }
  /* If WriteAddr is not I2C_PageSize aligned  */
  else 
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage== 0) 
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_PageSize */
    else
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / Page_Byte_Size ;
      NumOfSingle = NumByteToWrite % Page_Byte_Size ;	
      
      if(count != 0)
      {  
        I2C_EE_PageWrite(pBuffer, WriteAddr, count);
        I2C_EE_WaitEepromStandbyState();
        WriteAddr += count;
        pBuffer += count;
      } 
      
      while(NumOfPage--)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, Page_Byte_Size );
        I2C_EE_WaitEepromStandbyState();
        WriteAddr += Page_Byte_Size ;
        pBuffer += Page_Byte_Size ;  
      }
      if(NumOfSingle != 0)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); 
        I2C_EE_WaitEepromStandbyState();
      }
    }
  }  
}


/*****END OF FILE****/
  • 🌿I2C_EE.h内容

/* Define to prevent recursive inclusion ------------------------------------ */
#ifndef __I2C_EE_H
#define __I2C_EE_H

/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define I2C_Speed              100000
#define I2C1_SLAVE_ADDRESS7    0xA0
#define EEPROM_BASE_ADDRESS    0x0000
#define Page_Byte_Size    ((u8)8)   /*EEPROM 每页最多写8Byte*/
#define EEPROM_ADDRESS         0xA0
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void I2C_EEInit(void);
void I2C_EE_ByteWrite(u8* pBuffer, u16 WriteAddr);
void I2C_EE_PageWrite(u8* pBuffer, u16 WriteAddr, u8 NumByteToWrite);
void I2C_EE_BufferRead(u8* pBuffer, u16 ReadAddr, u8 NumByteToRead);
uint8_t I2C_ReadRegister_SR1();
void I2C_EE_WaitEepromStandbyState(void);
void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite);
#endif /* __I2C_EE_H */




  • 🌿主程序代码
/**************************************************************************************
实验现象:打开串口调试助手,选择CH340对应串口号,波特率设置9600, 串口助手上会显示
			printf各种数据格式输出信息。

接线说明:	1,STM8S单片机-->LED
		   		PC7-->LED1
                                PC6-->LED2

注意事项:	1、点击“Download active application”按钮,程序下载完成后,即可运行程序。
		2、串口1使用的是PA4和PA5引脚,所以这两个IO口不要被占用
***************************************************************************************/

#include "stm8s.h"      /*  添加库函数头文件 */
#include "delay.h"
#include "intrinsics.h"
#include "stm8s_clk.h"
#include "led.h"
#include "usart.h"
#include "i2c_ee.h"
#include <stdio.h>//包含此头文件调用printf函数串口才能有输出


u8 Buffer[] = "Hi!STM8S208RB";
#define BASE_ADDRESS ((u16)0x0000)

#define countof(a) (sizeof(a) / sizeof(*(a)))
#define BufferSize1             (countof(Buffer)-1)
u8 Read_Buffer[BufferSize1];


/* 主函数 */
int main( void )
{
    u8 i = 0;

    disableInterrupts();    //关闭系统中断
    //内部时钟为1分频 = 16Mhz
    CLK_SYSCLKConfig( CLK_PRESCALER_HSIDIV1 );

    I2C_DeInit();
    LED_Init();
    USART1_Init( 9600 ); //初始化USART1 , 并设置波特率为9600
    printf( "Hello World! \r\n" );
    enableInterrupts();     //使能系统中断
   
    /* Initialize the I2C */
    I2C_EEInit();     //IIC初始化
    I2C_EE_PageWrite( Buffer, BASE_ADDRESS, BufferSize1 );
    delay_ms( 2000 ); /* To let eeprom the time to finish the write operation */
    I2C_EE_BufferRead( Read_Buffer, BASE_ADDRESS, BufferSize1 );
    printf( "What is writed into a page of AT24C02 EEPROM: \r\n" );

    while( 1 )
    {
        i++;
        if( i % 20 == 0 )
        {
            LED1_TOGGLE;
            LED2_TOGGLE;
        }
        if( i % 100 == 0 )
        {
          printf("Read_Buffer= %s",Read_Buffer);
        }
        delay_ms( 10 );
    }
}
//是一个宏定义;在固件库中,它的作用就是检测传递给函数的参数是否是有效的参数
void assert_failed( u8* file, u32 line )
{
    while ( 1 )
    {

    }
}

📚工程源码

  • 🔖IAR对中文路径不友好,不要将工程解压在带有中文字符路径的文件夹内直接打开工程编译,这样会导致IAR内部检索文件路径将消耗大量CPU资源。
  • 📌软件I2C实现读写AT24Cxx系列程序
  • ✨申明:本文章仅发表在CSDN网站,任何其他网见此内容均为盗链和爬取,请多多尊重和支持原创!
  • 🍁对于文中所提供的相关资源链接将作不定期更换。
链接: https://pan.baidu.com/s/19gqGlPcUdjyL1Y6ZohFxNA
提取码: ku5h
  • 📌硬件接口I2C实现读写AT24C02程序
    ✨申明:本文章仅发表在CSDN网站,任何其他网见此内容均为盗链和爬取,请多多尊重和支持原创!
    🍁对于文中所提供的相关资源链接将作不定期更换。
链接: https://pan.baidu.com/s/1YKuyxTcs6HpWkvmuOTkyQg
提取码: gyi2
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IAR是一种常见的继电器开发工具,用于开发STM8S单片机。STM8S是意法半导体公司推出的一款低功耗、高性能的8位单片机系列。 在使用IAR开发STM8S时,首先需要安装IAR Embedded Workbench软件。这个软件提供了一个集成的开发环境,包括编译器、调试器和IDE等工具,使得开发者能够方便地进行代码编写、编译、下载和调试等步骤。 在编写代码时,可以使用C语言或汇编语言来进行编程。IAR提供了丰富的库函数和例程,方便开发者使用各种功能和外设。开发人员可以根据自己的需求,调用相应的库函数来控制STM8S的引脚、定时器、串口通信、ADC等外设。 编译完成后,可以使用IAR提供的调试器进行下载和调试。开发者可以通过调试器实时监视程序运行的状态,查看变量的值、寄存器的状态,以及程序执行的流程等。同时,也可以进行单步调试、断点调试等功能,帮助开发者更好地进行程序调试和错误定位。 使用IAR开发STM8S具有良好的兼容性和可移植性。开发者可以使用IAR软件在不同的平台上开发STM8S,例如Windows和Linux等操作系统。同时,IAR提供了针对不同型号的STM8S芯片的编译器和库文件,使得开发者能够方便地移植和调试代码。 总之,使用IAR开发STM8S是一种高效、方便和可靠的方式。通过该开发工具,开发者可以快速开发出满足各种需求的嵌入式应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值