STM32Cube MX 下IIC的配置与使用

发布者:brian808090最新更新时间:2018-11-26 来源: eefocus关键字:STM32Cube  MX  IIC  配置与使用 手机看文章 扫描二维码
随时随地手机看文章

本文介绍了在STM32下的IIC的基本使用方法,通过对板载具备IIC接口EEPROM的读写,完成对IIC驱动程序的测试。


硬件平台:STM32F107VCT6开发板


软件平台:STM32Cube MX + MDK5.22


1. 进行STM32Cube MX的配置



配置PB6和PB7为输出模式,同时配置了USART1进行串口调试使用。然后生成工程。


2. 打开工程,可以看到GPIO的初始化状态



3. 模拟IIC驱动程序源文件代码


/**


  * @file  iic_dup.c


  * @brief IIC上层程序


  * @par   date        version    author    remarks


  *        2016-03-21  v1.0       zbt       初次创建


  *


  */

 


/** 头文件包含区 ------------------------------------------------ */


#include "iic_dup.h"


 

/** 私有宏(类型定义) -------------------------------------------- */ 


#define IIC1_SCL(pin_status)        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, pin_status);


#define IIC1_SDA(pin_status)        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, pin_status);


#define IIC1_SCL_IS_HIGH()          (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_RESET)


#define IIC1_SDA_IS_HIGH()          (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_RESET)

 

/** 私有变量 --------------------------------------------------- */

 

 

/** 外部变量 --------------------------------------------------- */

 

/** 私有函数原型 ----------------------------------------------- */


static void iic_delay(void);

 

/** 公有函数 --------------------------------------------------- */


/**


  * @brief  IIC启动


  * @param  None


  * @retval None


  * @note   当SCL处于高电平状态时,SDA出现一个下降沿


            即产生IIC启动信号


  */


void iic_start(void)


{

   

IIC1_SCL(GPIO_PIN_SET);


    /** SDA产生一个下降沿 */


    IIC1_SDA(GPIO_PIN_SET);


    iic_delay(); 

    

    IIC1_SDA(GPIO_PIN_RESET);


    iic_delay(); 


    IIC1_SCL(GPIO_PIN_RESET);   /**< 拉低准备发送数据 */


    iic_delay();   


}

 


/**


  * @brief  IIC停止


  * @param  None


  * @retval None


  * @note   当SCL处于高电平状态时,SDA出现一个上升沿


            即产生IIC停止信号


  */


void iic_stop(void)


{


    IIC1_SCL(GPIO_PIN_RESET);


    iic_delay();


    /** SDA产生一个上升沿 */


    IIC1_SDA(GPIO_PIN_RESET);


    iic_delay();

    

    IIC1_SCL(GPIO_PIN_SET);


    iic_delay();


    IIC1_SDA(GPIO_PIN_SET);


    iic_delay();


}

 

/**


  * @brief  IIC发送1byte数据


  * @param  None


  * @retval None


  * @note   


  */


void iic_sendbyte(uint8_t byte)


{


    uint8_t i;

    

    /** 发送一个字节的高7位 */

  

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


    {


        if (byte & 0x80)


        {


            IIC1_SDA(GPIO_PIN_SET);


        }


        else


        {


            IIC1_SDA(GPIO_PIN_RESET);


        }


        

        iic_delay();


        IIC1_SCL(GPIO_PIN_SET);


        iic_delay();


        IIC1_SCL(GPIO_PIN_RESET)


        if (i == 7)


        {


            IIC1_SDA(GPIO_PIN_SET);


        }

        

        byte <<= 1;


        iic_delay();


    }      


}

 

/**


  * @brief  IIC读取1byte数据


  * @param  None


  * @retval None


  * @note             


  */


uint8_t iic_readbyte(void)


{


    uint8_t i;


    uint8_t recv_value = 0;

    

    IIC1_SDA(GPIO_PIN_SET);


    iic_delay();

    


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


    {


        IIC1_SCL(GPIO_PIN_SET);


        iic_delay();


        recv_value <<= 1;


        if (IIC1_SDA_IS_HIGH())


        {


            recv_value |= 0x01;


        }


        else


        {


            recv_value &= ~0x01;


        }

        

        iic_delay();


        IIC1_SCL(GPIO_PIN_RESET);


    }

    


    return recv_value;


}

 

