STMF4 硬件IIC(天空星开发板)

                                        前言:笔记参考立创开发文档,连接放在最后

#IIC概念介绍

#IIC介绍

        IIC通信协议,一种常见的串行通信协议,英文全程是 Inter-Integrated Circuit  使用这种通信方式的模块,通常有SCL(Serial Clock Line)  和SDA(Serial Date)两个引脚  ,也就是当看到这两个引脚也就知道,使用的IIC通信。        

        IIC通信分为硬件IIC通信   软件IIC通信,本篇介绍硬件IIC通信 ,想要了解软件IIC的可以看另一篇文章,IIC通信SDA数据线 高电平电压范围在 2.5V~5.5V  低电平范围 0V~0.3V 

#软件IIC介绍

        软件IIC指的是,通过GPIO引脚模拟IIC通信的波形时序,也就是控制引脚的电平变化来传输数据还有时序信号,达到IIC通信的效果目的,软件IIC通信好处是,在MCU内部没有集成硬件IIC电路的时候,可以使用软件IIC通信,只要MCU支持GPIO就能使用软件IIC通信

        软件IIC的性能相对于硬件IIC较低,通常使用在低速通信还有简单通信的情况下去使用。

#硬件IIC介绍

        硬件IIC指的是芯片内部集成的IIC硬件外设,硬件IIC效率远高于软件IIC, STMF4VET6上带有3个硬件IIC,允许与外部IIC接口进行通信,STMF4的硬件IIC使用特定的引脚复位,来进行数据和时钟信号的传输。

       硬件IIC的通信时序波形,是通过硬件电路还有寄存器来实现的,这些电路还有寄存器负责生成时钟,还有数据线电平变化,使其符合IIC通信协议的要求,这个就是IIC通信的硬件控制流程,具体可以参考下图硬件IIC的框图。

                        

        硬件IIC框图里面,可以发现硬件IIC,也支持中断 还有 DMA输出传输数据。

#配置硬件IIC相关流程

#硬件IIC发送流程

        软件初始化:硬件IIC的通信时序,由内部的寄存器 控制器,来负责所以首先要配置IIC控制器的参数,需要设置 IIC速率  地址模式    设备地址

        START设置:发送起始信号到IIC总线,设置硬件IIC控制器开始位来启动发送过程,通过标志位SBSEND判断起始信号是否发送完毕,发送完毕标志位(SBSEND)会置一。

        清除SBSEND:当起始信号发送完成,SBSEND这个标志位会被硬件置1,10位地址模式,需要清除标志位才能进行下一步,7位地址模式,该标志位不能清除。

        清除ADDSEND:如果地址为10位模式,要发送 地址高位地址低位,发送完成ADD10SEND 和 ADDSEND 会由硬件置1,这个时候需要清除 ADD10SEND 和 ADDSEND 如果地址为 7位模式则只需要发送一次地址,并等待ADDSEND硬件置1后,清除ADDSEND标志位。

        传输数据:为了防止数据溢出,需要判断发送寄存器的数据是否为空,也就是查询TBE标志位的值,当发送数据寄存器为空的时候,TBE寄存器会被硬件置1,主机接受从机应答信号,此时发送数据成功,BTC标志位会被硬件置1

        设置STOP:当数据发送完成,这个时候要停止IIC通信,设置STOP也就是发送停止信号。

#硬件IIC接收流程

        硬件IIC,接收数据跟发送数据过程大致相同, 设置START   清除SBSEND  清除ADDEND  读取字节数据  清除ACKEN   设置STOP 。下面只介绍不同的部分。

        在此设置START:这里其实信号发送之前,硬件IIC必须是空闲状态才能发送,负责没有办法进行下一步。

        读取数据字节:RBNE标志位,当接收数据寄存器中,如果有数据,会将RBNE自动硬件置1,这个时候通过读取标志位信息,停止发送信息,防止数据溢出。取出寄存器里面的数据之后,通过使能ACK应答位,硬件会自动发送,这个时候从机才会继续发送数据。

#软件IIC实验

            硬件IIC通常来说不为常用,一般通过软件IIC进行通信,也就是通过控制GPIO引脚电平,模拟IIC通信时序,电平。

#宏定义 IIC引脚  调用函数

       使用宏定义,去写代码,这种函数是能够提升程序的执行速度,因为宏定义是预处理指令,在程序执行前,开始执行的,如果是将函数在次封装在调用,这种程序执行速度是比不上,宏定义函数,宏定义常量的。

