Files
GPS-Navigator-/ETH/UdpServer/User/interface_24c02.c
2025-09-05 21:09:02 +08:00

627 lines
14 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.

#include <debug.h>
#include "interface_config.h"
#include "ch32v30x_i2c.h"
//#define _nop_() Delay_Us(1);
//#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}
#define bit bool
#define MASTER_TEST_LEN 100//连续最多发送100个字节的数据
#define SCL_GPIO GPIOB
#define SCL_PIN GPIO_Pin_10
#define SDA_GPIO GPIOB
#define SDA_PIN GPIO_Pin_11
//void iic_start(void);
//void iic_stop(void);
//void iic_ack(bit ackbit);
//void iic_sendbyte(unsigned char byt);
//void wrbyte_24c02(unsigned int add,unsigned char dat);
//void delay(unsigned char t);
//bit iic_waitack(void);
//unsigned char i2c_recbyte(void);
unsigned char rdbyte_24c02(unsigned int add);
//unsigned char wrEE_CRC_Bak(unsigned char add,unsigned char *eeData,unsigned char len,unsigned char addbak);
//unsigned char rdEE_CRC_Bak(unsigned char add,unsigned char *eeData,unsigned char len,unsigned char addbak);
////FM25CL64指令定义
#define FM25CL64_WREN 0x06 //使能
#define FM25CL64_WRDI 0x04 //失能
#define FM25CL64_RDSR 0x05 //读状态
#define FM25CL64_WRSR 0x01 //写状态
#define FM25CL64_READ 0x03 //读数据
#define FM25CL64_WRITE 0x02 //写数据
#define MAX_FM25CL64_LEN 8192//8k字节
/*********************************************************************
* @fn IIC_Init
*
* @brief Initializes the IIC peripheral.
*
* @return none
*/
void iicInit(I2C_TypeDef *I2Cx, u32 bound, u16 address)
{
GPIO_InitTypeDef GPIO_InitStructure = { 0 };
// I2C_InitTypeDef I2C_InitTSturcture = { 0 };
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// if(I2Cx == I2C1)//判断是I2C1还是I2C2
// {
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// }
// else
// {
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
// }
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// I2C_InitTSturcture.I2C_ClockSpeed = bound;
// I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
// I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_16_9;
// I2C_InitTSturcture.I2C_OwnAddress1 = address;
// I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
// I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
// I2C_Init(I2Cx, &I2C_InitTSturcture);
// I2C_Cmd(I2Cx, ENABLE);
rm3100Init();//初始化RM3100
}
#ifdef _EEROM_CRC_
#define POLY 0x1021
/**
* Calculating CRC-16 in 'C'
* @para addr, start of data
* @para num, length of data
* @para crc, incoming CRC
*/
unsigned int crc16(unsigned char *addr, int num, unsigned int crc)
{
int i;
for (; num > 0; num--) /* Step through bytes in memory */
{
crc = crc ^ ((*addr) << 8); /* Fetch byte from memory, XOR into CRC top byte*/
addr++;
for (i = 0; i < 8; i++) /* Prepare to rotate 8 bits */
{
if (crc & 0x8000) /* b15 is set... */
crc = (crc << 1) ^ POLY; /* rotate and XOR with polynomic */
else /* b15 is clear... */
crc <<= 1; /* just rotate */
} /* Loop for 8 bits */
crc &= 0xFFFF; /* Ensure CRC remains 16-bit value */
} /* Loop until num=0 */
return(crc); /* Return updated CRC */
}
//写入正确会自动写一个备份,写入有问题就不会写备份
unsigned char wrEE_CRC_Bak(unsigned char add,unsigned char *eeData,unsigned char len,unsigned char addbak)
{
uword crc_Res;
unsigned char index;
unsigned char flagEEwrOK;
crc_Res = crc16(eeData, len-2, 0xffff); //计算数据的校验
eeData[len-2] = (ubyte)(crc_Res );
eeData[len-1] = (ubyte)(crc_Res >> 8);
for(index=0;index<len;index++) //写数据
{WDT_vServiceWDT();
wrbyte_24c02( add + index, eeData[index]);
}
flagEEwrOK = 1;
for(index=0;index<len;index++) //校验数据
{WDT_vServiceWDT();
if(rdbyte_24c02( add + index) != eeData[index])
{
flagEEwrOK = 0;
break;
}
}
if(1 == flagEEwrOK) //
{
for(index=0;index<len;index++) //写数据和校验数据
{WDT_vServiceWDT();
wrbyte_24c02( addbak + index, eeData[index]);
}
flagEEwrOK = 2;
for(index=0;index<len;index++)
{WDT_vServiceWDT();
if(rdbyte_24c02( addbak + index) != eeData[index])
{ flagEEwrOK = 0;
break;
}
}
}
else
{
flagEEwrOK = 0;
//.........
}
return flagEEwrOK;
}
unsigned char rdEE_CRC_Bak(unsigned char add,unsigned char *eeData,unsigned char len,unsigned char addbak)
{
uword crc_Res;
unsigned char index;
unsigned char reEEok = 0;
for(index=0;index<len;index++) //读数据和校验数据
{WDT_vServiceWDT();
eeData[index] = rdbyte_24c02(add + index);
}
crc_Res = crc16(eeData, len-2, 0xffff); //计算数据的校验
if( crc_Res == ((uword)eeData[len-1] << 8) + (uword)eeData[len-2]) //对比读取的校验值 正确采用EE值不正确...
{
reEEok = 1;
}
else
{
for(index=0;index<len;index++) //读备份数据和校验数据
{WDT_vServiceWDT();
eeData[index] = rdbyte_24c02(addbak + index);
}
crc_Res = crc16(eeData, len-2, 0xffff); //计算数据的校验
if( crc_Res == ((uword)eeData[len-1] << 8) + (uword)eeData[len-2]) //对比读取的校验值 正确采用EE值不正确...
{
reEEok = 2;
}
else
{
reEEok = 0;
}
}
return reEEok;
}
#endif
void SDAOut(bit c)
{
GPIO_WriteBit(SDA_GPIO, SDA_PIN, c);
}
void SCLOut(bit c)
{
GPIO_WriteBit(SCL_GPIO, SCL_PIN, c);
}
uint8_t readSDA(void)
{
return GPIO_ReadInputDataBit(SDA_GPIO, SDA_PIN);
}
void iic_start(void)
{
SDAOut(1);
_nop_();
SCLOut(1);
somenop;
SDAOut(0);
somenop;
SCLOut(0);
}
void iic_stop(void)
{
SDAOut(0);
_nop_();
SCLOut(1);
somenop;
SDAOut(1);
}
void iic_ack(bit ackbit)
{
if(ackbit)
SDAOut(0);
else
SDAOut(1);
somenop;
SCLOut(1);
somenop;
SCLOut(0);
SDAOut(1);
somenop;
}
bit iic_waitack(void)
{
SDAOut(1);
somenop;
SCLOut(1);
// sdrv_pinctrl_set_input_select(GPIO_Y3, PIN_IS_CMOS_SCHMITT);
// sdrv_gpio_set_pin_direction(GPIO_Y3, GPIO_DIR_IN);
somenop;
if(readSDA())
{
SCLOut(0);
iic_stop();
return 0;
}
else
{
SCLOut(0);
return 1;
}
}
void iic_sendbyte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
SDAOut(1);
else
SDAOut(0);
somenop;
SCLOut(1);
byt <<= 1;
somenop;
SCLOut(0);
}
}
unsigned char iic_recbyte(void)
{
unsigned char da = 0;
unsigned char i = 0;
for(i=0;i<8;i++)
{
SCLOut(1);
// sdrv_pinctrl_set_input_select(GPIO_Y3, PIN_IS_CMOS_SCHMITT);
// sdrv_gpio_set_pin_direction(GPIO_Y3, GPIO_DIR_IN);
somenop;
da <<= 1;
// P1_IOCR01 = 0x0020; // load port control register 1
if(readSDA())
da |= 0x01;
SCLOut(0);
somenop;
}
return da;
}
/**
* @brief 连续读取多个寄存器数据模拟I2C版本
* @param reg_addr : 起始寄存器地址
* @param pData : 存储读取数据的数组指针
* @param len : 数据长度
* @retval 操作状态0-成功1-失败
*/
uint8_t rm3100ReadRegs(uint8_t reg_addr, uint8_t *pData, uint16_t len)
{
// 1. 发送起始条件
iic_start();
// 2. 发送设备地址(写模式)
iic_sendbyte(RM3100_ADDRESS); // 地址左移1位最低位0表示写
if (!iic_waitack())
{ // 等待ACK
iic_stop();
return 1;
}
// 3. 发送寄存器地址
iic_sendbyte(reg_addr);
if (!iic_waitack())
{
iic_stop();
return 1;
}
// 4. 重复起始条件
iic_start();
// 5. 发送设备地址(读模式)
iic_sendbyte((RM3100_ADDRESS) | 0x01); // 最低位1表示读
if (!iic_waitack())
{
iic_stop();
return 1;
}
// 6. 接收数据
while (len > 0)
{
*pData++ = iic_recbyte(); // 读取字节
len--;
// 发送ACK/NACK
if (len > 0)
{
iic_ack(1); // 非最后一个字节发送ACK
}
else
{
iic_ack(0); // 最后一个字节发送NACK
}
}
// 7. 发送停止条件
iic_stop();
return 0;
}
unsigned char wrbyte_24c02(unsigned int add,unsigned char dat)
{
#if EN_24C02
// uint8_t device_add = 0xA0; // 固定设备地址
uint8_t addr_high = (add >> 8) & 0xFF; // 地址高字节
uint8_t addr_low = add & 0xFF; // 地址低字节
//-------------------------------------------------
if(add > E2_PAGE_SIZE)
{
return 1;//地址超长
}
iic_start();
iic_sendbyte(EEPROM_ADDRESS);
iic_waitack();
iic_sendbyte(addr_high);
iic_waitack();
iic_sendbyte(addr_low);
iic_waitack();
iic_sendbyte(dat);
iic_waitack();
iic_stop();
#else
if(add >= MAX_FM25CL64_LEN)//最大地址限制
{
printf("E2 len error!\r\n");
}
else
{
m_tx_buf_u8[0] = FM25CL64_WREN;//写使能
if (sdrv_spi_sync_transmit(&g_master, m_tx_buf_u8, m_rx_buf_u8,1,1))
{
printf("E2 write Failed!\r\n");
}
m_tx_buf_u8[0] = FM25CL64_WRITE;//写数据
m_tx_buf_u8[1] = (uint8_t)( add >> 8);// 高8位地址
m_tx_buf_u8[2] = (uint8_t)( add );//
m_tx_buf_u8[3] = dat;//
if (sdrv_spi_sync_transmit(&g_master, m_tx_buf_u8, m_rx_buf_u8,4,4))
{
printf("E2 write Failed!\r\n");
}
}
#endif
return 0;
}
unsigned char rdbyte_24c02(unsigned int add)
{
#if EN_24C02
uint8_t addr_high = (add >> 8) & 0xFF;
uint8_t addr_low = add & 0xFF;
uint8_t data = 0;
//-------------------------------------------------
// Device Address 1100 000 R/W
iic_start();
iic_sendbyte(EEPROM_ADDRESS);
iic_waitack();
iic_sendbyte(addr_high);
iic_waitack();
iic_sendbyte(addr_low);
iic_waitack();
iic_start();
iic_sendbyte(EEPROM_ADDRESS | 0x01);
iic_waitack();
data = iic_recbyte();
iic_ack(0);
iic_stop();
//CAN_sendAck(add, da);
return data;
#else
if(add >= MAX_FM25CL64_LEN)//最大地址限制
{
printf("E2 len error!\r\n");
}
else
{
m_tx_buf_u8[0] = FM25CL64_READ;//读数据
m_tx_buf_u8[1] = (uint8_t)( add >> 8);// 高8位地址
m_tx_buf_u8[2] = (uint8_t)( add );//
m_tx_buf_u8[3] = 0xFF;//
if (sdrv_spi_sync_transmit(&g_master, m_tx_buf_u8, m_rx_buf_u8,4,4))
{
printf("E2 write Failed!\r\n");
}
return m_rx_buf_u8[3];
}
#endif
}
/**
* @brief 连续写入多个寄存器数据模拟I2C版本
* @param reg_addr : 起始寄存器地址
* @param values : 要写入的数据数组指针
* @param len : 数据长度
* @retval 操作状态0-成功1-失败
*/
uint8_t rm3100WriteMultiReg(uint8_t reg_addr, const uint8_t *values, uint8_t len)
{
// 1. 发送起始条件
iic_start();
// 2. 发送设备地址(写模式)
iic_sendbyte(RM3100_ADDRESS); // 地址左移1位最低位0表示写
if (!iic_waitack()) { // 等待ACK
iic_stop();
return 1;
}
// 3. 发送寄存器地址
iic_sendbyte(reg_addr);
if (!iic_waitack()) {
iic_stop();
return 1;
}
// 4. 循环发送数据
for (uint8_t i = 0; i < len; i++) {
iic_sendbyte(values[i]);
if (!iic_waitack()) { // 每个数据后必须检查ACK
iic_stop();
return 1;
}
}
// 5. 发送停止条件
iic_stop();
return 0;
}
//判断数据是否准备好
uint8_t rm3100CheckDataReady(void)
{
uint8_t cResult = 0;
rm3100ReadRegs(0x34, &cResult, 1);
cResult = cResult&0x80;
return cResult;
}
void rm3100Init(void)
{
uint8_t CCR[6] = {0, 200, 0, 200, 0, 200};//200
rm3100WriteMultiReg(ADDR_CCX, CCR, 6);//设置循环采样次数
//发送一次poll请求开始测量
uint8_t data = POLL_XYZ;
rm3100WriteMultiReg(ADDR_POLL, &data, 1);
}
//判断数据是否准备好
uint8_t RM3100_GetData(short *x,short *y,short*z)
{
static long Mag_Data[3] = {0};
uint8_t temp[9]={0};
uint8_t poll_request = POLL_XYZ;
static uint8_t cNoDataCnt = 0;
//------------------------------------------------
if(rm3100CheckDataReady() == 0x80)
{//data ready
//读取9个字节
rm3100ReadRegs(0x24, temp, 9);
Mag_Data[0]= (long)temp[0]<<16 | (long)temp[1]<<8 | temp[2];
Mag_Data[1] = (long)temp[3]<<16 | (long)temp[4]<<8 | temp[5];
Mag_Data[2] = (long)temp[6]<<16 | (long)temp[7]<<8 | temp[8];
for(uint8_t i=0; i<3; i++)//补码转换
{
if(Mag_Data[i]&0x00800000)
Mag_Data[i] |= 0xff000000;
}
*y = Mag_Data[0];
*x = Mag_Data[1];
*z = Mag_Data[2];
//发送一次poll请求开始测量
rm3100WriteMultiReg(ADDR_POLL, &poll_request, 1);
return 0;
}
else
{
cNoDataCnt +=5;
if (cNoDataCnt >= 20)
{
cNoDataCnt = 0;
rm3100WriteMultiReg(ADDR_POLL, &poll_request, 1);
}
return 1;
}
}