[STM32F1] STM32 HAL 库 I2C 的问题

[复制链接]
62|12
east森林 发表于 2026-9-1 21:21 | 显示全部楼层 |阅读模式
I2c, STM32, TE, AD, HA, in
已有一套在 Keil4 上开发完成的软件,现在需要修改部分功能,切换至 Keil5 搭配 HAL 库,目前整体迁移进展还算顺利。

第一个难题是 I2C。板子上挂载了 4 片 24AA1025 EEPROM,该电路在 Keil4 无 HAL 库的旧程序中可以正常工作。

旧代码使用指令:`I2C_SendData(I2C1,AddressMEM>>8);`,但是新版 HAL 库没有这个底层函数,我对这套 HAL 库接口体系有点困惑。

变量`AddressMEM`用来表示 EEPROM 内部字节地址,地址本身取值正常。现在的难点是如何把原有读写逻辑迁移到下面这个 HAL 函数:

HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

该函数一共有 7 个入参,读取数据的函数同样需要适配。
#include <stdio.h>
#include <string.h>
#include "stm32f10x.h"
#include "I2C.h"
#include "define_globals.h"
#include "Subroutines.h"
#include "RTC.h"


void init_i2c()
{
        I2C_InitTypeDef  I2C_InitStructure;
        I2C_Cmd(I2C1, ENABLE);

        // I2C1 configuration for EEPROM
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;                                // Working in Fast Mode
        I2C_InitStructure.I2C_OwnAddress1 = 0x30;                                                // Own I2C Adress
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;                                                // Enables the acknowledgement
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;                //Acknowledge 7-bit address
        I2C_InitStructure.I2C_ClockSpeed = 100000;                                                // Clock frequency 400kHz
        I2C_Init(I2C1, &I2C_InitStructure);

}

unsigned char eeprom_write_bytes(int AddressMEM,int NumByte,unsigned char* pBuffer)
{
                u16 timeout=0;
                char temp;
                int AddressI2C=I2C1_ADDRESS_EEPROM1_BLOCK0;
                //If Adress not in EEPROM1_BLOCK0
                if(AddressMEM>=65536)
                {
                        temp=AddressMEM>>16;
                        AddressI2C=AddressI2C|((temp&0x01)<<3);                //select Block
                        AddressI2C=AddressI2C|(temp&0x06);                                //select EEPROM
                }
                //If Address is too high
                if(AddressMEM>=524288)               
                {
                        return FAILED;
                }
               
               
                //If there is a boundary of a block reached or the message has more than 128 Bytes
                while((AddressMEM%128)+NumByte>128)
                {
                        //write the last bytes which are below the boundary or below 128 bytes in the next instance of eeprom_write_bytes
                        if(eeprom_write_bytes(AddressMEM,(128-(AddressMEM%128)),pBuffer)){return FAILED;}
                        //now we are back in the instance wich can continue with the next bytes:
                        //increment the pointer of the buffer, decrement the NumByte and increment the address.
                        //that will be written in the actual instance
                        pBuffer = pBuffer+(128-(AddressMEM%128));
                        NumByte = NumByte-(128-(AddressMEM%128));
                        AddressMEM = AddressMEM+(128-(AddressMEM%128));
                       
                }
       
                timeout=0;
                //turn off interrupts to prevent breaks while the message is sent                        
//                USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
                USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
                USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP0, DISABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP1, DISABLE);
               
                //wait until I2C slave is ready-----------------------------------------------------------------------------------------------------
                if(i2c_wait_until_ready(AddressI2C)){return FAILED;}
               
                //Send START condition---------------------------------------------------------------------------------------------------------------
          I2C_GenerateSTART(I2C1, ENABLE);
          while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF){return FAILED;}

                //Send Control Byte---------------------------------------------------------------------------------------------------------------
                I2C_Send7bitAddress(I2C1, AddressI2C, I2C_Direction_Transmitter);  
                timeout=0;
          while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)&& timeout<0xFFFF){timeout++;}
          if(timeout==0xFFFF){return FAILED;}

           //Send Address High Byte---------------------------------------------------------------------------------------------------------------
                I2C_SendData(I2C1,AddressMEM>>8);  
                timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}

                //Send Address Low Byte---------------------------------------------------------------------------------------------------------------
          I2C_SendData(I2C1,AddressMEM);
          timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}

         
          // While there is data to be written---------------------------------------------------------------------------------------------------
                while(NumByte--)  
                {
                        timeout=0;
                        //Send the current byte
                        I2C_SendData(I2C1, *pBuffer);                                                        
                        //Point to the next byte to be written
                        pBuffer++;                                                                                                                                        
                        //wait until transmission is ended                       
                        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)&& timeout<0xFFFF){timeout++;}
                        if(timeout==0xFFFF){return FAILED;}
                }

          // Send STOP condition--------------------------------------------------------------------------------------------------------------
          I2C_GenerateSTOP(I2C1, ENABLE);
               
                //turn on interrupts after the message was sent                       
