627 lines
14 KiB
C
627 lines
14 KiB
C
|
||
|
||
#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;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|