HAL库软件IIC读取AT24C02/AT24C32

您所在的位置:网站首页 通讯地址写什么比较好 HAL库软件IIC读取AT24C02/AT24C32

HAL库软件IIC读取AT24C02/AT24C32

2024-07-17 15:28| 来源: 网络整理| 查看: 265

    为了克服硬件IIC的缺点以及更好了了解IIC协议,下面让我来介绍一下HAL库环境下的软件IIC如何使用。

硬件:stm32f103RCT6、AT24C02

软件:cubemx、keil5、野火上位机

我们把程序分为三部分,第一部分是延时函数和软件IIC函数;第二部分是AT24C02读写函数;第三部分是main()测试函数。

delay函数:

delay.c: #include "stm32f1xx_hal.h" #include "delay.h" void Delay_Us(uint16_t us){ SysTick->LOAD = us*72; //运行频率为72MHZ就乘72,因为一个systick为 (1/运行频率)秒 SysTick->VAL = 0x00; SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; while(!(SysTick->CTRL&SysTick_CTRL_COUNTFLAG_Msk)); SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk; } void Delay_Ms(uint16_t ms){ while(ms--){ Delay_Us(1000); } } delay.h: 头文件 #ifndef DELAY_H #define DELAY_H #include "stdint.h" void Delay_Us(uint16_t us); void Delay_Ms(uint16_t ms); #endif

软件IIC函数:

SCL我们选择推挽输出+上拉,默认输出高电平;

SDA我们选择开漏输出+上拉,默认输出高电平;因为SDA线既要用作输出,也要用作输入(从机应答信号),使用开漏模式则可以解决这个问题。当然我们也可以使SDA为推挽输出模式,但是这样每次SDA输出和输入模式转变时都需要重新初始化SDA的GPIO口,比较麻烦。

Sotf_IIC.c: #include "Soft_IIC.h" #include "delay.h" /* iic起始信号,当SCL为高电平时,SDA从高电平变为低电平*/ void iic_start(void) { /* 保持时钟线高电平,数据线产生下降沿 */ IIC_SDA_H(); IIC_SCL_H(); iic_delay(); IIC_SDA_L(); iic_delay(); /* 拉低时钟线,准备发送/接收数据 ,此时SCL和SDA都为低电平*/ IIC_SCL_L(); iic_delay(); } /* iic停止信号,当SCL为高电平时,SDA从低电平变为高电平 */ void iic_stop(void) { /* 保持时钟线高电平,数据线产生上升沿 */ IIC_SDA_L(); IIC_SCL_H(); iic_delay(); IIC_SDA_H(); iic_delay(); //停止信号发送后传输结束,SDA和SCL都为高电平 } /* 等待应答信号 */ /* return 0:fail 1:succeed*/ uint8_t iic_wait_ack (void) { IIC_SDA_H(); /* 主机释放SDA线 */ iic_delay(); IIC_SCL_H(); /* 拉高SCL等待读取从机应答信号 */ iic_delay(); if (IIC_READ_SDA) /* SCL高电平读取SDA状态 */ { iic_stop(); /* SDA高电平表示从机非应答 */ return 0; } /* SDA低电平表示从机应答 */ IIC_SCL_L(); /* SCL低电平表示结束应答检查 */ iic_delay(); return 1; } /* 应答信号 */ void iic_ack(void) { IIC_SDA_L(); //拉低SDA IIC_SCL_H(); //拉高SCL iic_delay(); IIC_SCL_L(); //拉低SCL IIC_SDA_H(); //拉高SDA,释放SDA线 iic_delay(); } /* 非应答信号 */ void iic_nack(void) { IIC_SCL_L(); iic_delay(); IIC_SDA_H(); /* 数据线为高电平,表示非应答 */ iic_delay(); IIC_SCL_H(); iic_delay(); IIC_SCL_L(); } /* 发送一个字节数据 */ void iic_send_byte(uint8_t data) { for (uint8_t t=0; t> 7); iic_delay(); /* 拉高时钟线,稳定数据接收 */ IIC_SCL_H(); iic_delay(); IIC_SCL_L(); data


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3