//                USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
                USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
                USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP1, ENABLE);
               
                return SUCCESSFUL;
}

unsigned char eeprom_read_bytes(int AddressMEM,int NumByte,u8* pBuffer)
{
                int temp;
                u16 timeout=0;
          int AddressI2C=I2C1_ADDRESS_EEPROM1_BLOCK0;
                //If Adress not in EEPROM1_BLOCK0
                if(AddressMEM>=65536)
                {
                        temp=AddressMEM>>16;
                        AddressI2C=AddressI2C|((temp&0x01)<<3); //select Block
                        AddressI2C=AddressI2C|(temp&0x06);                        //select EEPROM
                }
                //If Address is too high
                if(AddressMEM>=524288)               
                {
                        return FAILED;
                }
                while((AddressMEM%65536)+NumByte>65536)
                {
                        if(eeprom_read_bytes(AddressMEM,(65536-(AddressMEM%65536)),pBuffer)){return FAILED;}
                        pBuffer = pBuffer+(65536-(AddressMEM%65536));
                        NumByte = NumByte-(65536-(AddressMEM%65536));
                        AddressMEM = AddressMEM+(65536-(AddressMEM%65536));
                }
       
                //turn off interrupts to prevent breaks while the message is sent                        
//                USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
                USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
                USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP0, DISABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP1, DISABLE);

                //wait until I2C slave is ready-----------------------------------------------------------------------------------------------------
                if(i2c_wait_until_ready(AddressI2C)){return FAILED;}

                //Send STRAT condition---------------------------------------------------------------------------------------------------------------
          I2C_GenerateSTART(I2C1, ENABLE);
          timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)&& timeout<0xFFFF){timeout++;}
                if(timeout>0xFFFF)
                {return FAILED;}

                //Send Control Byte---------------------------------------------------------------------------------------------------------------
                I2C_Send7bitAddress(I2C1, AddressI2C, I2C_Direction_Transmitter);
                timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}
                I2C_Cmd(I2C1, ENABLE);

                //Send Address High Byte---------------------------------------------------------------------------------------------------------------
                I2C_SendData(I2C1,AddressMEM>>8);  
                timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}

                //Send Address Low Byte---------------------------------------------------------------------------------------------------------------
          I2C_SendData(I2C1,AddressMEM);
          timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}
         
          //Send STRAT condition---------------------------------------------------------------------------------------------------------------
          I2C_GenerateSTART(I2C1, ENABLE);
          timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}
               
                //Send Control Byte---------------------------------------------------------------------------------------------------------------
                I2C_Send7bitAddress(I2C1, AddressI2C, I2C_Direction_Receiver);
                timeout=0;       
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)&& timeout<0xFFFF)
                if(timeout==0xFFFF)
                {return FAILED;}

          //Read Bytes until NumByte is reached---------------------------------------------------------------------------------------------------
                while(NumByte)  
                {
                        if(NumByte == 1)
                        {
                                // Disable Acknowledgement
                                I2C_AcknowledgeConfig(I2C1, DISABLE);
                                // Send STOP Condition
                                I2C_GenerateSTOP(I2C1, ENABLE);
                        }
                        //Test if Data-Byte is recived
                        if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))  
                        {      
                                I2C_AcknowledgeConfig(I2C1, ENABLE);
                                // Read a byte from the EEPROM
                                *pBuffer = I2C_ReceiveData(I2C1);
                                //Point to the next location where the byte read will be saved
                                pBuffer++;
                                // Decrement the read bytes counter
                                NumByte--;        
                        }   
                }
               
                // Send STOP condition--------------------------------------------------------------------------------------------------------------
                //I2C_GenerateSTOP(I2C1, ENABLE);
               
                //turn on interrupts after the message was sent                       
//                USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
                USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
                USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP1, ENABLE);
               
                return SUCCESSFUL;
}

