用面向对象思想封装IIC、AT24C64驱动

发布者:advancement4最新更新时间:2024-06-18 来源: elecfans关键字:AT24C64  驱动 手机看文章 扫描二维码
随时随地手机看文章

一. 简述

使用面向对象的编程思想封装IIC驱动,将IIC的属性和操作封装成一个库,在需要创建一个IIC设备时只需要实例化一个IIC对象即可,本文是基于STM32和HAL库做进一步封装的。底层驱动方法不重要,封装的思想很重要。在完成对IIC驱动的封装之后借助继承特性实现AT24C64存储器的驱动开发,仍使用面向对象的思想封装AT24C64驱动。

二. IIC驱动面向对象封装

iic.h头文件主要是类模板的定义,具体如下:

//定义IIC类

typedef struct IIC_Type

{

   //属性

   GPIO_TypeDef  *GPIOx_SCL;  //GPIO_SCL所属的GPIO组(如:GPIOA)

   GPIO_TypeDef  *GPIOx_SDA;  //GPIO_SDA所属的GPIO组(如:GPIOA)

   uint32_t GPIO_SCL;     //GPIO_SCL的IO引脚(如:GPIO_PIN_0)

   uint32_t GPIO_SDA;     //GPIO_SDA的IO引脚(如:GPIO_PIN_0)

   //操作

   void (*IIC_Init)(const struct IIC_Type*);        //IIC_Init

   void (*IIC_Start)(const struct IIC_Type*);       //IIC_Start

   void (*IIC_Stop)(const struct IIC_Type*);        //IIC_Stop

   uint8_t (*IIC_Wait_Ack)(const struct IIC_Type*);    //IIC_Wait_ack,返回wait失败或是成功

   void (*IIC_Ack)(const struct IIC_Type*);       //IIC_Ack,IIC发送ACK信号

   void (*IIC_NAck)(const struct IIC_Type*);       //IIC_NAck,IIC发送NACK信号

   void (*IIC_Send_Byte)(const struct IIC_Type*,uint8_t);       //IIC_Send_Byte,入口参数为要发送的字节

   uint8_t (*IIC_Read_Byte)(const struct IIC_Type*,uint8_t);     //IIC_Send_Byte,入口参数为是否要发送ACK信号

   void (*delay_us)(uint32_t);              //us延时

}IIC_TypeDef;

iic.c源文件主要是类模板具体操作函数的实现,具体如下:

//设置SDA为输入模式

static void SDA_IN(const struct IIC_Type* IIC_Type_t)

{

  uint8_t io_num = 0;  //定义io Num号

  switch(IIC_Type_t->GPIO_SDA)

  {

   case GPIO_PIN_0:

    io_num = 0;

   break;

   case GPIO_PIN_1:

    io_num = 1;

   break; 

   case GPIO_PIN_2:

    io_num = 2;

   break; 

   case GPIO_PIN_3:

    io_num = 3;

   break;

   case GPIO_PIN_4:

    io_num = 4;

   break; 

    case GPIO_PIN_5:

    io_num = 5;

   break; 

   case GPIO_PIN_6:

    io_num = 6;

   break; 

   case GPIO_PIN_7:

    io_num = 7;

   break;

   case GPIO_PIN_8:

    io_num = 8;

   break; 

   case GPIO_PIN_9:

    io_num = 9;

   break;

   case GPIO_PIN_10:

    io_num = 10;

   break;

   case GPIO_PIN_11:

    io_num = 11;

   break; 

   case GPIO_PIN_12:

    io_num = 12;

   break;

   case GPIO_PIN_13:

    io_num = 13;

   break;

   case GPIO_PIN_14:

    io_num = 14;

   break; 

   case GPIO_PIN_15:

    io_num = 15;

   break;

  }

  IIC_Type_t->GPIOx_SDA->MODER&=~(3<<(io_num*2)); //将GPIOx_SDA->GPIO_SDA清零

  IIC_Type_t->GPIOx_SDA->MODER|=0<<(io_num*2);   //将GPIOx_SDA->GPIO_SDA设置为输入模式

}



//设置SDA为输出模式

static void SDA_OUT(const struct IIC_Type* IIC_Type_t)

