///Copyright (c) 2022, 四川汇源光通信有限公司 ///All rights reserved. ///@file mb85rc64.h ///@brief mb85rc64驱动程序 铁电存储器 /// ///@details ///@note ///@author lqc ///@date 2022/05/26 /// ///@version v1.0 2022/05/26 初始版本 #include "mb85rc64.h" /* @ brief 延时函数 @ param @ return @ note 2022-5-23 */ static void delay_us(int us) { for(int i = 0; i < us; i++ ) { asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); } } /* @ brief 芯片初始化 @ param @ return @ note 2022-05-26 */ void mb85rc64_gpio_init() { //配置引脚时钟 rcu_periph_clock_enable(RCU_GPIOB); //设置引脚为输出模式:PB6 gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6); //设置引脚PB7输出模式 gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7); MB85RC64_SCL_HIGH; MB85RC64_SDA_HIGH; } /* @ brief 设置SDA引脚为输出模式 @ param @ return @ note 2022-5-26 lqc */ static void mb85rc64_sda_output() { gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7); gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7); 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, GPIO_PIN_7); gpio_output_options_set(GPIOB, GPIO_PUPD_NONE, GPIO_OSPEED_50MHZ, GPIO_PIN_7); } /* @ 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:保存数据的长度 @ return @ note 2022-05-27 */ char mb85rc64_page_write(unsigned short int addr, unsigned char* data, int data_len) { 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); //ack信号 mb85rc64_ack(); //写高8位地址 mb85rc64_write_byte(addr_H); //ack信号 mb85rc64_ack(); //写低8位地址 mb85rc64_write_byte(addr_L); //ack信号 mb85rc64_ack(); for(int i = 0; i < data_len; i++) { mb85rc64_write_byte(*data); mb85rc64_ack(); data++; } //停止信号 i2c_stop(); return 1; } /* @ brief 读取数据 ,顺序读取,指定地址,连续接收数据 @ param addr :需要读取数据的地址,data:数据, data_len:数据长度 @ return @ note 2022-05-27 lqc */ char mb85rc64_add_read(unsigned short int addr, unsigned char *data, int data_len) { 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); //ack信号 mb85rc64_ack(); //写高8位地址 mb85rc64_write_byte(addr_H); //ack信号 mb85rc64_ack(); //写低8位地址 mb85rc64_write_byte(addr_L); //ack信号 mb85rc64_ack(); //启动信号 i2c_start(); //写地址,R/W为为1,读数据 mb85rc64_write_byte(MB85RC64_ADDRESS_READ); //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; } void read_mb_id(uint8_t* buff) { i2c_start(); mb85rc64_write_byte(0xf8); mb85rc64_ack(); mb85rc64_write_byte(MB85RC64_ADDRESS_WRITE); mb85rc64_ack(); i2c_start(); mb85rc64_write_byte(0xf9); mb85rc64_ack(); for(int i = 0; i < 3; i++) { //读数据 buff[i] = mb85rc64_read_byte(); if(i == 3 - 1) { master_no_ack(); } else { master_ack(); } } i2c_stop(); }