使用硬件I2C的说明
STM32F0使用硬件I2C作为master,与外设通信,code步骤如下:
配置GPIO引脚功能
初始化I2C外设
调用I2C的外设库函数进行读写I2C
下面是详细代码:
1. 配置GPIO引脚功能
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_1);
这里外设控制时钟使用了AHB总线时钟,PB8、9脚复用了I2C功能GPIO_AF_1,注意使用了开漏的脚位设置,实际电路上8、9两脚上要上拉10K电阻
2. 初始化I2C外设
I2C_InitTypeDef I2C_InitStructure;
RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_Timing = 0x30E32E44;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
这里工作时钟使用了系统时钟RCC_I2C1CLK_SYSCLK,注意I2C_Timing时钟寄存器的值需要使用ST官方工具来计算
3. 调用I2C的外设库函数进行读写I2C
可以使用查询状态寄存器方式
主要库函数有:
(1).void I2C_TransferHandling(I2C_TypeDef* I2Cx, uint16_t Address, uint8_t Number_Bytes, uint32_t ReloadEndMode, uint32_t StartStopMode)
(2)uint8_t I2C_ReceiveData ( I2C_TypeDef * I2Cx )
(3)void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)
详细说明可看标准外设库帮助文档
I2C读设备数据
/**
* @brief 从I2C1总线上的某一器件的某一起始地址中读取一定字节的数据到数组中
* @param driver_Addr:I2C器件地址
* @param start_Addr:起始字节地址
* @param number_Bytes:要读取的字节数量(小于一页)
* @param read_Buffer:存放读取数据的数组指针
* @retval 是否读取成功
*/
I2C_Status I2C1_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer)
{
uint8_t read_Num;
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_TransferHandling(I2C1, driver_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_SendData(I2C1, start_Addr);
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TC) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_TransferHandling(I2C1, driver_Addr, number_Bytes, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
for(read_Num = 0; read_Num 《 number_Bytes; read_Num++)
{
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
read_Buffer[read_Num] = I2C_ReceiveData(I2C1);
}
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
return I2C_OK;
}
I2C写设备数据
/**
* @brief 从I2C1的总线上的某一器件的某一起始地址中读取一定字节的数据到数组中
* @param driver_Addr:I2C器件地址
* @param start_Addr:起始字节地址
* @param number_Bytes:要读取的字节数量(小于一页)
* @param write_Buffer:存放读取数据的数组指针
* @retval 是否读取成功
*/
I2C_Status I2C1_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer)
{
uint8_t write_Num;
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_TransferHandling(I2C1, driver_Addr, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_SendData(I2C1, start_Addr);
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_TransferHandling(I2C1, driver_Addr, number_Bytes, I2C_AutoEnd_Mode, I2C_No_StartStop);
for(write_Num = 0; write_Num 《 number_Bytes; write_Num++)
{
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_SendData(I2C1, write_Buffer[write_Num]);
}
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
return I2C_OK;
}
使用硬件I2C的说明
STM32F0使用硬件I2C作为master,与外设通信,code步骤如下:
配置GPIO引脚功能
初始化I2C外设
调用I2C的外设库函数进行读写I2C
下面是详细代码:
1. 配置GPIO引脚功能
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_1);
这里外设控制时钟使用了AHB总线时钟,PB8、9脚复用了I2C功能GPIO_AF_1,注意使用了开漏的脚位设置,实际电路上8、9两脚上要上拉10K电阻
2. 初始化I2C外设
I2C_InitTypeDef I2C_InitStructure;
RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_Timing = 0x30E32E44;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
这里工作时钟使用了系统时钟RCC_I2C1CLK_SYSCLK,注意I2C_Timing时钟寄存器的值需要使用ST官方工具来计算
3. 调用I2C的外设库函数进行读写I2C
可以使用查询状态寄存器方式
主要库函数有:
(1).void I2C_TransferHandling(I2C_TypeDef* I2Cx, uint16_t Address, uint8_t Number_Bytes, uint32_t ReloadEndMode, uint32_t StartStopMode)
(2)uint8_t I2C_ReceiveData ( I2C_TypeDef * I2Cx )
(3)void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)
详细说明可看标准外设库帮助文档
I2C读设备数据
/**
* @brief 从I2C1总线上的某一器件的某一起始地址中读取一定字节的数据到数组中
* @param driver_Addr:I2C器件地址
* @param start_Addr:起始字节地址
* @param number_Bytes:要读取的字节数量(小于一页)
* @param read_Buffer:存放读取数据的数组指针
* @retval 是否读取成功
*/
I2C_Status I2C1_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer)
{
uint8_t read_Num;
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_TransferHandling(I2C1, driver_Addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_SendData(I2C1, start_Addr);
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TC) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_TransferHandling(I2C1, driver_Addr, number_Bytes, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
for(read_Num = 0; read_Num 《 number_Bytes; read_Num++)
{
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
read_Buffer[read_Num] = I2C_ReceiveData(I2C1);
}
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
return I2C_OK;
}
I2C写设备数据
/**
* @brief 从I2C1的总线上的某一器件的某一起始地址中读取一定字节的数据到数组中
* @param driver_Addr:I2C器件地址
* @param start_Addr:起始字节地址
* @param number_Bytes:要读取的字节数量(小于一页)
* @param write_Buffer:存放读取数据的数组指针
* @retval 是否读取成功
*/
I2C_Status I2C1_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer)
{
uint8_t write_Num;
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_TransferHandling(I2C1, driver_Addr, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_SendData(I2C1, start_Addr);
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_TransferHandling(I2C1, driver_Addr, number_Bytes, I2C_AutoEnd_Mode, I2C_No_StartStop);
for(write_Num = 0; write_Num 《 number_Bytes; write_Num++)
{
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
I2C_SendData(I2C1, write_Buffer[write_Num]);
}
I2C_Timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
{
if((I2C_Timeout--) == 0)
{
return I2C_FAIL;
}
}
return I2C_OK;
}
举报