/**


  * @brief  IIC等待应答信号


  * @param  None


  * @retval ack_status: 应答状态,0表示应答,1表示设备无响应


  */


uint8_t iic_wait_ack(void)


{


    uint8_t ack_status = 0;

    


    /** 在等待应答信号之前,要释放总线,即将SDA置位 */


    IIC1_SDA(GPIO_PIN_SET);


    iic_delay();


    IIC1_SCL(GPIO_PIN_SET);


    iic_delay();

    

    if (IIC1_SDA_IS_HIGH())


    {    


        ack_status = 1;


        iic_stop();


    }


    else


    {


        ack_status = 0;


    }

    

    IIC1_SCL(GPIO_PIN_RESET);


    iic_delay();

    

    return ack_status;


}

 

/**


  * @brief  主机(主控制器)产生应答信号


  * @param  None


  * @retval None


  */


void iic_ack(void)


{


    IIC1_SDA(GPIO_PIN_RESET);


    iic_delay();

    

    IIC1_SCL(GPIO_PIN_SET);


    iic_delay();


    IIC1_SCL(GPIO_PIN_RESET);


    iic_delay();

    

    IIC1_SDA(GPIO_PIN_SET);


}

 

/**


  * @brief  主机(主控制器)产生不应答信号


  * @param  None


  * @retval None


  */


void iic_nack(void)


{


    IIC1_SDA(GPIO_PIN_SET);


    iic_delay();

    

    IIC1_SCL(GPIO_PIN_SET);


    iic_delay();


    IIC1_SCL(GPIO_PIN_RESET);


    iic_delay();


}

 

/**


  * @brief  检测IIC总线上的设备状态


  * @param  device_addr: 从机设备地址 


  * @retval ack_status: 0 (正常)or 1(异常)


  * @note   主机发送设备地址等待从机应答,若有从机正确的应答信号


            则表明IIC总线上挂接了设备,否则表示IIC总线上未检测到


            设备


  */


uint8_t iic_check_device_status(uint8_t device_addr)


{


    uint8_t ack_status;

    

    if (IIC1_SCL_IS_HIGH() && IIC1_SDA_IS_HIGH())


    {


        iic_start();

        

        iic_sendbyte(device_addr | IIC_WRITE);


        ack_status = iic_wait_ack();

 

        iic_stop();

        

        return ack_status;    


}

    

    return 1;


}

 

/** 私有函数 --------------------------------------------------- */


/**


  * @brief  用于模拟IIC时的简单延时


  * @param  None


  * @retval None


  */


static void iic_delay(void)


{


    uint8_t i = 0;


    uint8_t delay = 5;

    

    while (delay--)


    {


        i = 10;


        while (i--);


    }


}


4. AT24C02部分驱动代码


/**


  * @file  at24c02.c


  * @brief at24c02驱动程序


  * @par   date        version    author    remarks


  *        2016-03-21  v1.0       zbt       初次创建


  *


  */

 

/** 头文件包含区 ------------------------------------------------ */


#include "at24c02.h"


#include "iic_dup.h"

 

/** 私有宏(类型定义) -------------------------------------------- */ 


#define AT24C02_DEVICE_ADDR         0xA0


#define AT24C02_PAGE_SIZE           8


#define AT24C02_MEM_SIZE            256


#define AT24C02_ADDR_BYTE           1

 

/** 私有变量 --------------------------------------------------- */


uint8_t test_buffer[AT24C02_MEM_SIZE];

 

/** 外部变量 --------------------------------------------------- */

 

/** 私有函数原型 ----------------------------------------------- */


//static void AT24C02_ack(void);


static void AT24C02_error_handle(void);


static void AT24C02_read_test(void);


static void AT24C02_write_test(void);


static void AT24C02_erase_test(void);

 

/** 公有函数 --------------------------------------------------- */


/**


  * @brief  AT24C02与主控制器的IIC通讯测试代码


  * @param  None


  * @retval None


  */


void AT24C02_iic_test(void)