unsigned char rtc_read_time(int AddressI2C,int AddressMEM,int NumByte,u8* pBuffer)
{
                u16 timeout=0;
         
                //turn off interrupts to prevent breaks while the message is sent                        
//                USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
                USART_ITConfig(USART2, USART_IT_TXE, DISABLE);  //Provisorisch ausgeschaltet!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP0, DISABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP1, DISABLE);

                //wait until I2C slave is ready-----------------------------------------------------------------------------------------------------
                if(i2c_wait_until_ready(AddressI2C)){return FAILED;}       
       
                //Send STRAT condition---------------------------------------------------------------------------------------------------------------
          I2C_GenerateSTART(I2C1, ENABLE);
          timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)&& timeout<0xFFFF){timeout++;}
                if(timeout>0xFFFF)
                {return FAILED;}

                //Send Control Byte---------------------------------------------------------------------------------------------------------------
                I2C_Send7bitAddress(I2C1, AddressI2C, I2C_Direction_Transmitter);
                timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}
                I2C_Cmd(I2C1, ENABLE);


                //Send Address --------------------------------------------------------------------------------------------------------------------
          I2C_SendData(I2C1,AddressMEM);
          timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}
         
          //Send STRAT condition---------------------------------------------------------------------------------------------------------------
          I2C_GenerateSTART(I2C1, ENABLE);
          timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}
               
                //Send Control Byte---------------------------------------------------------------------------------------------------------------
                I2C_Send7bitAddress(I2C1, AddressI2C, I2C_Direction_Receiver);
                timeout=0;       
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)&& timeout<0xFFFF)
                if(timeout==0xFFFF)
                {return FAILED;}

          //Read Bytes until NumByte is reached---------------------------------------------------------------------------------------------------
                while(NumByte)  
                {
                        if(NumByte == 1)
                        {
                                // Disable Acknowledgement
                                I2C_AcknowledgeConfig(I2C1, DISABLE);
                                // Send STOP Condition
                                I2C_GenerateSTOP(I2C1, ENABLE);
                        }
                        //Test if Data-Byte is recived
                        if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))  
                        {      
                                I2C_AcknowledgeConfig(I2C1, ENABLE);
                                // Read a byte from the EEPROM
                                *pBuffer = I2C_ReceiveData(I2C1);
                                //Point to the next location where the byte read will be saved
                                pBuffer++;
                                // Decrement the read bytes counter
                                NumByte--;        
                        }   
                }
               
                // Send STOP condition--------------------------------------------------------------------------------------------------------------
                //I2C_GenerateSTOP(I2C1, ENABLE);
               
                //turn on interrupts after the message was sent                       
//                USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
                USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
                USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP1, ENABLE);
               
                return SUCCESSFUL;
}

unsigned char rtc_write_time(int AddressI2C,int AddressMEM,int NumByte,u8* pBuffer)
{
                u16 timeout=0;
       
                //turn off interrupts to prevent breaks while the message is sent                        
//                USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
                USART_ITConfig(USART2, USART_IT_TXE, DISABLE); //Provisorisch Ausgeschaltet!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP0, DISABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP1, DISABLE);

                //wait until I2C slave is ready-----------------------------------------------------------------------------------------------------
                if(i2c_wait_until_ready(AddressI2C)){return FAILED;}

                //Send STRAT condition---------------------------------------------------------------------------------------------------------------
          I2C_GenerateSTART(I2C1, ENABLE);
          while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF){return FAILED;}

                //Send Control Byte---------------------------------------------------------------------------------------------------------------
                I2C_Send7bitAddress(I2C1, AddressI2C, I2C_Direction_Transmitter);  
                timeout=0;
          while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)&& timeout<0xFFFF){timeout++;}
          if(timeout==0xFFFF){return FAILED;}

                //Send Address ---------------------------------------------------------------------------------------------------------------------
          I2C_SendData(I2C1,AddressMEM);
          timeout=0;
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)&& timeout<0xFFFF){timeout++;}
                if(timeout==0xFFFF)
                {return FAILED;}

         
          // While there is data to be written---------------------------------------------------------------------------------------------------
                while(NumByte--)  
                {
                        timeout=0;
                        //Send the current byte
                        I2C_SendData(I2C1, *pBuffer);                                                        
                        //Point to the next byte to be written
                        pBuffer++;                                                                                                                                        
                        //wait until transmission is ended                       
                        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)&& timeout<0xFFFF){timeout++;}
                        if(timeout==0xFFFF){return FAILED;}
                }

          // Send STOP condition--------------------------------------------------------------------------------------------------------------
          I2C_GenerateSTOP(I2C1, ENABLE);
               
                //turn on interrupts after the message was sent                       