#define RCU_SCL          RCC_AHB1Periph_GPIOB
#define PORT_SCL         GPIOB
#define GPIO_SCL         GPIO_Pin_6

#define RCU_SDA          RCC_AHB1Periph_GPIOB
#define PORT_SDA         GPIOB
#define GPIO_SDA         GPIO_Pin_7


#define SDA_IN()  {SHT20_MODE_SET( GPIO_Mode_IN  );}  //SDA输入模式
#define SDA_OUT() {SHT20_MODE_SET( GPIO_Mode_OUT );}  //SDA输出模式

#define SCL(BIT)  GPIO_WriteBit(PORT_SCL, GPIO_SCL, BIT)
#define SDA(BIT)  GPIO_WriteBit(PORT_SDA, GPIO_SDA, BIT)
#define SDA_GET() GPIO_ReadInputDataBit(PORT_SDA, GPIO_SDA)
void SHT20_GPIO_INIT(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_SCL;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(PORT_SCL, &GPIO_InitStructure);
        
        GPIO_InitStructure.GPIO_Pin = GPIO_SDA;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(PORT_SDA, &GPIO_InitStructure);
}

        这里使用了宏定义常量 重定义了函数,同时初始化了 GPIO 引脚 用它作为 IIC通信数据线。

#配置IIC通信时序

void IIC_Start(void)
{
        SDA_OUT();
        
        SCL(0);
        SDA(1);
        SCL(1);
        
        delay_us(5);
        
        SDA(0);
        delay_us(5);
        SCL(0);
        delay_us(5);
        
        
}
void IIC_Stop(void)
{
        SDA_OUT();
        
        SCL(0);
        SDA(0);
        
        SCL(1);
        delay_us(5);
        SDA(1);
        delay_us(5);
        
}
void IIC_Send_Ack(uint8_t ack)
{
        SDA_OUT();
        SCL(0);
        SDA(0);
        delay_us(5);
        if(!ack) SDA(0);
        else         SDA(1);
        SCL(1);
        delay_us(5);
        SCL(0);
        SDA(1);
}
uint8_t IIC_Wait_Ack(void)
{
        char ack = 0;
        unsigned char ack_flag = 10;
        SDA_IN();
    SDA(1);
        delay_us(5);
        SCL(1);
        delay_us(5);
        while( (SDA_GET()==1) && ( ack_flag ) )
        {
                ack_flag--;
                delay_us(5);
        }
        
        if( ack_flag <= 0 )
        {
                IIC_Stop();
                return 1;
        }
        else
        {
                SCL(0);
                SDA_OUT();
        }
        return ack;
}
void IIC_Write(uint8_t data)
{
        int i = 0;
        SDA_OUT();
        SCL(0);//拉低时钟开始数据传输
        
        for( i = 0; i < 8; i++ )
        {
                SDA( (data & 0x80) >> 7 );
                delay_us(2);
        data<<=1;
        delay_us(6); 
                SCL(1);
                delay_us(4);
                SCL(0);
                delay_us(4);
                
        }
}

uint8_t IIC_Read(void)
{
        unsigned char i,receive=0;
    SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
        {
        SCL(0);
        delay_us(5);
        SCL(1);
        delay_us(5);
        receive<<=1;
        if( SDA_GET() )
        {        
            receive|=1;   
        }
        delay_us(5); 
    }                
  return receive;
}

        上面配置了IIC通信时序,接下来,根据温度湿度公式,计算实际温度还是湿度定义函数输出即可。

#配置温度湿度函数

float SHT20_Read(uint8_t regaddr)
{        
    unsigned char data_H = 0;
    unsigned char data_L = 0;
    float temp = 0;
    IIC_Start();
    IIC_Write(0x80|0);
    if( IIC_Wait_Ack() == 1 ) printf("error -1\r\n");
    IIC_Write(regaddr);
    if( IIC_Wait_Ack() == 1 ) printf("error -2\r\n");
       
    do{
    delay_us(10);
    IIC_Start();
    IIC_Write(0x80|1);
    
    }while( IIC_Wait_Ack() == 1 );

    delay_us(20);
    
    data_H = IIC_Read();
    IIC_Send_Ack(0);
    data_L = IIC_Read();
    IIC_Send_Ack(1);
    IIC_Stop();
    
    if( regaddr == 0xf3 )
    {
        temp = ((data_H<<8)|data_L) / 65536.0 * 175.72 - 46.85;
    }
    if( regaddr == 0xf5 )
    {
        temp = ((data_H<<8)|data_L) / 65536.0 * 125.0 - 6;
    }
   return temp;

}
int main(void)
{    
    board_init();
    uart1_init(115200U);
    
    //引脚初始化
    SHT20_GPIO_INIT();
    
    //等待传感器上电初始化完成
    delay_ms(20);
    
    while(1)
    {
        //采集温度
        printf("temp = %.2f\r\n", SHT20_Read(0xf3) );
        //采集湿度
        printf("humi = %.2f\r\n", SHT20_Read(0xf5) );
        printf("\r\n");
        delay_ms(500);
    }
}

 ⁠​‬​‍​‍‬​‍‌‍⁠​​‬‌‬​‬​‍‌​‬​⁠‍‌‌​​‍​​​​​‬​‌⁠​                  【立创·天空星STM32F407VET6】入门手册 - 飞书云文档 (feishu.cn)

                                     欢迎指正,希望对你,有所帮助!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/778609.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL-DCL(三)

