///Copyright (c) 2022, 四川汇源光通信有限公司 ///All rights reserved. ///@file mb85rc64.h ///@brief mb85rc64驱动程序 铁电存储器 /// ///@details ///@note ///@author dufresne ///@date 2025/09/26 /// ///@version v1.0 2022/05/26 初始版本 #include "mb85rc64.h" #ifdef SOFTWARE_I2C /* @ brief 设置SDA引脚为输出模式 @ param @ return @ note 2022-5-26 lqc */ static void mb85rc64_sda_output() { gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, I2C_SDA_PIN); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); MB85RC64_SDA_HIGH; } /* @ brief 设置SDA引脚为输入模式 @ param @ return @ note 2022-5-26 lqc */ static void mb85rc64_sda_input() { gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, I2C_SDA_PIN); gpio_output_options_set(GPIOB, GPIO_PUPD_NONE, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); } /* @ brief I2C start信号 @ param @ return @ note 2022-5-25 */ static void i2c_start() { MB85RC64_SDA_HIGH; delay_us(5); MB85RC64_SCL_HIGH; delay_us(5); MB85RC64_SDA_LOW; delay_us(4); } /* @ brief I2C stop信号 @ param @ return @ note 2022-05-25 */ static void i2c_stop() { MB85RC64_SDA_LOW; delay_us(5); MB85RC64_SCL_HIGH; delay_us(5); MB85RC64_SDA_HIGH; delay_us(4); } /* @ brief mb85rc64接收数据产生ACK信号 @ param SDA被从设备拉为低电平表示应答 @ return @ note 2022-05-26 */ static void mb85rc64_ack() { int i = 0; mb85rc64_sda_input(); delay_us(5); MB85RC64_SCL_HIGH; delay_us(5); while((MB85RC64_SDA_GET) && i<1000) { i++; } delay_us(5); MB85RC64_SCL_LOW; delay_us(5); mb85rc64_sda_output(); } /* @ brief 主机读取数据发送ACK信号,SDA为低电平 @ param SCL下降沿发送 @ return @ note 2022-05-26 */ static void master_ack() { MB85RC64_SDA_LOW; delay_us(5); MB85RC64_SCL_HIGH; delay_us(5); MB85RC64_SCL_LOW; delay_us(5); } /* @ brief 主机读取数据完毕,发送no_ack信号,SDA为高电平 @ param @ return @ note 2022-05-26 */ static void master_no_ack() { MB85RC64_SDA_HIGH; delay_us(5); MB85RC64_SCL_HIGH; delay_us(5); MB85RC64_SCL_LOW; delay_us(5); } /* @ brief 写一个字节数据 @ param @ return @ note 2022-05-26 */ static void mb85rc64_write_byte(uint8_t byte) { for(int i = 0; i < 8; i++) { MB85RC64_SCL_LOW; delay_us(5); if(byte & 0x80) { MB85RC64_SDA_HIGH; } else { MB85RC64_SDA_LOW; } MB85RC64_SCL_HIGH; delay_us(5); byte <<= 1; } MB85RC64_SCL_LOW; } /* @ brief 读一个字节数据 @ param @ return @ note 2022-05-26 */ static uint8_t mb85rc64_read_byte() { uint8_t value = 0; MB85RC64_SCL_LOW; delay_us(5); mb85rc64_sda_input(); for(int i = 0; i < 8; i++) { value <<= 1; MB85RC64_SCL_LOW; delay_us(5); MB85RC64_SCL_HIGH; delay_us(5); if(MB85RC64_SDA_GET) { value = value | 0x01; } else { value = value & 0xfe; } } MB85RC64_SCL_LOW; delay_us(5); mb85rc64_sda_output(); return value; } /* @ brief 保存数据,页写 @ param addr:保存数据的地址,data:需保存的数据,data_len:保存数据的长度,statues:页写还是地址读 @ return @ note 2022-05-27 */ bool mb85rc64_write_read(unsigned short int addr, unsigned char* data, int data_len, bool statues) { uint8_t addr_H = 0; uint8_t addr_L = 0; addr_H = (addr >> 8) & 0x00ff; addr_L = addr & 0x00ff; //启动信号 i2c_start(); //写地址,R/W位=0 // mb85rc64_write_byte(MB85RC64_ADDRESS_WRITE); mb85rc64_write_byte(MB85RC64_ADDRESS << 1); //ack信号 mb85rc64_ack(); //写高8位地址 mb85rc64_write_byte(addr_H); //ack信号 mb85rc64_ack(); //写低8位地址 mb85rc64_write_byte(addr_L); //ack信号 mb85rc64_ack(); if (statues == PAGE_WRITE) { for(int i = 0; i < data_len; i++) { mb85rc64_write_byte(*data); mb85rc64_ack(); data++; } } else if (statues == ADDR_READ) { //启动信号 i2c_start(); //写地址,R/W为为1,读数据 mb85rc64_write_byte((MB85RC64_ADDRESS << 1) + 1); //ack信号 mb85rc64_ack(); for(int i = 0; i < data_len; i++) { //读数据 data[i] = mb85rc64_read_byte(); if(i == data_len - 1) { master_no_ack(); } else { master_ack(); } } } //停止信号 i2c_stop(); return 1; } #endif #ifdef HARDWARE_I2C /* @ brief 保存数据,页写 @ param addr:操作数据的地址,data:需保存的数据,data_len:保存数据的长度,statues:页写还是地址读 @ return @ note 2022-05-27 */ bool mb85rc64_write_read(unsigned short int addr, unsigned char* data, int data_len, bool statues) { uint8_t addr_HL[2]; addr_HL[0] = (addr >> 8) & 0x00ff; addr_HL[1] = addr & 0x00ff; /* 等待总线空闲 */ while(i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY)); /* 发送起始条件 */ i2c_start_on_bus(I2C_PERIPH); /* 等待起始条件已发送标志 */ while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND)); /* 发送从机地址(写模式) */ i2c_master_addressing(I2C_PERIPH, MB85RC64_ADDRESS << 1, I2C_TRANSMITTER); /* 等待地址已发送标志 */ while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND)); /* 清除地址发送标志 */ i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND); for(int i = 0; i < 2; i++) { /* 等待发送数据缓冲区为空 */ while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE)); /* 发送一个字节数据 */ i2c_data_transmit(I2C_PERIPH, addr_HL[i]); } /* 等待数据传输完成 */ while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE)); /* 清除数据传输完成标志 */ i2c_flag_clear(I2C_PERIPH, I2C_FLAG_TBE); if (statues == PAGE_WRITE) { for(int i = 0; i < data_len; i++) { /* 等待发送数据缓冲区为空 */ while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE)); /* 发送一个字节数据 */ i2c_data_transmit(I2C_PERIPH, data[i]); } } else if (statues == ADDR_READ) { // /* 等待总线空闲 */ // while(i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY)); /* 发送起始条件 */ i2c_start_on_bus(I2C_PERIPH); /* 等待起始条件已发送标志 */ while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND)); /* 发送从机地址(写模式) */ i2c_master_addressing(I2C_PERIPH, MB85RC64_ADDRESS << 1, I2C_RECEIVER); /* 等待地址已发送标志 */ while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND)); /* 清除地址发送标志 */ i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND); /* 5. 接收数据 */ if(data_len > 1) { /* 使能ACK(多个字节接收时需要应答) */ i2c_ack_config(I2C_PERIPH, I2C_ACK_ENABLE); for(int i = 0; i < data_len; i++) { if(i == (data_len - 1)) { /* 最后一个字节前禁用ACK */ i2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE); } /* 等待RBNE标志(接收缓冲区非空) */ while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_RBNE)); /* 读取数据 */ data[i] = i2c_data_receive(I2C_PERIPH); } } else { /* 单字节接收:直接禁用ACK */ i2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE); /* 等待RBNE标志 */ while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_RBNE)); /* 读取数据 */ data[0] = i2c_data_receive(I2C_PERIPH); } } /* 发送停止信号 */ i2c_stop_on_bus(I2C_PERIPH); /* 等待停止信号完成 */ while(I2C_CTL0(I2C_PERIPH) & I2C_CTL0_STOP); return 1; } #endif