STM32 HAL库F103系列之IIC实验

IIC总线协议

IIC总线协议介绍

IICInter Integrated Circuit,集成电路总线,是一种同步 串行 半双工通信总线。

总线就是传输数据通道

协议就是传输数据的规则

IIC总线结构图

① 由时钟线SCL和数据线SDA组成,并且都接上拉电阻,确保总线空闲状态为高电平

② 总线支持多设备连接,允许多主机存在,每个设备都有一个唯一的地址

③ 连接到总线上的数目受总线的最大电容400pf限制

④ 数据传输速率:标准模式100k bit/s  快速模式400k bit/s 高速模式3.4Mbit/s

 

起始信号

void iic_start(void)
{ /* SCL为高电平期间, SDA从高电平往低电平跳变*/IIC_SDA ( 1 );	IIC_SCL ( 1 );iic_delay( );IIC_SDA ( 0 );	iic_delay( );IIC_SCL ( 0 );	iic_delay( );  /* 钳住总线, 准备发送/接收数据 */
}

停止信号

void iic_stop(void)
{ /* SCL为高电平期间, SDA从低电平往高电平跳变*/IIC_SDA ( 0 );	iic_delay( );IIC_SCL ( 1 );	iic_delay( );IIC_SDA ( 1 ); 	/* 发送总线停止信号*/iic_delay( );
}

检测应答信号

uint8_t iic_wait_ack (void) /* return 1:fail 0:succeed*/
{	IIC_SDA (1);  /* 主机释放SDA线 */iic_delay( );IIC_SCL (1);  /* 从机返回ACK*/ 	iic_delay( );if ( IIC_READ_SDA ) /* SCL高电平读取SDA状态*/ {iic_stop();	    /* SDA高电平表示从机nack */ return 1;}IIC_SCL(0);	 /* SCL低电平表示结束ACK检查 */ iic_delay( );return 0;
}

发送应答信号

void iic_ack(void)
{ IIC_SCL (0);	iic_delay( );IIC_SDA (0);  /* 数据线为低电平,表示应答 */iic_delay( );IIC_SCL (1); 	iic_delay( );
}

发送非应答信号

void iic_nack(void)
{ IIC_SCL (0);	iic_delay( );IIC_SDA (1);  /* 数据线为高电平,表示非应答 */iic_delay( );IIC_SCL (1); 	iic_delay( );
}

发送1字节数据

void iic_send_byte(uint8_t data)
{for (uint8_t t = 0; t < 8; t++){	/* 高位先发 */IIC_SDA((data & 0x80) >> 7);iic_delay( );IIC_SCL ( 1 );	iic_delay( );IIC_SCL ( 0 );data <<= 1; /* 左移1位, 用于下一次发送 */}IIC_SDA ( 1 ); 	/* 发送完成,主机释放SDA线 */ 
}

读取1字节数据

uint8_t iic_read_byte (uint8_t ack) /* 1:ack 0:nack*/
{ uint8_t receive = 0 ;for (uint8_t t = 0; t < 8; t++){	/* 高位先输出,先收到的数据位要左移 */ receive <<= 1;		IIC_SCL ( 1 );	iic_delay( );if ( IIC_READ_SDA ) receive++;IIC_SCL ( 0 );iic_delay( );}if ( !ack ) iic_nack();else iic_ack();return receive; 	
}

 AT24C02

原理图

EEPROM是一种掉电后数据不丢失的储存器,常用来存储一些配置信息,在系统重新上电时就可以加载。

AT24C02是一个2K bitEEPROM存储器,使用IIC通信方式。

AT24C02:写操作地址(0xA0) 读操作地址(0xA1)

AT24C02写时序

AT24C02读时序

IIC配置步骤

1、使能SCLSDA对应时钟

        __HAL_RCC_GPIOB_CLK_ENABLE()

2、设置GPIO工作模式

        SDA开漏/SCL推挽输出模式,使用HAL_GPIO_Init初始化

3、编写基本信号

        起始信号 停止信号 应答信号

4、编写读和写函数

                iic_read_byte、iic_send_byte