{

  uint8_t io_num = 0;  //定义io Num号

  switch(IIC_Type_t->GPIO_SDA)

  {

   case GPIO_PIN_0:

    io_num = 0;

   break;

   case GPIO_PIN_1:

    io_num = 1;

   break; 

   case GPIO_PIN_2:

    io_num = 2;

   break; 

   case GPIO_PIN_3:

    io_num = 3;

   break;

   case GPIO_PIN_4:

    io_num = 4;

   break; 

    case GPIO_PIN_5:

    io_num = 5;

   break; 

   case GPIO_PIN_6:

    io_num = 6;

   break; 

   case GPIO_PIN_7:

    io_num = 7;

   break;

   case GPIO_PIN_8:

    io_num = 8;

   break; 

   case GPIO_PIN_9:

    io_num = 9;

   break;

   case GPIO_PIN_10:

    io_num = 10;

   break;

   case GPIO_PIN_11:

    io_num = 11;

   break; 

   case GPIO_PIN_12:

    io_num = 12;

   break;

   case GPIO_PIN_13:

    io_num = 13;

   break;

   case GPIO_PIN_14:

    io_num = 14;

   break; 

   case GPIO_PIN_15:

    io_num = 15;

   break;

  }

  IIC_Type_t->GPIOx_SDA->MODER&=~(3<<(io_num*2)); //将GPIOx_SDA->GPIO_SDA清零

  IIC_Type_t->GPIOx_SDA->MODER|=1<<(io_num*2);   //将GPIOx_SDA->GPIO_SDA设置为输出模式

}

//设置SCL电平

static void IIC_SCL(const struct IIC_Type* IIC_Type_t,int n)

{

  if(n == 1)

  {

    HAL_GPIO_WritePin(IIC_Type_t->GPIOx_SCL,IIC_Type_t->GPIO_SCL,GPIO_PIN_SET);     //设置SCL为高电平

  }

  else{

    HAL_GPIO_WritePin(IIC_Type_t->GPIOx_SCL,IIC_Type_t->GPIO_SCL,GPIO_PIN_RESET);     //设置SCL为低电平

  }

}

//设置SDA电平

static void IIC_SDA(const struct IIC_Type* IIC_Type_t,int n)

{

  if(n == 1)

  {

    HAL_GPIO_WritePin(IIC_Type_t->GPIOx_SDA,IIC_Type_t->GPIO_SDA,GPIO_PIN_SET);     //设置SDA为高电平

  }

  else{

    HAL_GPIO_WritePin(IIC_Type_t->GPIOx_SDA,IIC_Type_t->GPIO_SDA,GPIO_PIN_RESET);     //设置SDA为低电平

  }

}

//读取SDA电平

static uint8_t READ_SDA(const struct IIC_Type* IIC_Type_t)

{

  return HAL_GPIO_ReadPin(IIC_Type_t->GPIOx_SDA,IIC_Type_t->GPIO_SDA);  //读取SDA电平

}

//IIC初始化

static void IIC_Init_t(const struct IIC_Type* IIC_Type_t)

{

      GPIO_InitTypeDef GPIO_Initure;

    

   //根据GPIO组初始化GPIO时钟

   if(IIC_Type_t->GPIOx_SCL == GPIOA || IIC_Type_t->GPIOx_SDA == GPIOA)

   {

     __HAL_RCC_GPIOA_CLK_ENABLE();   //使能GPIOA时钟

   }

   if(IIC_Type_t->GPIOx_SCL == GPIOB || IIC_Type_t->GPIOx_SDA == GPIOB)

   {

     __HAL_RCC_GPIOB_CLK_ENABLE();   //使能GPIOB时钟

   }

   if(IIC_Type_t->GPIOx_SCL == GPIOC || IIC_Type_t->GPIOx_SDA == GPIOC)

   {

     __HAL_RCC_GPIOC_CLK_ENABLE();   //使能GPIOC时钟

   }

   if(IIC_Type_t->GPIOx_SCL == GPIOD || IIC_Type_t->GPIOx_SDA == GPIOD)

   {

     __HAL_RCC_GPIOD_CLK_ENABLE();   //使能GPIOD时钟

   }

   if(IIC_Type_t->GPIOx_SCL == GPIOE || IIC_Type_t->GPIOx_SDA == GPIOE)

   {

     __HAL_RCC_GPIOE_CLK_ENABLE();   //使能GPIOE时钟

   } 

   if(IIC_Type_t->GPIOx_SCL == GPIOH || IIC_Type_t->GPIOx_SDA == GPIOH)

   {

     __HAL_RCC_GPIOH_CLK_ENABLE();   //使能GPIOH时钟

   }     

   

     //GPIO_SCL初始化设置

     GPIO_Initure.Pin=IIC_Type_t->GPIO_SCL;

     GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出

     GPIO_Initure.Pull=GPIO_PULLUP;          //上拉

     GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;    //快速

     HAL_GPIO_Init(IIC_Type_t->GPIOx_SCL,&GPIO_Initure);

     //GPIO_SDA初始化设置

     GPIO_Initure.Pin=IIC_Type_t->GPIO_SDA;

     GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出

     GPIO_Initure.Pull=GPIO_PULLUP;          //上拉

     GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;    //快速

     HAL_GPIO_Init(IIC_Type_t->GPIOx_SDA,&GPIO_Initure);

     

            //SCL与SDA的初始化均为高电平

      IIC_SCL(IIC_Type_t,1);

       IIC_SDA(IIC_Type_t,1);

}

