通讯总线地址
根据数据手册可知,通讯总线的高6位固定位00100100B 根据PIN 1 即AD0接GND还是VIDDIO 来选择设置LSB 为1还是为0,
最后一位为读或写标志
AD0 拉高时:00100110B = 0x26
AD0 拉低时:00100100B = 0x24
读取芯片ID
查询芯片ID所在的寄存器地址
根据9.1 Register Map章中的Table 13. Register Map可知,芯片ID的寄存器地址为0x00,部分截图如下所示
编写程序读芯片ID
参考:国民技术资料:examples\I2C\EEPROM工程
我用的I2C2 使用的引脚是PA4,PA5 ,需要重映射管脚的功能,通过查阅N32WB452系列用户手册V3.0的7.2.5.12.2 I2C2 管脚重映射可知,需要将管脚配置为GPIO_RMP3_I2C2
以下为7.4.8 AFIO复用重映射配置寄存器3(AFIO_RMP_CFG3) 的部分描述
I2C初始化代码
//外部定义
#define QMA_I2Cx I2C2
/** GPIO configuration and clock enable */
GPIO_InitType GPIO_InitStructure;
I2C_InitType I2C_InitStructure;
/** enable peripheral clk*/
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C2, ENABLE);
I2C_DeInit(QMA_I2Cx);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
GPIO_ConfigPinRemap(GPIO_RMP3_I2C2, ENABLE); //复用io
GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
/** I2C periphral configuration */
I2C_DeInit(QMA_I2Cx);
I2C_InitStructure.BusMode = I2C_BUSMODE_I2C;
I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
I2C_InitStructure.OwnAddr1 = QMA_OWN_ADDR;
I2C_InitStructure.AckEnable = I2C_ACKEN;
I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT;
I2C_InitStructure.ClkSpeed = 100000; // 100000 100K
I2C_Init(QMA_I2Cx, &I2C_InitStructure);
读芯片id代码
//外部定义
#define sQMA7981_FLAG_TIMEOUT ((uint32_t)0x1000)
#define sQMA7981_LONG_TIMEOUT ((uint32_t)(100 * sQMA7981_FLAG_TIMEOUT))
#define QMA_WRITE_ADDR 0x24
#define QMA_READ_ADDR 0x24
u32 sQMA7981Timeout = sQMA7981_LONG_TIMEOUT;
//具体程序
sQMA7981Timeout = sQMA7981_LONG_TIMEOUT;
while (I2C_GetFlag(QMA_I2Cx, I2C_FLAG_BUSY))
{
if ((sQMA7981Timeout--) == 0)
sQMA7981_TIMEOUT_UserCallback();
}
QMA_I2Cx->CTRL1 &= ~0x0800; // clear POSEN
I2C_ConfigAck(QMA_I2Cx, ENABLE);
/** Send START condition */
I2C_GenerateStart(QMA_I2Cx, ENABLE);
/** Test on EV5 and clear it */
sQMA7981Timeout = sQMA7981_LONG_TIMEOUT;
while (!I2C_CheckEvent(QMA_I2Cx, I2C_EVT_MASTER_MODE_FLAG))
{
if ((sQMA7981Timeout--) == 0)
sQMA7981_TIMEOUT_UserCallback();
}
/** 发送数据,寄存器地址为QMA_WRITE_ADDR 方向为主机发送 */
I2C_SendAddr7bit(QMA_I2Cx, QMA_WRITE_ADDR, I2C_DIRECTION_SEND);
/** Test on EV6 and clear it */
sQMA7981Timeout = sQMA7981_LONG_TIMEOUT;
while (!I2C_CheckEvent(QMA_I2Cx, I2C_EVT_MASTER_TXMODE_FLAG))
{
if ((sQMA7981Timeout--) == 0)
sQMA7981_TIMEOUT_UserCallback();
}
/** Clear EV6 by setting again the PE bit */
I2C_Enable(QMA_I2Cx, ENABLE);
/** 发送需要读取的寄存器地址 */
I2C_SendData(QMA_I2Cx, ReadAddr);
/** Test on EV8 and clear it */
sQMA7981Timeout = sQMA7981_LONG_TIMEOUT;
while (!I2C_CheckEvent(QMA_I2Cx, I2C_EVT_MASTER_DATA_SENDED))
{
if ((sQMA7981Timeout--) == 0)
sQMA7981_TIMEOUT_UserCallback();
}
/** Send STRAT condition a second time */
I2C_GenerateStart(QMA_I2Cx, ENABLE);
/** Test on EV5 and clear it */
sQMA7981Timeout = sQMA7981_LONG_TIMEOUT;
while (!I2C_CheckEvent(QMA_I2Cx, I2C_EVT_MASTER_MODE_FLAG))
{
if ((sQMA7981Timeout--) == 0)
sQMA7981_TIMEOUT_UserCallback();
}
/** 发送数据,寄存器地址为QMA_WRITE_ADDR 方向为三轴芯片发送,主机接收 */
I2C_SendAddr7bit(QMA_I2Cx, QMA_WRITE_ADDR, I2C_DIRECTION_RECV);
sQMA7981Timeout = sQMA7981_LONG_TIMEOUT;
while (!I2C_GetFlag(QMA_I2Cx, I2C_FLAG_ADDRF))
{
if ((sQMA7981Timeout--) == 0)
sQMA7981_TIMEOUT_UserCallback();
}
/** While there is data to be read */
if (NumByteToRead == 1)
{
/** Disable Acknowledgement */
I2C_ConfigAck(QMA_I2Cx, DISABLE);
(void)(QMA_I2Cx->STS1); /// clear ADDR
(void)(QMA_I2Cx->STS2);
I2C_GenerateStop(QMA_I2Cx, ENABLE);
}
/** One byte */
if (NumByteToRead == 1)
{
/** Wait until RXNE flag is set */
sQMA7981Timeout = sQMA7981_LONG_TIMEOUT;
while (!I2C_GetFlag(QMA_I2Cx, I2C_FLAG_RXDATNE))
{
if ((sQMA7981Timeout--) == 0)
sQMA7981_TIMEOUT_UserCallback();
}
/** 读取数据*/
*pBuffer = I2C_RecvData(QMA_I2Cx);
}
说明
目前先写到这里,只是读了一下芯片的id,读三轴数据时一样的,上方已经给出了三轴的寄存器地址,只需要修改I2C_SendData(QMA_I2Cx, ReadAddr);
中的ReadAddr读取相应的寄存器即可,但是需要注意的是,每个轴的数据中,低6位所在的寄存器是低地址的高6位,即
x轴:0x01寄存器地址的2-7位为x轴数据的0-5位,0x02寄存器的0-7位为x轴数据的6-13位
结束
好了 到这里就结束了 有什么问题可以私信我