为什么IIC总线SDA建议用开漏模式?

开漏输出的特点:不能输出高电平,   必须有外部(或内部)上拉才能输出高电平

IICSDA脚即要作为输出,又要作为输入,用开漏输出模式,很好实现输出输入共用,避免IO模式频繁切换带来的麻烦。

输出时:主机(MCU)输出0,可以拉低信号,来实现低电平发送,主机输出1(实际不起作用),由外部上拉电阻上拉,实现高电平发送。

输入时:主机(MCU)设置输出1状态,此时因为MCU无法输出1,相当于释放了SDA脚,此时外部器件可以主动拉低SDA/释放SDA脚(同样由上拉电阻提供“输出1的功能”),实现SDA脚的高低电平变化。

由于开漏输出模式下,MCU还是可以读取IDR状态寄存器,来获取引脚高低电平,因此MCU读取IDR,即可获得SDA脚的高低电平状态,从而实现输入检测。

AT24C02配置步骤

1、初始化IIC接口

2、编写写入/读取一个字节数据函数        遵循读写时序流程编写

3、编写连续读和连续写函数        在2的基础上进行实现

实验:驱动AT24C02实现读和写1字节数据

myiic.c

#include "./BSP/IIC/myiic.h"
#include "./SYSTEM/delay/delay.h"void iic_init(void)
{GPIO_InitTypeDef gpio_init_struct;IIC_SCL_GPIO_CLK_ENABLE();  /* SCL引脚时钟使能 */IIC_SDA_GPIO_CLK_ENABLE();  /* SDA引脚时钟使能 */gpio_init_struct.Pin = IIC_SCL_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */HAL_GPIO_Init(IIC_SCL_GPIO_PORT, &gpio_init_struct);    /* SCL */gpio_init_struct.Pin = IIC_SDA_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;            /* 开漏输出 */HAL_GPIO_Init(IIC_SDA_GPIO_PORT, &gpio_init_struct);    /* SDA *//* SDA引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1), 也可以读取外部信号的高低电平 */
}static void iic_delay(void)
{delay_us(2);
}/* 起始信号 */
void iic_start(void)
{/* SCL为高电平期间, SDA从高电平往低电平跳变*/IIC_SDA ( 1 );IIC_SCL ( 1 );iic_delay( );IIC_SDA ( 0 );iic_delay( );IIC_SCL ( 0 );iic_delay( );  /* 钳住总线, 准备发送/接收数据 */
}/* 停止信号 */
void iic_stop(void)
{/* SCL为高电平期间, SDA从低电平往高电平跳变*/IIC_SDA ( 0 );iic_delay( );IIC_SCL ( 1 );iic_delay( );IIC_SDA ( 1 );  /* 发送总线停止信号*/iic_delay( );
}/* 等待应答信号 */
uint8_t iic_wait_ack (void) /* return 1:fail 0:succeed*/
{IIC_SDA (1);    /* 主机释放SDA线 */iic_delay( );IIC_SCL (1);    /* 从机返回ACK*/iic_delay( );if ( IIC_READ_SDA ) /* SCL高电平读取SDA状态*/ {iic_stop();     /* SDA高电平表示从机nack */ return 1;}IIC_SCL(0);         /* SCL低电平表示结束ACK检查 */ iic_delay( );return 0;
}/* 应答信号 */
void iic_ack(void)
{ IIC_SCL (0);iic_delay( );IIC_SDA (0);  /* 数据线为低电平,表示应答 */iic_delay( );IIC_SCL (1);iic_delay( );
}/* 非应答信号 */
void iic_nack(void)
{ IIC_SCL (0);iic_delay( );IIC_SDA (1);  /* 数据线为低电平,表示应答 */iic_delay( );IIC_SCL (1);iic_delay( );
}/* 发送一个字节数据 */
void iic_send_byte(uint8_t data)
{for (uint8_t t = 0; t < 8; t++){/* 高位先发 */IIC_SDA((data & 0x80) >> 7);iic_delay( );IIC_SCL ( 1 );iic_delay( );IIC_SCL ( 0 );data <<= 1;     /* 左移1位, 用于下一次发送 */}IIC_SDA ( 1 );      /* 发送完成,主机释放SDA线 */ 
}/* 读取1字节数据 */
uint8_t iic_read_byte (uint8_t ack)
{ uint8_t receive = 0 ;for (uint8_t t = 0; t < 8; t++){/* 高位先输出,先收到的数据位要左移 */ receive <<= 1;IIC_SCL ( 1 );iic_delay( );if ( IIC_READ_SDA ) receive++;IIC_SCL ( 0 );iic_delay( );}if ( !ack ) iic_nack();else iic_nack();return receive;
}