一.DCL介绍 DCL英文全称是Data Control Language(数据库控制语言),用来管理数据库 用户,控制数据库的访问权限。 二.两个方面 1.数据库可以由那些用户访问 2.可以访问那些内容 三.DCL-管理用户 1.查询用户 USE mysql SELECT * FROM user 2.创建用户 CREATE USER…

Redis---10---SpringBoot集成Redis

SpringBoot集成Redis 总体概述jedis-lettuce-RedisTemplate三者的联系 本地Java连接Redis常见问题&#xff0c;注意 bind配置请注释掉​ 保护模式设置为no​ Linux系统的防火墙设置​ redis服务器的IP地址和密码是否正确​ 忘记写访问redis的服务端口号和auth密码集成Jedis …

HTML(26)——平面转换-旋转-多重转换-缩放

旋转 属性&#xff1a;transform:rotate(旋转角度) 角度的单位是deg。 取值为正&#xff0c;顺时针旋转取值为负&#xff0c;逆时针旋转 默认情况下&#xff0c;旋转的原点是盒子中心点 改变旋转的原点可以使用属性:transform-origin:水平原点位置 垂直原点位置 取值&a…

Vue表单输入绑定v-model

表单输入绑定 在前端处理表单时&#xff0c;我们常常需要将表单输入框的内容同步给Javascript中相应的变量。手动连接绑定和更改事件监听器可能会很麻&#xff0c;v-model 指令帮我们简化了这一步骤。 <template><h3>表单输入绑定</h3><hr> <inpu…

【分布式系统】ELK 企业级日志分析系统

目录 一.ELK概述 1.简介 1.1.可以添加的其他组件 1.2.filebeat 结合 logstash 带来好处 2.为什么使用ELK 3.完整日志系统基本特征 4.工作原理 二.部署ELK日志分析系统 1.初始化环境 2.完成JAVA部署 三. ELK Elasticsearch 集群部署 1.安装 2.修改配置文件 3.es 性…

OpenAI突然停止中国API使用,出海SaaS产品如何化挑战为机遇?

2023年是AI爆发的年代&#xff0c;人工智能带来的信息裂变刷新了整个SaaS行业。在这个AI引领的时代&#xff0c;我们不应该单纯依赖工具本身&#xff0c;而是要理解如何将这些AI功能与行业相结合。 然而&#xff0c;上周OpenAI宣布禁止对中国提供API服务&#xff0c;有一些用户…

【单片机毕业设计选题24047】-基于阿里云的工地环境监测系统

系统功能: 基于STM32完成 主机&#xff08;阿里云以及oled屏显示位置一&#xff09;&#xff1a;烟雾检测&#xff0c;温湿度检测&#xff0c;噪声检测&#xff0c;且用OLED屏显示&#xff0c;设置阈值&#xff0c;超过报警&#xff08;蜂鸣器&#xff09;。 从机&#xff0…

假阳性和假阴性、真阳性和真阴性

在深度学习的分类问题中&#xff0c;真阳性、真阴性、假阳性和假阴性是评估模型性能的重要指标。它们的定义和计算如下&#xff1a; 真阳性&#xff08;True Positive, TP&#xff09;&#xff1a; 定义&#xff1a;模型预测为正类&#xff08;阳性&#xff09;&#xff0c;且实…

【matlab】分类回归——智能优化算法优化径向基神经网络

目录 径向基&#xff08;Radial Basis Function, RBF&#xff09;神经网络 一、基本概念 二、网络结构 三、工作原理 四、学习算法 五、优点与应用 六、与BP神经网络的比较 智能优化算法 常见的智能优化算法 灰狼优化算法&#xff08;Grey Wolf Optimizer, GWO&#…