//IIC Start

static void IIC_Start_t(const struct IIC_Type* IIC_Type_t)

{

  SDA_OUT(IIC_Type_t);      //sda线输出

  IIC_SDA(IIC_Type_t,1);      

  IIC_SCL(IIC_Type_t,1);

  IIC_Type_t->delay_us(4);

   IIC_SDA(IIC_Type_t,0);  //START:when CLK is high,DATA change form high to low 

  IIC_Type_t->delay_us(4);

  IIC_SCL(IIC_Type_t,0);  //钳住I2C总线,准备发送或接收数据 

}

//IIC Stop

static void IIC_Stop_t(const struct IIC_Type* IIC_Type_t)

{

  SDA_OUT(IIC_Type_t); //sda线输出

  IIC_SCL(IIC_Type_t,0);

  IIC_SDA(IIC_Type_t,0); //STOP:when CLK is high DATA change form low to high

   IIC_Type_t->delay_us(4);

  IIC_SCL(IIC_Type_t,1); 

  IIC_SDA(IIC_Type_t,1); //发送I2C总线结束信号

  IIC_Type_t->delay_us(4); 

}

//IIC_Wait_ack 返回HAL_OK表示wait成功,返回HAL_ERROR表示wait失败

static uint8_t IIC_Wait_Ack_t(const struct IIC_Type* IIC_Type_t)   //IIC_Wait_ack,返回wait失败或是成功

{

  uint8_t ucErrTime = 0;

  SDA_IN(IIC_Type_t);      //SDA设置为输入  

  IIC_SDA(IIC_Type_t,1);IIC_Type_t->delay_us(1);   

  IIC_SCL(IIC_Type_t,1);IIC_Type_t->delay_us(1);

  while(READ_SDA(IIC_Type_t))

  {

    ucErrTime++;

    if(ucErrTime>250)

    {

      IIC_Type_t->IIC_Stop(IIC_Type_t);

      return HAL_ERROR;

    }

  }

  IIC_SCL(IIC_Type_t,0);//时钟输出0     

  return HAL_OK;  

}

//产生ACK应答

static void IIC_Ack_t(const struct IIC_Type* IIC_Type_t)      

{

  IIC_SCL(IIC_Type_t,0);

  SDA_OUT(IIC_Type_t);

  IIC_SDA(IIC_Type_t,0);

  IIC_Type_t->delay_us(2);  

  IIC_SCL(IIC_Type_t,1);

  IIC_Type_t->delay_us(2);  

  IIC_SCL(IIC_Type_t,0);

}

//产生NACK应答

static void IIC_NAck_t(const struct IIC_Type* IIC_Type_t)      

