newPtz/drivers/mb85rc64/mb85rc64.c

369 lines
7.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

///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