Keil环境下编写类定义

        当在单片机编程中多处使用同一种资源时,用C++编程会方便的多。

        例如:在STM32中使用了软件I2C程序,C++头文件代码如下:

#ifndef     __I2C_SOFTWARE_H__

#define     __I2C_SOFTWARE_H__

#ifdef __cplusplus

extern "C" {

#endif


 

#include "main.h"

   

// I2C函数使用的宏定义

#define PORT_SDA_I2C_SET_OUT        sdaSetOut()

#define PORT_SDA_I2C_SET_IN         sdaSetInput()

#define PORT_SDA_I2C_SET_1          HAL_GPIO_WritePin(pGpioPortSDA,gpioPinSDA,GPIO_PIN_SET)

#define PORT_SDA_I2C_SET_0          HAL_GPIO_WritePin(pGpioPortSDA,gpioPinSDA,GPIO_PIN_RESET)

#define PORT_SDA_I2C_READ           HAL_GPIO_ReadPin(pGpioPortSDA,gpioPinSDA)

#define PORT_SCL_I2C_SET_OUT        sclSetOut()

#define PORT_SCL_I2C_SET_1          HAL_GPIO_WritePin(pGpioPortSCL,gpioPinSCL,GPIO_PIN_SET)

#define PORT_SCL_I2C_SET_0          HAL_GPIO_WritePin(pGpioPortSCL,gpioPinSCL,GPIO_PIN_RESET)

#define PORT_SCL_I2C_READ           HAL_GPIO_ReadPin(pGpioPortSCL,gpioPinSCL)

#define TimeDelay                   10

class   CI2C_Software

{

    public:

        /// @brief SCL端口定义,PORT + PIN

        GPIO_TypeDef *pGpioPortSCL;

        uint16_t     gpioPinSCL;

        /// @brief SDA端口定义,PORT + PIN

        GPIO_TypeDef *pGpioPortSDA;

        uint16_t     gpioPinSDA;

   

    protected:

        // 修改方向用的结构

        GPIO_InitTypeDef* mpSclStruct;

        GPIO_InitTypeDef* mpSdaStruct;

   

    protected:

        void sdaSetInput() {

            mpSdaStruct->Mode = GPIO_MODE_INPUT;

            mpSdaStruct->Pull = GPIO_PULLUP;/*上拉*/

            HAL_GPIO_Init(pGpioPortSDA, mpSdaStruct);

        }

        void sdaSetOut() {

            mpSdaStruct->Mode = GPIO_MODE_OUTPUT_OD;

            HAL_GPIO_Init(pGpioPortSDA, mpSdaStruct);

        }

        void sdaSetValue(GPIO_PinState value){

            HAL_GPIO_WritePin(pGpioPortSDA,gpioPinSDA,value);

        }

       

        // void sdaSetOutput() {

        //  mpSclStruct->Mode = GPIO_MODE_AF_OD;

        //  mpSclStruct->Pull = GPIO_PULLUP;/*上拉*/

        //  mpSclStruct->

        //  HAL_GPIO_Init(pGpioPortSCL, mpSclStruct);

        // }

        void sclSetValue(GPIO_PinState value) {

            HAL_GPIO_WritePin(pGpioPortSCL, gpioPinSCL, value);

        }

       

    public:

        CI2C_Software();        // 无参数构造函数

        CI2C_Software(GPIO_TypeDef *pPortScl,uint16_t pinScl,GPIO_TypeDef *pPortSda,uint16_t pinSda,   GPIO_InitTypeDef* pSclInitDef,GPIO_InitTypeDef* pSdaInitDef);// 给定SCL和SDA两个信号线的“端口”和“线序”的构造函数,一般使用这个构造函数构造本类的对象

        void    I2C_Start();        // 生成主机I2C起始时序函数

        void    I2C_SendAddress(uint8_t address,uint8_t isRead); // 主机I2C发送地址和读/写方向函数

        void    I2C_SendData(uint8_t data);// 主机I2C发送数据函数

        void    I2C_Stop();        // 主机生成I2C停止时序函数

        void    I2C_Ack();        // 生成主机I2C应答时序函数

        void    I2C_NAck();        // 生成主机I2C不应答时序函数

        uint8_t I2C_WaitAck();        // 主机等待

        uint8_t I2C_ReadDate(uint8_t ack);

   

};

// 公开程序体中定义的2个软件 I2C 对象,供其它模块调用

extern CI2C_Software I2CSoftware1;

extern CI2C_Software I2CSoftware2;

#ifdef __cplusplus

}

#endif

#endif

软件I2C程序体代码如下:

#include "main.h"

#include    "I2CSoftware.hpp"

#include "tim.h"

// 初始化I2C1修改方向的数据结构

GPIO_InitTypeDef    gScl1InitTypeDef = { 0,GPIO_MODE_OUTPUT_OD,GPIO_PULLUP,GPIO_SPEED_FREQ_HIGH };

GPIO_InitTypeDef    gSda1InitTypeDef = { 0,GPIO_MODE_INPUT,GPIO_PULLUP,GPIO_SPEED_FREQ_HIGH } ;

// 初始化修改I2C2方向的数据结构

GPIO_InitTypeDef    gScl2InitTypeDef = { 0,GPIO_MODE_OUTPUT_OD,GPIO_PULLUP,GPIO_SPEED_FREQ_HIGH };

GPIO_InitTypeDef    gSda2InitTypeDef = { 0,GPIO_MODE_INPUT,GPIO_PULLUP,GPIO_SPEED_FREQ_HIGH } ;

// 建立两个I2C对象,用于建立和I2C器件的连接