//                USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
                USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
                USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);
                CAN_ITConfig(CAN1,CAN_IT_FMP1, ENABLE);
               
                return SUCCESSFUL;
}


unsigned char i2c_wait_until_ready(char I2C_EEAddress)
{
  volatile uint16_t SR1_Tmp = 0;
  volatile uint16_t SR2_Tmp = 0;
  u32 timeout=0;
        int x;
  do
  {
    /*!< Send START condition */
    I2C_GenerateSTART(I2C1, ENABLE);

    /*!< Read sEE SR1 + SR2 registers to clear pending flags (ADDR Flag) */
    SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);
        //SR2_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR2);

    /*!< Send EEPROM address for write */
    I2C_Send7bitAddress(I2C1, I2C_EEAddress, I2C_Direction_Transmitter);
        timeout++;
  }while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002) && timeout<0xFFF);          //ADDR bit the I2C_SR1 Register is set after
                                                                                                                                                                          //the ACK of the byte is received.
                                                                                                                                                                        //While the EEPROM is in standby, he return a NACK
  if(timeout==0xFFF)
  {
          return FAILED;
  }       

  /*!< Clear AF flag */
  I2C_ClearFlag(I2C1, I2C_FLAG_AF);

  /*!< STOP condition */   
  I2C_GenerateSTOP(I2C1, ENABLE);
       
        /*!< wait for Bus free time see datasheet of 24AA1025*/
        for(x=0;x<1500;x++){}

  return SUCCESSFUL;
}

void log_date(){
        g_Log_array[0] = 1;                                                         //Msg ID
        g_Log_array[1] = g_date;                                         //date
        g_Log_array[2] = g_month;                                 //month
        g_Log_array[3] = g_year & 0xFF;         //first byte of the year
        g_Log_array[4] = g_year >> 8;                 //second byte of the year
       
        //delete other positions
        g_Log_array[5] = 0;
        g_Log_array[6] = 0;
        g_Log_array[7] = 0;
       
        write_log_data_EEPROM();
}

void log_login(unsigned char user){
        g_Log_array[0] = 2;                                                         //Msg ID
        g_Log_array[1] = user;                                                 //User ID
        g_Log_array[2] = g_hour;                                         //hour
        g_Log_array[3] = g_minute;                                 //minute
       
        //delete other positions
        g_Log_array[4] = 0;
        g_Log_array[5] = 0;
        g_Log_array[6] = 0;
        g_Log_array[7] = 0;
       
        write_log_data_EEPROM();
}

void log_prog_start(unsigned char station, unsigned char prog_Nr, unsigned int ref_Nr){
        g_Log_array[0] = 3;                                                                                 //Msg ID
        g_Log_array[1] = station;                                                         //station
        g_Log_array[2] = prog_Nr;                                                         //program number
        g_Log_array[3] = g_hour;                                                                 //hour
        g_Log_array[4] = g_minute;                                                         //minute
        g_Log_array[5] = ref_Nr & 0xFF;                                 //fist byte of reference number
        g_Log_array[6] = (ref_Nr >>  8) & 0xFF;        //second byte of reference number
        g_Log_array[7] = (ref_Nr >> 16) & 0xFF; //third byte of reference number
       
        write_log_data_EEPROM();
}

void log_prog_stop(unsigned char station, unsigned char prog_Nr){
        g_Log_array[0] = 4;                                                                                 //Msg ID
        g_Log_array[1] = station;                                                         //station
        g_Log_array[2] = prog_Nr;                                                         //program number
        g_Log_array[3] = g_hour;                                                                 //hour
        g_Log_array[4] = g_minute;                                                         //minute

        //delete old values
        g_Log_array[5] = 0;
        g_Log_array[6] = 0;
        g_Log_array[7] = 0;

        write_log_data_EEPROM();
}

