#include #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 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; } }