CI2C_Software I2CSoftware1(MCU_SCL1_GPIO_Port, MCU_SCL1_Pin,MCU_SDA1_GPIO_Port,MCU_SDA1_Pin,&gScl1InitTypeDef,&gSda1InitTypeDef);

CI2C_Software I2CSoftware1(MCU_SCL2_GPIO_Port, MCU_SCL2_Pin,MCU_SDA2_GPIO_Port,MCU_SDA2_Pin,&gScl2InitTypeDef,&gSda2InitTypeDef);

/// @brief 无参构造函数

CI2C_Software::CI2C_Software()

{

    mpSclStruct = NULL;

    mpSdaStruct = NULL;

}

/// @brief 给定I2C 2个信号线参数和方向数据结构体的构造函数

/// @param pPortScl :SCL端口

/// @param pinScl :SCL引脚号

/// @param pPortSda :SDA端口

/// @param pinSda :SDA引脚号

/// @param pSclInitDef :SCL修改端口属性的“数据结构”

/// @param pSdaInitDef :SDA修改端口属性的“数据结构”

CI2C_Software::CI2C_Software(GPIO_TypeDef *pPortScl,uint16_t pinScl,GPIO_TypeDef *pPortSda,uint16_t pinSda,

            GPIO_InitTypeDef* pSclInitDef,GPIO_InitTypeDef* pSdaInitDef)

{

    // 赋值引脚端口和引脚号

    pGpioPortSCL = pPortScl;

    gpioPinSCL = pinScl;

    pGpioPortSDA = pPortSda;

    gpioPinSDA = pinSda;

    // 赋值寄存器结构体

    mpSclStruct = pSclInitDef;

    mpSdaStruct = pSdaInitDef;

}

/// @brief I2C Start 函数

void CI2C_Software::I2C_Start(){

    PORT_SDA_I2C_SET_OUT;

    PORT_SCL_I2C_SET_1;

    delay_us(TimeDelay);

    PORT_SDA_I2C_SET_1;

    delay_us(TimeDelay);

    PORT_SDA_I2C_SET_0;

    delay_us(TimeDelay);

    PORT_SCL_I2C_SET_0;

    delay_us(TimeDelay);

}

/// @brief I2C发送一个数据,高字节在前

/// @param data :给定的数据字节

void CI2C_Software::I2C_SendData(uint8_t data){

    uint8_t mask = 0x80;

    PORT_SDA_I2C_SET_OUT;

    for (uint8_t t = 0; t < 8; t++) {

        if (data & mask)

            PORT_SDA_I2C_SET_1;

        else

            PORT_SDA_I2C_SET_0;

        mask >>= 1;

        delay_us(TimeDelay);

        PORT_SCL_I2C_SET_1;

        delay_us(TimeDelay);

        PORT_SCL_I2C_SET_0;

        delay_us(TimeDelay);

    }

    delay_us(TimeDelay);

}

/// @brief I2C发送地址

/// @param address : 7Bit地址

/// @param isRead : 0=Write;1=Read

void CI2C_Software::I2C_SendAddress(uint8_t address,uint8_t isRead){

    I2C_SendData((address << 1) | isRead);

}


 

/// @brief 从I2C读取一个字节

/// @param ack : 0=不应答,1=应答

uint8_t CI2C_Software::I2C_ReadDate(uint8_t ack) {

    uint8_t receive = 0;

    uint8_t mask = 0x80;

    PORT_SDA_I2C_SET_IN;

    for (uint8_t i = 0; i < 8; i++) {

        PORT_SCL_I2C_SET_0;

        delay_us(TimeDelay);

        PORT_SCL_I2C_SET_1;

        delay_us(TimeDelay);

        receive <<= 1;

        if (PORT_SDA_I2C_READ)  receive |= mask;

        mask  >>= 1;

        delay_us(TimeDelay);

    }

    if (ack==0)

        I2C_NAck();

    else

        I2C_Ack();

    delay_us(TimeDelay);

    return receive;

}

void CI2C_Software::I2C_Stop(){

    PORT_SDA_I2C_SET_OUT;

    PORT_SCL_I2C_SET_0;

    PORT_SDA_I2C_SET_0;

    delay_us(TimeDelay);

    PORT_SCL_I2C_SET_1;

    delay_us(TimeDelay);

    PORT_SDA_I2C_SET_1;

    delay_us(TimeDelay);

}

void CI2C_Software::I2C_Ack() {

    PORT_SCL_I2C_SET_0; //SCL拉低

    PORT_SDA_I2C_SET_OUT;

    PORT_SDA_I2C_SET_0;

    delay_us(TimeDelay);

    PORT_SCL_I2C_SET_1;

    delay_us(TimeDelay);

    PORT_SCL_I2C_SET_0;

    delay_us(TimeDelay);

}

void CI2C_Software::I2C_NAck() {

    PORT_SCL_I2C_SET_0;

    PORT_SDA_I2C_SET_OUT;

    PORT_SDA_I2C_SET_1;

    delay_us(TimeDelay);

    PORT_SCL_I2C_SET_1;

    delay_us(TimeDelay);

    PORT_SCL_I2C_SET_0;

}

/// @brief 等待数控电位器应答

/// @return 0=应答正常,0xFF=无应答

uint8_t CI2C_Software::I2C_WaitAck() {

    uint8_t ucErrtime = 0;

    PORT_SDA_I2C_SET_IN;

    delay_us(TimeDelay);

    PORT_SCL_I2C_SET_1;

    delay_us(TimeDelay);

    while (PORT_SDA_I2C_READ)

    {

        ucErrtime++;

        if (ucErrtime > 250) {

            I2C_Stop();

            return 0xFF;

        }

    }

    PORT_SCL_I2C_SET_0;

    return 0;

}

函数delay_us(TimeDelay);自己另行定义
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值