{

  IIC_SCL(IIC_Type_t,0);

  SDA_OUT(IIC_Type_t);

[1] [2] [3]
关键字:AT24C64  驱动 引用地址:用面向对象思想封装IIC、AT24C64驱动

上一篇:如何添加触摸屏驱动到TouchGFX中?
下一篇:使用单片机设计一种火灾监测报警系统?

推荐阅读最新更新时间:2026-03-24 11:07

MSP430单片机对AT24C64的读写操作子程序
/*----------------------------------- MSP430单片机对AT24C64的读写操作子程序 来源:晖创电子网www.schuitron.comMSP430程序 ---------------------------------------*/ #ifndef_I2C_H #define_I2C_H #defineSDA_1P4OUT|=0x02//SDA=1 #defineSDA_0P4OUT&=~0x02//SDA=0 #defineSCL_1P4OUT|=0x01//SCL=1 #defineSCL_0P4OUT&=~0x01//SCL=0 #defineSDA_INP4
[单片机]
PIC单片机的AT24C64通讯设计
该程序实现的功能是: 将I2C_A,I2C_B.。...I2C_K内容写入EEPROM中 同时在EEPROM中读出数据从新写入各个寄存器 LISTP=16C74B #include ERRORLEVEL-302 I2C_AEQU0X20 I2C_BEQU0X21 I2C_CEQU0X22 I2C_DEQU0X23 I2C_EEQU0X24 I2C_FEQU0X25 I2C_GEQU0X26 REG1EQU0X2B REG2EQU0X2C COUN TE QU0X71;I2C BCOUNTEQU0X72;I2C TXBUFEQU0X73;I2C RXBUFEQU0X74;I2C BUSCONEQU0X75;I2C BUSS
[单片机]
PIC单片机的<font color='red'>AT24C64</font>通讯设计
人形机器人的电机驱动系统
人形机器人的运动能力本质上取决于电机驱动系统的性能上限。 无论是双足行走、手指精细操作,还是复杂环境中的动态平衡控制,其核心都离不开高响应、高精度、高可靠性的电机驱动架构。 与传统工业机器人相比,人形机器人对体积、重量、能效、安全性和控制精度的要求更为苛刻,电机驱动系统必须在功率密度、控制精度、电磁兼容和系统安全等多个维度上实现系统级优化。 从系统结构看,典型的人形机器人电机驱动单元通常由48V直流母线供电,核心包括三相逆变功率级、栅极驱动器、电机控制MCU、电流与电压检测模块、电源管理单元以及多种通信与安全监测电路。 电机类型以无刷直流电机(BLDC)或永磁同步电机(PMSM)为主,位置反馈通常来自数字
[机器人]
人形机器人的电机<font color='red'>驱动</font>系统
兆易创新GD32H7高性能系列MCU强势扩容,以“超高算力+实时通信”双擎驱动未来
中国北京(2026年1月22日)—— 业界领先的半导体器件供应商兆易创新GigaDevice(股票代码 603986.SH、3986.HK)今日宣布, 正式推出新一代GD32H7系列超高性能MCU,包含GD32H789/779系列超高性能通用MCU ,以及集成EtherCAT ® 从站控制器GD32H78E/77E超高实时性系列MCU,该系列产品基于Arm ® Cortex ® -M7内核,主频高达750MHz,配备高速大容量内存架构及640KB可与CPU同频运行紧耦合内存(TCM),实现了高性能、低动态功耗与高速通信的有机统一。该系列微控制器可适用伺服控制、变频驱动、数字电源、便携电子产品,智能家居以及消防等领域,树立性能新标杆
[嵌入式]
兆易创新GD32H7高性能系列MCU强势扩容,以“超高算力+实时通信”双擎<font color='red'>驱动</font>未来
颠覆性创新:TSN让数据驱动的制造业走得又“快”又“稳”!
图源:Freepik 时间敏感网络(Time-Sensitive Networking,TSN)的本质是一组IEEE 802.1标准,实现了精确的同步和调度流量,使以太网能够支持运动控制和安全系统等对时间要求严格的应用。TSN允许各种数据类型(包括人机界面/监控与数据采集、控制信号和信息技术流量)在单一网络上共存,从而简化架构、降低成本、提高运行时间并增强数据透明度。 简单来说,它的目标是让数据像高铁一样按时刻表运行,而不是像普通交通那样容易堵车。TSN不仅仅是对以太网的一次升级,更是工业物联网(IIoT)和数字化转型中不可或缺的基础技术。 01 在现代制造业中TSN为何如此重要?
[嵌入式]
应对严苛电压瞬态游刃有余,意法半导体智能高边驱动器为汽车系统持续供电与守护
满足汽车电气电子元件质量标准的严苛要求 2026 年 3月 9 日,中国—— 意法半导体的VNQ9050LAJ车规四通道高边驱动器的最低工作电压仅为4V,即便在冷启动电压极低的2.7V工况下也能连续稳定工作,全面提升车辆的可靠性,为用户带来卓越的使用体验。 该芯片在恶劣瞬变条件下韧性表现优异,完全符合汽车行业电气电子元件质量标准LV124的最新版的严格要求。 VNQ9050LAJ 可以驱动12V接地负载,兼容 3V和5V 逻辑信号,采用意法半导体最新一代制造工艺VIPower-M09,每通道典型导通电阻低至 50Ω,有助于提升应用能效,并节省电能。 作为一款智能功率开关, VNQ9050LAJ 引入了更多的创新技术,可
[汽车电子]
应对严苛电压瞬态游刃有余,意法半导体智能高边<font color='red'>驱动</font>器为汽车系统持续供电与守护
Arm Neoverse CSS V3 驱动 Microsoft Azure Cobalt 200:开启 AI 时代 Arm 架构计算新纪元
微软最新发布的 Cobalt 200 CPU 处理器基于 Arm Neoverse CSS V3 打造,为云与 AI 基础设施的设计方式带来突破性变革。 在人工智能 (AI) 时代,行业已从通用型现成系统向定制化基础设施发生显著转型。从传统网络服务到可扩展数据分析,再到大规模模型推理,各类工作负载如今均已融入 AI 驱动的智能处理链路中。现代数据中心的架构设计已经不再是独立计算资源的堆砌,而是需要构建成能够高效处理多样化、高负载任务的融合系统。为满足这一需求,业界正从底层对计算技术进行全面优化,优先保障性能、可扩展性和能效表现。 Azure Cobalt 200:加速融合型 AI 数据中心发展 近日,微软发布了 Co
[嵌入式]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved