1.stm32上硬件iic一般有三个,与模拟iic区别在于引脚固定。
2.硬件iic是属于外设的,和串口一个性质。
3.既然是外设,就有其对应的固件库。
typedef struct
{
uint32_t I2C_ClockSpeed; /*时钟频率。
该参数必须设置为小于400kHz的值 */
uint16_t I2C_Mode; /*!< I2C模式。
取值为@ref I2C_mode */
uint16_t I2C_DutyCycle;/*!< I2C快速模式占空比。
取值为@ref I2C_duty_cycle_in_fast_mode */
uint16_t I2C_OwnAddress1;/*!< 指定第一个设备自己的地址。
取值为7位或10位地址。*/
uint16_t I2C_Ack; /*!< 启用或禁用确认。
可以是@ref I2C_acknowledgement */
uint16_t I2C_AcknowledgedAddress; /*指定是否确认7位或10位地址。
取值为@ref i2c_acknowledgement d_addres */
}I2C_InitTypeDef;
//----------------------------------------------------------------------------------
此为iic的初始化所需要的结构体,各个成员为所要设置的参数
void I2C_DeInit(I2C_TypeDef* I2Cx);//重置初始化
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);//初始化
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);//使能
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);//发送
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);//接收
类似于串口的初始化
//------------------------------------------------------------------------------
1.初始化硬件iic的引脚
static void I2C_GPIO_Config(void)
{
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//根据实际引脚选择时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_y | GPIO_Pin_x;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//I2C必须开漏输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C1);//使用I2C1
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//iic模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//占空比有1/2和16/9,两者区别不大
I2C_InitStructure.I2C_OwnAddress1 = 0x30;//主机的I2C地址,随便写的,只要和从设备地址不冲突即可
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//应答使能
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//传输数据的为8位或者10位
I2C_InitStructure.I2C_ClockSpeed = 400000;//有100k 400K,(stm32速度达不到3.4m)可选
I2C_Init(I2C1, &I2C_InitStructure);//初始化
I2C_Cmd(I2C1, ENABLE);//使能
}
2.iic写函数解读(一般根据对象不同能容稍有差别,但作用是一样的都是写数据到丛机)
对于iic的写大致由图中的部分组成,其中的应答和等待都省略了。
uint32_t I2C_ByteWrite(u8* pBuffer, u8 WriteAddr)
{
I2C_GenerateSTART(I2C1, ENABLE);//iic起始信号
//while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));用于判断响应是否完成
I2C_Send7bitAddress(I2C1, xx_ADDRESS, I2C_Direction_Transmitter);//主设备获取从设备地址
I2C_SendData(I2C1, WriteAddr);//从设备发送给主设备(要写到的)从设备中的地址
I2C_SendData(I2C1, *pBuffer); //写的数据不超8位
I2C_GenerateSTOP(I2C1, ENABLE);//iic结束信号
return 1;
}
3.iic读函数解读
uint32_t I2C_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)
{
I2C_GenerateSTART(I2C1, ENABLE);//起始
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//主设备获取从设备地址
I2C_Cmd(I2C1, ENABLE);
I2C_SendData(I2C1, ReadAddr); //读取的位置地址(从哪里开始读)
I2C_GenerateSTART(I2C1, ENABLE);//起始
I2C_Send7bitAddress(I2C, xx_ADDRESS, I2C_Direction_Receiver);//从设备来接收的数据
while(NumByteToRead)
{
if(NumByteToRead == 1)//当读到最后一位数据时候
{
I2C_AcknowledgeConfig(I2C1, DISABLE);//不进行响应
I2C_GenerateSTOP(I2C1, ENABLE);//结束
}
*pBuffer = I2C_ReceiveData(I2C1);//接收的数据存入pbuff中
pBuffer++;
NumByteToRead--;
}
I2C_AcknowledgeConfig(I2C1, ENABLE); //重新开启应答
return 1;
}
一般通过官方的数据或设备信息中查找设备地址
例如eeprom
地址:
其中的1010 和后四位组成了设备地址。
p和A,分别是设备地址和页地址的组合。及a a a 000 ,p p p 111
通过阅读手册知道r和w对应的分别为0和1,
可以这样看对于1010 AAA r/w
1010 0001 w
1010 0000 r
转成16进制数
0xA0 读
或
0xA1 写
地址
其中b7-b0共8位,其中sa0无关紧要,r 1 ,w0
0111 1000 w
0x78
0111 1010 r
0x7a