{


    iic_stop();     /**< 必须先复位IIC总线上的设备到待机模式 */


    HAL_Delay(10);

    

    /** 检测总线上是否挂接了IIC设备(此处为AT24C02) */


    if (iic_check_device_status(AT24C02_DEVICE_ADDR) == 0)


    {


        printf("iic device exists\n");


    }


    else


    {


        printf("no iic device exists\n");


    }

    

    AT24C02_write_test();


    HAL_Delay(5);


    AT24C02_read_test();


    HAL_Delay(5);


    AT24C02_erase_test();


}

 

/**


  * @brief  从AT24C02中读取数据


  * @param  read_data: 读取到的数据


  * @param  start_addr: 读取数据的起始地址


  * @param  data_length: 数据的长度


  * @retval None


  */


void AT24C02_read_data(uint8_t *read_data, uint16_t start_addr, uint16_t data_length)


{


    uint16_t i;

    

    iic_start();


    iic_sendbyte(AT24C02_DEVICE_ADDR | IIC_WRITE);


//    AT24C02_ack();


    if (iic_wait_ack() != 0)


    {


        AT24C02_error_handle();


        printf("first read error\r\n");


    }

    

    if (AT24C02_ADDR_BYTE == 1)

 

   {


        iic_sendbyte((uint8_t)start_addr & 0xff);


//        AT24C02_ack();


        if (iic_wait_ack() != 0)


        {


            AT24C02_error_handle();


            printf("addr byte error\r\n");


        }

    }

    

    iic_start();


    iic_sendbyte(AT24C02_DEVICE_ADDR | IIC_READ);


//    AT24C02_ack();


    if (iic_wait_ack() != 0)

   

{

 

       AT24C02_error_handle();


        printf("read data error\r\n");


    }


     for (i = 0; i < data_length; i++)

    

{


        read_data[i] = iic_readbyte();

        

        if (i != data_length - 1)


        {


            iic_ack();      /**< 读完非最后一个字节后, 产生应答信号 */


        }


        else


        {


            iic_nack();     /**< 最后一个字节读完后 产生非应答信号 */


        }


//        printf("read data is %d\n", read_data[i]);  /**< 调试代码 */


    }

iic_stop();


}

 

/**


  * @brief  通过IIC向AT24C02写数据


  * @param  write_data:  要写入AT24C02的数据指针


  * @param  start_addr:  要写入AT24C02的起始地址


  * @param  data_length: 要写入AT24C02的数据长度


 * @retval None


 */


void AT24C02_write_data(uint8_t *write_data, uint16_t start_addr, uint16_t data_length)


{


    uint16_t i, j;


    uint16_t start_addr_dup;

    

    start_addr_dup = start_addr;


    for (i = 0; i < data_length; i++)


    {

        

        if ((i == 0) || (start_addr_dup & (AT24C02_PAGE_SIZE - 1)) == 0)


        {


            iic_stop();

            

            for (j = 0; j < 2000; j++)

       

     {


                iic_start();

         

       iic_sendbyte(AT24C02_DEVICE_ADDR | IIC_WRITE);

                

                if (iic_wait_ack() == 0)

       

         {

   

                 break;


                }


            }


            if (j >= 2000)


            {


                printf("j = 1000\r\n");


                AT24C02_error_handle();


            }

            

            if (AT24C02_ADDR_BYTE == 1)


            {


                iic_sendbyte((uint8_t)start_addr_dup & 0xff);


//                AT24C02_ack();


                if (iic_wait_ack() != 0)


                {


                    AT24C02_error_handle();


                    printf("addr_byte wrong\r\n");


                }


            }


        }

        

        iic_sendbyte(write_data[i]);


//        AT24C02_ack();


        if (iic_wait_ack() != 0)


        {


            AT24C02_error_handle();


            printf("write failed\r\n");


        }

        

//        printf("write_data is %d \n", write_data[i]);    /**< 调试代码 */ 


        start_addr_dup++;


    }

    

    iic_stop();


}

 

/** 私有函数 --------------------------------------------------- */


/** 以下为测试用程序 ------------------------------------------- */


/**


  * @brief  AT24C02读取数据测试


  * @param  None


  * @retval None


  */


static void AT24C02_read_test(void)


{


    uint16_t i;

    

    AT24C02_read_data(test_buffer, 0, (AT24C02_MEM_SIZE % 10));

    

    printf("read data is:\n");


    for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++)


    {


        printf("%d ", test_buffer[i]);


    }

    

    printf("\r\nread test ok\r\n");


}

 