void log_finished_step(unsigned char station, unsigned char prog_Nr, unsigned char step_Nr,int step_time, unsigned char av_power, unsigned char av_temperature, int nom_freq){
        char temp;
       
        //round nominal frequency and divide by 1000, so that we log 0.1 kHz
        nom_freq = (int)(((double)nom_freq + 50.0)/100.0);
       
        //Byte 0
        temp = 5;                                                                                                                                                        //Bit 0-4 = Msg_ID
        temp = ((station & 7)<<5) | temp;                                                        //Bit 0-2 of station = Bit 5-7 of Byte 0
        g_Log_array[0] = temp;
        //Byte 1
  temp = station >> 3;                                                                                                        //Bit 3 of station = Bit 0 of Byte 1
        temp = ((prog_Nr & 0X7F) << 1) | temp;                                //Bit 0-6 of prog_Nr = Bit 1-7 of Byte 1
        g_Log_array[1] = temp;                                                                
        //Byte 2
        temp = step_Nr & 0x7F;                                                                                                //Bit 0-6 of step_Nr = Bit 0-6 of Byte 2
        temp = ((step_time & 1) << 7) | temp;                                        //Bit 0 of step_time = Bit 7 of Byte 2
        g_Log_array[2] = temp;                                                                
        //Byte 3
        g_Log_array[3] = (step_time >> 1) & 0xFF;                        //Bit 1-8 of step_time = Byte 3
        //Byte 4
        temp = (step_time >> 9) & 0X7;                                                                //Bit 9-11 of step_time = Bit 0-2 of Byte 4
        temp = ((av_power & 0X1F) << 4) | temp;                          //Bit 0-4 of av_power = Bit 3-7 of Byte 4
        g_Log_array[4] = temp;                                                
        //Byte 5
        temp = (av_power >> 5) & 3;                                                                                //Bit 5-6 of av_power = Bit 0-1 of Byte 5
        temp = ((av_temperature & 0X3F) << 2) | temp;        //Bit 0-5 of nom_freq = Bit 2-7 of Byte 5
        g_Log_array[5] = temp;                       
        //Byte 6
        temp = (av_temperature >> 6) & 1;                                                        //Bit 6 of av_temperature = Bit 0 of Byte 6
        temp = ((nom_freq & 0x7F) << 1) | temp;                                //Bit 0-6 of nom_freq = bit 1-7 of Byte 6
        g_Log_array[6] = temp;                        
        //Byte 7
        g_Log_array[7] = nom_freq >> 7;
        write_log_data_EEPROM();
}

void log_error_msg(unsigned char error_ID, unsigned char generator_ID){
       
//        unsigned char EEPROM_value_errorlog_pointer[4];  //temporary used variable to read the value of the address of the error log data pointer in the EEPROM
        unsigned char error=0;

        //write error parameters also in modbus registers and set error bit in system bits
        g_modbus_registers[ERROR_MSG_HOUR_ADDR - ADDRESS_MIN_MOD] = g_hour;
        g_modbus_registers[ERROR_MSG_MIN_ADDR - ADDRESS_MIN_MOD] = g_minute;
        g_modbus_registers[ERROR_MSG_ERR_ID_ADDR - ADDRESS_MIN_MOD] = error_ID;
        g_modbus_registers[ERROR_MSG_GEN_ID_ADDR - ADDRESS_MIN_MOD] = generator_ID;
        g_modbus_registers[SYSTEM_BITS_ADDR - ADDRESS_MIN_MOD] |= (1<<2);
       
        g_Log_array[0] = 6;                                                                                         //Msg ID
        g_Log_array[1] = g_hour;                                                                         //hour
        g_Log_array[2] = g_minute;                                                                 //minute
        g_Log_array[3] = error_ID;                                                                 //error ID
        g_Log_array[4] = generator_ID;                                                //generator ID

        //delete old values
        g_Log_array[5] = 0;
        g_Log_array[6] = 0;
        g_Log_array[7] = 0;
       
       
        //save firstly the error log message in the "normal" log data
        write_log_data_EEPROM();
       
       
       
        if(g_error_log_data_pointer < EEPROM_ERROR_LOG_BEGIN || g_error_log_data_pointer > EEPROM_ERROR_LOG_END || ((g_error_log_data_pointer - EEPROM_ERROR_LOG_BEGIN)%LOG_DATA_MESSAGE_LENGTH != 0)){
                g_error_log_data_pointer = EEPROM_ERROR_LOG_BEGIN;
        }
       
        //                             -1 because the address itself is also a Byte
        if(g_error_log_data_pointer + (LOG_DATA_MESSAGE_LENGTH - 1) < EEPROM_ERROR_LOG_END){ //checks whether there is an overflow
                if(!error){
                        error = eeprom_write_bytes(g_error_log_data_pointer, LOG_DATA_MESSAGE_LENGTH, g_Log_array); //No overflow
                } else {
                                eeprom_write_bytes(g_error_log_data_pointer, LOG_DATA_MESSAGE_LENGTH, g_Log_array); //No voerflow
                }
                g_error_log_data_pointer = g_error_log_data_pointer + LOG_DATA_MESSAGE_LENGTH;
        } else {
                        //log g_Log_array which is saved in the global variable g_Log_array at start address of error log data memory
      if(!error){               
                                error = eeprom_write_bytes(EEPROM_ERROR_LOG_BEGIN, LOG_DATA_MESSAGE_LENGTH, g_Log_array);
                        } else {
                                        eeprom_write_bytes(EEPROM_ERROR_LOG_BEGIN, LOG_DATA_MESSAGE_LENGTH, g_Log_array);
                        }
                  g_error_log_data_pointer = EEPROM_ERROR_LOG_BEGIN + LOG_DATA_MESSAGE_LENGTH;
        }
       
        if(error){error_handler(EEPROM_ERROR, 0);}
               
}


公羊子丹 发表于 2026-9-2 09:07 | 显示全部楼层
F1的HAL硬件I2C坑真不少,标准库跑得好好的,切HAL就翻车很常见。建议你先把MemAddSize参数核对好,24AA1025是16位片内地址,要填I2C_MEMADD_SIZE_16BIT,很多人这里踩坑。
周半梅 发表于 2026-9-2 09:08 | 显示全部楼层
提醒下,HAL里面DevAddress是7位地址左移1之后的值,别直接把旧代码的AddressI2C原样丢进去,很容易出现NACK。可以先用HAL_I2C_IsDeviceReady做设备就绪测试,先确认能不能找到芯片。
帛灿灿 发表于 2026-9-2 09:09 | 显示全部楼层
你原来代码里有页边界拆分逻辑,迁移HAL之后这部分逻辑不能丢!HAL_I2C_Mem_Write不会自动处理EEPROM页越界,跨页写会乱数据,这块很容易忽略。
童雨竹 发表于 2026-9-2 09:10 | 显示全部楼层
F1硬件I2C有个老毛病,通信异常后BUSY位会卡死释放不掉。建议每次读写前加个判断,如果检测到总线忙,就做一次I2C反初始化再重新初始化,能规避不少偶现卡死问题。
万图 发表于 2026-9-2 09:11 | 显示全部楼层
哈哈,我之前迁移AT24C系列也被这7个参数整懵了。可以先写个极简测试,单字节读写,先调通单字节,再把分页、多片选块选择逻辑套上去,不要直接全量移植。
Wordsworth 发表于 2026-9-2 09:12 | 显示全部楼层
你旧代码读写前后会开关串口、CAN中断,迁移HAL之后这块还得保留。HAL库I2C阻塞函数如果被中断打断,很容易直接超时报错,中断干扰这块千万不要直接删掉。
Bblythe 发表于 2026-9-2 09:13 | 显示全部楼层
怀疑你可以先降速测试,旧代码100KHz,CubeMX里面I2C也配置100K,F1硬件I2C跑400KHz很多EEPROM会不稳定,先低速跑通再往上调速度。
Pulitzer 发表于 2026-9-2 09:13 | 显示全部楼层
想问下,你CubeMX配置I2C引脚的时候,GPIO模式是不是配置成复用开漏?很多人切HAL忘了这点,配成推挽,硬件层面就直接通信异常了,标准库那套初始化不能直接照搬HAL。
Uriah 发表于 2026-9-2 09:14 | 显示全部楼层
写完之后记得给EEPROM留写等待时间,24AA1025内部烧写需要几ms。HAL函数返回OK不等于芯片已经写完,你原来i2c_wait_until_ready轮询检测从机,这个逻辑建议保留,不要直接靠延时硬等。
Clyde011 发表于 2026-9-2 09:15 | 显示全部楼层
如果硬件I2C一直各种报错调不通,实在不行可以临时换软件模拟I2C先验证上层业务逻辑,确认业务没问题之后再回头啃HAL硬件I2C,这样能快速区分是上层逻辑还是HAL底层问题。
香水城 发表于 2026-9-2 10:17 | 显示全部楼层
重点是梳理 EEPROM 的寻址模型,理解HAL_I2C_Mem_Read/Write() 的这几个关键参数,


  • DevAddressEEPROM 器件地址
  • MemAddressEEPROM 内部地址
  • MemAddSize:内部地址长度
  • pData:数据缓冲区
  • Size:读写长度



然后进行合适调用。
MessageRing 发表于 2026-9-2 12:17 | 显示全部楼层
页边界拆分逻辑别忘了,HAL_I2C_Mem_Write不会自动处理,跨页写会乱数据。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

37

主题

717

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部
0