myiic.h

#ifndef __MYIIC_H
#define __MYIIC_H#include "./SYSTEM/sys/sys.h"/******************************************************************************************/
/* 引脚 定义 */#define IIC_SCL_GPIO_PORT               GPIOB
#define IIC_SCL_GPIO_PIN                GPIO_PIN_6
#define IIC_SCL_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PB口时钟使能 */#define IIC_SDA_GPIO_PORT               GPIOB
#define IIC_SDA_GPIO_PIN                GPIO_PIN_7
#define IIC_SDA_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PB口时钟使能 *//******************************************************************************************//* IO操作 */
#define IIC_SCL(x)        do{ x ? \HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_SET) : \HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_RESET); \}while(0)       /* SCL */#define IIC_SDA(x)        do{ x ? \HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_SET) : \HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_RESET); \}while(0)       /* SDA */#define IIC_READ_SDA     HAL_GPIO_ReadPin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) /* 读取SDA */void iic_init(void);
void iic_start(void);
void iic_stop(void);
uint8_t iic_wait_ack(void);
void iic_ack(void);
void iic_nack(void);
void iic_send_byte(uint8_t data);
uint8_t iic_read_byte (uint8_t ack);#endif

24cxx.c

#include "./BSP/IIC/myiic.h"
#include "./BSP/24CXX/24cxx.h"
#include "./SYSTEM/delay/delay.h"void at24c02_init(void)
{iic_init();
}void at24c02_write_one_byte(uint8_t addr, uint8_t data)
{/* 1、发送起始信号 */iic_start();/* 2、发送通讯地址(写操作地址) */iic_send_byte(0xA0);/* 3、等待应答信号 */iic_wait_ack();/* 4、发送内存地址 */iic_send_byte(addr);/* 5、等待应答信号 */iic_wait_ack();/* 6、发送写入数据 */iic_send_byte(data);/* 7、等待应答信号 */iic_wait_ack();/* 8、发送停止信号 */iic_stop();/* 等待EEPROM写入完成 */delay_ms(10);
}uint8_t at24c02_read_one_byte(uint8_t addr)
{uint8_t rec = 0;/* 1、发送起始信号 */iic_start();/* 2、发送通讯地址(写操作地址) */iic_send_byte(0xA0);/* 3、等待应答信号 */iic_wait_ack();/* 4、发送内存地址 */iic_send_byte(addr);/* 5、等待应答信号 */iic_wait_ack();/* 6、发送起始信号 */iic_start();/* 7、发送通讯地址(读操作地址) */iic_send_byte(0xA1);/* 8、等待应答信号 */iic_wait_ack();/* 9、等待接收数据 */rec = iic_read_byte(0);/* 10、发送非应答(获取该地址即可) *//* 11、发送停止信号 */iic_stop();return rec;
}

24cxx.h