/**


  * @brief  AT24C02写数据测试


  * @param  None


  * @retval None


  */

static void AT24C02_write_test(void)

{

    uint16_t i;

    

    for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++)

    {

        test_buffer[i] = i;

    }

    

    AT24C02_write_data(test_buffer, 0, (AT24C02_MEM_SIZE % 10));

    

    printf("write data is:\n");


    for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++)


    {


        printf("%d ", test_buffer[i]);


    }

    

    printf("\r\nwrite test ok\r\n");


}

 

/**

  * @brief  AT24C02擦除数据测试


  * @param  None


  * @retval None


  */


static void AT24C02_erase_test(void)


{


    uint16_t i;

    

    for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++)


    {


        test_buffer[i] = 0xff;


    }

    

    AT24C02_write_data(test_buffer, 0, (AT24C02_MEM_SIZE % 10));

    

    printf("erase value is: \n");


    for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++)


    {


        printf("%d ", test_buffer[i]);


    }

    

    printf("\r\nerase test ok\r\n");


}


/** 以上为测试用程序 ------------------------------------------- */

 

/**


  * @brief  AT24C02应答错误处理程序


  * @param  None


  * @retval None


  */


static void AT24C02_error_handle(void)


{


    iic_stop();


//    printf("At24C02 read failed\r\n");   /**< 调试用 */


}

 

//static void AT24C02_ack(void)


//{


//    if (iic_wait_ack() != 0)


//    {


//        AT24C02_error_handle();


//    }


//}


5. 在主函数中添加 AT24C02_iic_test(); 进行读写测试成功。

关键字:STM32Cube  MX  IIC  配置与使用 引用地址:STM32Cube MX 下IIC的配置与使用

上一篇:STM32 硬件I2C中断实现
下一篇:LPC1114时钟学习

推荐阅读最新更新时间:2024-03-16 16:18