基于工业互联网的智慧矿山解决方案PPT(38页)

文章摘要 工业互联网与智慧矿山 基于工业互联网的新一代智慧矿山解决方案&#xff0c;将互联网和新一代IT技术与工业系统深度融合&#xff0c;形成关键的产业和应用生态&#xff0c;推动工业智能化发展。该方案以“四级、三层、两网、一平台”为总体框架&#xff0c;强调应用目…

Lambda架构

1.Lambda架构对大数据处理系统的理解 Lambda架构由Storm的作者Nathan Marz提出&#xff0c;其设计目的在于提供一个能满足大数据系统关键特性的架构&#xff0c;包括高容错、低延迟、可扩展等。其整合离线计算与实时计算&#xff0c;融合不可变性、读写分离和复杂性隔离等原则&…

MySQL基础篇(二)字符集以及校验规则

在MySQL基础篇&#xff08;一&#xff09;中&#xff0c;我们知道了如何创建数据库&#xff0c;这篇文章带大家了解创建的一些细节。 红色框&#xff1a;可省略&#xff0c;作用如果存在相同的数据库名称&#xff0c;就不会再创建&#xff0c;反之&#xff0c;创建。 蓝色框&…

#数据结构 链式栈

1. 概念 链式栈LinkStack 逻辑结构&#xff1a;线性结构物理结构&#xff1a;链式存储栈的特点&#xff1a;后进先出 栈具有后进先出的特点&#xff0c;我们使用链表来实现栈&#xff0c;即链式栈。那么栈顶是入栈和出栈的地方&#xff0c;单向链表有头有尾&#xff0c;那我…

Java + MySQL 实现存储完整 Json

Java MySQL 实现存储完整 Json 一、应用场景二、数据库配置三、后端代码配置1、maven 依赖2、实体类3、Service 实现类4、xml 文件 四、测试1、新增接口2、查询接口3、数据表内容 一、应用场景 将前端传过来的 Json 完整存储到 MySQL 中&#xff0c;涉及技术栈为 Java、MyBat…

Git中两个开发分支merge的原理

一 分支合并 1.1 原理 分支合并&#xff1a;就是将A分支修改后且commit的内容&#xff0c;合并到B分支&#xff0c;这些修改且提交的内容和B分支对应的内容和位置进行比较&#xff1a; 1.不一样的话&#xff0c;提示冲突&#xff0c;需要人工干预。 2.一样的话&#xff0c;…

python读取csv出错怎么解决

Python用pandas的read_csv函数读取csv文件。 首先&#xff0c;导入pandas包后&#xff0c;直接用read_csv函数读取报错OSError&#xff0c;如下&#xff1a; 解决方案是加上参数&#xff1a;enginepython。 运行之后没有报错&#xff0c;正在我欣喜之余&#xff0c;输出一下d…

LT8712 支持USB Type-C的DP到HDMI/VGA 用于对接站 适配器

描述 LT8712是一个DisplayPort(DP)到HDMI和VGA转换器&#xff0c;设计用于同时连接一个DP源到一个VGA收发器和最多两个HDMI收发器。LT8712集成了一个DP1.2兼容的接收器、一个高速三通道视频DAC和两个HDMI1.4兼容的发射器(发射器0和发射器1)。接收端口集成了CC控制器&#xff0c…

『古籍自有答案』古风H5案例赏析

「古籍自有答案」&#xff0c;一部由新京报与字节跳动公益联合打造的古风H5&#xff0c;以诗意盎然的开篇引领用户穿梭于千年文脉。 part1. 创意定位 "人生有惑问先贤&#xff0c;先贤答案存古籍"&#xff0c;在这里&#xff0c;每一个灵魂的探问&#xff0c;都能在…

ElasticSearch 如何计算得分及一个不太成熟的使用

1.背景 最近在做 ES 相关东西&#xff0c;只最会在查询的时候给不同的字段设置不同的权重&#xff0c;但是得分具体怎么算的不太明白&#xff0c;花了4-5 天研究和总结了一下。这样不至于被别人问到“这个分数怎么算出来的&#xff1f;”&#xff0c;两眼一抹黑&#xff0c;不…

前端面试题19(vue性能优化)

Vue.js应用的性能优化是一个多方面的过程&#xff0c;涉及初始化加载、运行时渲染以及用户交互等多个环节。以下是一些关键的Vue性能优化策略&#xff0c;包括详细的说明和示例代码&#xff1a; 1. 懒加载组件 对于大型应用&#xff0c;可以使用懒加载来减少初始加载时间。Vu…