#ifndef __24CXX_H
#define __24CXX_H#include "./SYSTEM/sys/sys.h"void at24c02_init(void);
void at24c02_write_one_byte(uint8_t addr, uint8_t data);
uint8_t at24c02_read_one_byte(uint8_t addr);#endif

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/24CXX/24cxx.h"int main(void)
{uint8_t key;uint8_t i = 0;uint8_t data = 0;HAL_Init();                                 /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */delay_init(72);                             /* 延时初始化 */usart_init(115200);                         /* 串口初始化为115200 */led_init();                                 /* 初始化LED */key_init();                                 /* 初始化按键 */at24c02_init();while (1){key = key_scan(0);if (key == KEY1_PRES){at24c02_write_one_byte(100, 66);printf("write data \r\n");}if (key == KEY0_PRES){data = at24c02_read_one_byte(100);printf("read data:%d \r\n", data);}i++;if (i % 20 == 0){LED0_TOGGLE();  /* 红灯闪烁 */i = 0;}delay_ms(10);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线性代数基础3 行列式

行列式 行列式其实在机器学习中用的并不多&#xff0c;一个矩阵必须是方阵&#xff0c;才能计算它的行列式 行列式是把矩阵变成一个标量 import numpy as np A np.array([[1,3],[2,5]]) display(A) print(矩阵A的行列式是&#xff1a;\n,np.linalg.det(A))array([[1, 3],[2, …

【C++打怪之路Lv3】-- 类和对象(上)

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分82)&#…

C++链表操作入门

数据结构基础&#xff1a;链表操作入门 数据结构基础&#xff1a;链表操作入门链表的基本概念链表的基本操作输出链表插入节点删除节点查找值 完整的链表操作示例结语 数据结构基础&#xff1a;链表操作入门 在计算机科学中&#xff0c;数据结构是组织和存储数据的方式&#x…

论文解读:(CAVPT)Dual Modality Prompt Tuning for Vision-Language Pre-Trained Model

v1文章名字&#xff1a;Dual Modality Prompt Tuning for Vision-Language Pre-Trained Model v2文章名字&#xff1a;Class-Aware Visual Prompt Tuning for Vision-Language Pre-Trained Model 文章汇总 对该文的改进&#xff1a;论文解读&#xff1a;(VPT)Visual Prompt …

ClickHouse 数据类型、表引擎与TTL

文章目录 数据类型注意事项 表引擎1.TinyLog 引擎2.MergeTree 引擎3.ReplacingMergeTree 引擎4.AggregatingMergeTree 引擎5.SummingMergeTree 引擎6.CollapsingMergeTree 引擎7.Distributed 引擎 TTL列级 TTL表级TTL 数据类型 ClickHouse 数据类型Java 数据类型数据范围UInt8…

在控制台实现贪吃蛇

在控制台实现贪吃蛇 前备知识Win32APICOORD这个结构体的声明如下&#xff1a;GetStdHandle 函数GetConsoleCursorInfo 函数SetConsoleCursorInfo 函数 SetConsoleCursorPosition 函数getAsyncKeyState 函数 控制台窗口的大小以及字符打印介绍控制台中的坐标宽字符及本地化介绍s…

使用 Gradio 的“热重载”模式快速开发 AI 应用

在这篇文章中&#xff0c;我将展示如何利用 Gradio 的热重载模式快速构建一个功能齐全的 AI 应用。但在进入正题之前&#xff0c;让我们先了解一下什么是重载模式以及 Gradio 为什么要采用自定义的自动重载逻辑。如果你已熟悉 Gradio 并急于开始构建&#xff0c;请直接跳转到第…

UE4 拍摄、保存并浏览相册

效果&#xff1a; 1.新建CameraActor类 2.修改截图保存路径 3.编写BP_Camera蓝图 注意路径 Save Image函数要在执行拍照和BeginPlay事件执行一次 按钮执行拍摄事件 3.编写UMG蓝图 技巧&#xff1a;让Index加1、减1循环赋值 4.把BP_Camera挂在玩家上

SVN--基本原理与使用(超详细)

目录 一、SVN概述二、SVN服务端软件安装三、SVN服务端配置四、SVN客户端软件安装与使用五、SVN三大指令六、SVN图标集与忽略功能6.1 图标集6.2 忽略功能 七、SVN版本回退八、SVN版本冲突九、SVN配置多仓库与权限控制9.1 配置多仓库9.2 权限控制 十、服务配置与管理十一、模拟真…

新建云仓库

1.GitHub新建云仓库&#xff1a; LICENSE:开源许可证&#xff1b;README.md:仓库说明文件&#xff1b;开源项目&#xff1b;cocoaPodsName.podspec: CocoaPods项目的属性描述文件。 2.Coding新建云仓库&#xff1a; 备注&#xff1a; Coding新建项目&#xff1a;

每日一题(力扣45):跳跃游戏2--贪心

由于题目已经告诉了我们一定可以跳到&#xff0c;所以我们只需去考虑前进最快的方法。即 判断当前下一步能跳的各个位置中&#xff0c;哪个能带你去去向最远的地方&#xff08;why&#xff1f; 因为其他位置所能提供的最大范围都没最远那个大&#xff0c;所以最远的那个已经可以…

The Log-Structured Merge-Tree (LSM-Tree) 论文阅读笔记

原论文&#xff1a;The Log-Structured Merge-Tree (LSM-Tree) LSM-Tree的简介和关键技术要点 LSM-Tree&#xff08;Log-Structured Merge-Tree&#xff09;是一种为高吞吐量读写操作优化的数据结构&#xff0c;特别适用于写入密集型的应用场景。它由Patrick O’Neil等人开发…

Vue 组件分类、局部注册和全局注册

文章目录 背景知识组件分类安装 vue-cli示例设置组件局部注册设置组件全局注册 背景知识 开发 Vue 的两种方式&#xff1a; 核心包传统开发模式&#xff1a;基于 html / css / js 文件&#xff0c;直接引入核心包&#xff0c;开发 Vue。工程化开发模式&#xff1a;基于构建工…

国产麒麟系统下打包electron+vue项目(AppImage、deb)

需要用到的一些依赖包、安装包以及更详细的打包方法word以及麒麟官网给出的文档都已放网盘&#xff0c;链接在文章最后&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&a…

13 c++版本的五子棋

前言 呵呵 这大概是 大学里面的 c 五子棋了吧 有一些 面向对象的理解, 但是不多 这里 具体的实现 就不赘述, 仅仅是 发一下代码 以及 具体的使用 然后 貌似 放在 win10 上面执行 还有一些问题, 渲染的, 应该很好调整 五子棋 #include<Windows.h> #include<io…

elaticsearch windows安装

es下载地址 https://www.elastic.co/cn/downloads/elasticsearch https://www.elastic.co/cn/downloads/past-releases#elasticsearch 在这里插入图片描述 下载直接解压&#xff0c;解压后目录 双击bin目录下的elasticsearch.bat开启服务 注意&#xff1a;9300 端口为 Elas…

阶跃星辰:探索智能科技的星辰大海

引言 在当今快速发展的科技时代&#xff0c;人工智能已经成为推动社会进步的重要力量。阶跃星辰&#xff0c;正是在这一背景下诞生的。 阶跃星辰是一家专注于通用人工智能探索的公司&#xff0c;成立于2023年4月。该公司的创始团队由一群对人工智能充满热情和渴望的人组成&am…

半导体行业的隐形翅膀:国产RFID技术突破封锁,助力生产

半导体行业的隐形翅膀&#xff1a;国产RFID技术突破封锁&#xff0c;助力生产 RFID技术&#xff0c;简单来说&#xff0c;就是一种自动识别技术&#xff0c;通过无线电波实现对标签信息的读取和写入。而这些标签&#xff0c;就像给物品贴上的小标签&#xff0c;上面存储着它们…

《系统架构设计师教程(第2版)》第15章-面向服务架构设计理论与实践-05-SOA设计模式

文章目录 1. 服务注册表模式1.1 服务注册表1.2 SOA治理功能1.3 注册表中的配置文件 2. 企业服务总线&#xff08;ESB&#xff09;模式3. Synchro ESB3. 微服务模式3.1 概述3.2 微服务架构模式方案3.2.1 聚合器微服务1&#xff09;概述2&#xff09;几种特殊的聚合微服务 3.2.2 …

C++解方程组的库

解决多元多次方程组的问题&#xff0c;你可以考虑以下几个C库&#xff1a; Eigen: Eigen库是一个高性能的C模板库&#xff0c;用于线性代数运算。它提供了强大的矩阵运算功能&#xff0c;可以用来解多元一次方程组。对于多次方程组&#xff0c;你可能需要结合Eigen和一些数值优…