首页 > 编程知识 正文

i2c设备地址扫描,i2c地址扫描

时间:2023-05-03 06:14:57 阅读:233154 作者:448

I2C扫描从设备方法 说明

这几天在研究0.96寸OLED屏;但是一直都点不亮,同事建议用I2C扫描从设备地址,如是写了这个函数;虽然最终确定不是软件问题,但是解题思路很好,因此记录下来;MCU是STM32F103VE.

思路

I2C发送从设备地址,检测哪些地址有应答,则把这些地址答应出来,即可知道此I2C挂载了多少从设备;

代码

I2C_SCAN.H

#ifndef __I2C_SCAN_H#define __I2C_SCAN_H#include "stm32f10x.h"#include "stm32f10x_i2c.h"/**************************I2C参数定义,I2C1或I2C2********************************/#define EEPROM_I2Cx I2C1#define EEPROM_I2C_APBxClock_FUN RCC_APB1PeriphClockCmd#define EEPROM_I2C_CLK RCC_APB1Periph_I2C1#define EEPROM_I2C_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd#define EEPROM_I2C_GPIO_CLK RCC_APB2Periph_GPIOB #define EEPROM_I2C_SCL_PORT GPIOB #define EEPROM_I2C_SCL_PIN GPIO_Pin_6#define EEPROM_I2C_SDA_PORT GPIOB #define EEPROM_I2C_SDA_PIN GPIO_Pin_7/*等待超时时间*/#define I2CT_FLAG_TIMEOUT ((uint32_t)0x1000)#define I2CT_LONG_TIMEOUT ((uint32_t)(10 * I2CT_FLAG_TIMEOUT))/*信息输出*/#define EEPROM_DEBUG_ON 0#define EEPROM_INFO(fmt,arg...) printf("<<-EEPROM-INFO->> "fmt"n",##arg)#define EEPROM_ERROR(fmt,arg...) printf("<<-EEPROM-ERROR->> "fmt"n",##arg)#define EEPROM_DEBUG(fmt,arg...) do{ if(EEPROM_DEBUG_ON) printf("<<-EEPROM-DEBUG->> [%d]"fmt"n",__LINE__, ##arg); }while(0)void I2C_SCAN_Init(void);//主函数调用下面函数,如果检测地址0~200中间是否有外设的地址,把200写入进去即可uint32_t I2C_SCAN(uint32_t TEST_ADDRESS);#endif /*__BSP_I2C_24C02_H*/

I2C_SCAN.C

#include "i2c_scan.h"static __IO uint32_t I2CTimeout = I2CT_LONG_TIMEOUT; static uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode);static void I2C_GPIO_Config(void){ //PB6=SCL;PB7=SDA I2C1 GPIO_InitTypeDef GPIO_InitStructure; //使能GPIOB时钟;使能I2C时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //复用开漏输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //复用开漏输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure);}static void I2C_Mode_Config(void){ I2C_InitTypeDef I2C_InitStructure; //设置速度为400Khz I2C_InitStructure.I2C_ClockSpeed = 100000; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //占空比1:2 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //指定自身地址 I2C_InitStructure.I2C_OwnAddress1 = 0x10; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //设备地址七位 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_Init(I2C1,&I2C_InitStructure);}void I2C_SCAN_Init(void){ I2C_GPIO_Config(); I2C_Mode_Config();}uint32_t I2C_SCAN(uint32_t TEST_ADDRESS){ while(TEST_ADDRESS>0) { /* Send STRAT condition */ I2C_GenerateSTART(EEPROM_I2Cx, ENABLE); I2CTimeout = I2CT_FLAG_TIMEOUT; /* Test on EV5 and clear it */ while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) { if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(0); } I2CTimeout = I2CT_FLAG_TIMEOUT; /* Send EEPROM address for write */ I2C_Send7bitAddress(EEPROM_I2Cx, TEST_ADDRESS, I2C_Direction_Transmitter); /* Test on EV6 and clear it */ while(!I2C_CheckEvent(EEPROM_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { if((--I2CTimeout) == 0) break; } if(I2CTimeout>0) printf("%#xn",TEST_ADDRESS); /* Send STOP condition */ I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE); TEST_ADDRESS--; } }/** * @brief Basic management of the timeout situation. * @param errorCode:错误代码,可以用来定位是哪个环节出错. * @retval 返回0,表示IIC读取失败. */static uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode){ /* Block communication and all processes */ EEPROM_ERROR("I2C 等待超时!errorCode = %d",errorCode); return 0;} 最终打印效果&不解的地方

本次挂载了两个从设备,一个是24C02地址为0XA0;一个是OLED,地址为0X78;但最终打印出来的数据如下:
0xaf
0xae
0xad
0xac
0xab
0xaa
0xa9
0xa8
0xa7
0xa6
0xa5
0xa4
0xa3
0xa2
0xa1
0xa0
0x79
0x78

不知道为什么会打印这么多;知道的讲一下哦!

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。