MSP430 G2553 硬件IIC OLED 单片机 OLED滚动显示
效果: 总结: (1)网上没好用的源码; (2)SSD1306地址是0X3C,7位地址模式。 (3)G2553手册确实介绍得很好。 (4)SSD1306写入命令顺序:开始信号– 等待UCB0TXIFG– 写入0X3C地址– 等待UCB0TXIFG- 写入0X00控制字– 等待UCB0TXIFG– 写入命令字符– 等待UCB0TXIFG– 发送停止信号。 (5)SSD1306写入数据顺序:开始信号– 等待UCB0TXIFG– 写入0X3C地址– 等待UCB0TXIFG- 写入0X40控制字– 等待UCB0TXIFG– 写入数据字符– 等待UCB0TXIFG– 发送停止信号。 (6)USCI模块支持的东西不一样: IIC通信的
[单片机]
MSP430 G2553 硬件<font color='red'>IIC</font> OLED 单片机 OLED滚动显示
STM32F103模拟IIC
在用STM32F103模拟IIC时,SDA的配置很有意思,既要读数据,又要写数据,这两者之间的切换通过GPIO的配置寄存器来实现。 #define SDA_IN() {GPIOB- CRL&=0X0FFFFFFF;GPIOB- CRL|=8 28;} #define SDA_OUT() {GPIOB- CRL&=0X0FFFFFFF;GPIOB- CRL|=3 28;} 就是这两句话,GPIO配置寄存器分为端口配置低寄存器(GPIOx_CRL) (x=A..E)和端口配置高寄存器(GPIOx_CRH) (x=A..E);在这里用到的是PB7模拟IIC的SDA,所以切换配置时,先将原配置清零,GPIOB- CRL&=0X0FFFFF
[单片机]
STM32F103模拟<font color='red'>IIC</font>
飞思卡尔推出业界能效最高的Cortex-A7 GHz级i.MX 7应用处理器
功能丰富的多核处理器采用i.MX 6系列三分之一的功耗实现了卓越的性能;深度暂停模式支持仅消耗250 W,即可实现丰富的操作系统待机功能 飞思卡尔在2015年飞思卡尔技术论坛中推出了i.MX 7系列应用处理器,此系列产品基于其成功和广泛部署的 i.MX平台,是新一代节能和功能全面的应用处理器。i.MX 7系列实现了15.7 DMIPS/mW的世界级内核功效,仅消耗250 W,即可进入全新低功耗状态保留模式(LPSR) ,也是业界首款采用ARM Cortex-A7和ARM Cortex-M4内核的通用微处理器系列。 这些技术结合飞思卡尔的全新PF3000 PMIC配套产品,为可穿戴计算和物联网时代释放创新、安全和节能
[嵌入式]
MX 8X处理器
恩智浦半导体(NXP)宣布推出全新i. MX 8X系列,进一步扩大i. MX 8系列应用处理器的可扩展范围。 此系列沿用了高端i. MX 8系列的通用子系统和架构,有多种针脚兼容(Pin-compatible)版本可供选择,同时最大程度地实现软件的重复使用,因此能提供非常出色且极具成本效益的选择。 恩智浦i. MX应用处理器产品部门总经理暨副总裁Ronald Martino表示,全新的多功能i. MX 8X和i.MX 8系列处理器为创新工业和汽车应用,提供了出色兼具可扩展性并值得信赖的解决方案。 无论是飞机驾驶舱、机上娱乐显示器,还是汽车仪表板和工业设备,要想在空中、路上或生产中获得流畅、不间断且安全的体验,系统可靠性至关重要。
[半导体设计/制造]
IIC:技术创新不遗余力,意法半导体展示两个“第一”
领先半导体厂商在技术创新方面可谓不遗余力。意法半导体这次在本届国际集成电路展(2006 IIC)上除了正式在中国市场正式推介其核心的Nomadik应用处理器,还同台展示了另外两个号称全球第一的针对便携式应用的新产品。 其一是世界上第一颗OTG+HIGH SPEED的USB-OTG控制芯片STW8100,集成电源控制功能,可实现480Mbps的high speed传输速度,并向下兼容12Mbps的full speed传输速度和1.5Mbps的low speed传输。易于集成到便携式电子产品,占位面积仅为5×5×1.2mm。据该公司技术市场工程师谈俊介绍,此前市面上的USB-OTG控制芯片要么是OTG+FULL SPEED,要么是单
[焦点新闻]
魅族确定9月2日召开发布会 MX4或现身
魅族或于9月2日发布MX4手机 新浪手机讯 8月18日上午消息,魅族科技今日在其官网微博宣布将于9月2日发布手机新品。根据邀请函,这次应该是魅族年度旗舰手机MX4发布。   在魅族科技的微博上,邀请函上最明显的部分是一个数字"4"新浪手机推测这个数字应该有多种含义,包括MX 4手机,Flyme 4.0系统,魅族首款4G手机等。发布会时间是9月2日下午14点30,位于国家体育馆副馆。   近期不断有网友曝光MX4相关消息,综合传闻,这款新机拥有黑、白两种颜色,机边框相较于前作MX3更窄,正上方的感应器布局有所改变,正下方的HOME延续了MX3圆圈设计。(杨肃观)
[手机便携]
魅族MX4 Pro发布或将延期
   打算等在10月入手魅族 MX 4 Pro的“煤油”们可能要有些小失望了。依照行业人士微博消息称,旗舰版魅族 MX 4 Pro的正式发布时间会有所延期,如果着急入手新机的“煤油”们,还是建议先入手MX4吧。   关于MX4 Pro配置有消息称,MX4 Pro或将配备5.4英寸2560×1536分辨率显示屏,搭载 三星 八核 处理器 (Exynos 5430),并支持Hi-Fi音效,还提供按压式指纹识别方案。售价方面或可能达到2499元。  此前,魅族在MX4发布会上称,由于技术层的原因,MX4 Pro的发布日期将会推迟到10月。看来,相等着买MX4 Pro的“煤油”们还需要更大的耐心才行。
[手机便携]
MSP430F249 IIC write and Uart send
//******************************************************************************/ #include msp430.h //注意:两次发送间隔必须要有延时,否则不能再次发送,串口发送格式: unsigned char PTxData ; // Pointer to TX data unsigned char pHead; unsigned char pTail; unsigned char TXByteCtr; const unsigned char TxData = // Table of data to tra
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved