第六节:STM32基于HAL库的IIC通信
IIC通信
《用CubeMX学习STM32》
注释 点击上面蓝字进入完整专栏,这个系列所有文章都会整合到这个专栏
6、STM32 I2C通信
前言: IIC协议简介
维基百科的解释如下: I2C(Inter-Integrated Circuit)字面上的意思是积体电路之间,它其实是I2C Bus简称,所以中文应该叫集成电路总线,它是一种串行通讯汇流排,使用多主从架构,由飞利浦公司在1980年代为了让主机板、嵌入式系统或手机用以连接低速周边装置而发展。I2C的正确读法为“I平方C”("I-squared-C"),而“I二C”("I-two-C")则是另一种错误但被广泛使用的读法。自2006年10月1日起,使用I2C协定已经不需要支付专利费,但制造商仍然需要付费以取得I2C从属装置位址。
我们需要了解的是 : I2C通信只需要两根线即可进行数据传输; 即串行数据线(SDA::Serial DAta)和串行时钟线(SCL::Serial CLock); IIC总线具有多主设备的优点, 就是有多个主机进行数据发送并且不会有混乱.
IIC总线可以用简单、优雅四个字形容,很方便。下面是IIC的时序图:
IIC总共有三种信号:开始信号,结束信号,应答信号
说明:高电平为1,低电平为0
1、图中S即为起始信号: SCL处于1时, SDA由高变低↓—>Start
下面是STM32的这部分代码,每句话我基本上都加了注释,可以对照时序图看, 便于理解
2、图中末尾P为结束信号: SCL=1, SDA 由低变高↑
3、数据传送: 每次数据传送都是8个字节; SCL=1时, SDA的数据不可以变化, 只有SCL为低电平, 数据线的数据才可以变化;
3.1、 数据传输流程:SCL=0, —>开始数据传输, 传输完一位之后,—> SCL=1(拉高时钟线);===
下面接着循环, 直到传输完一个字节8位数据.
下面举个例子:
e.g.
传输1001 1100?
SCL=0 --> SDA=1 --> SCL=1 (先传送最高位MSB)
SCL=0 --> SDA=0 --> SCL=1
SCL=0 --> SDA=0 --> SCL=1
…
**Tips:**在IIC协议中,起始信号必须有. 因为IC必须知道什么时候开始了,才可以正确判断接受数据.
下面开始Cube配置+IAR编程
6.1 操作简介
(1) 我所使用的STM32开发板板载了一个24C02的EEPROM存储芯片; 这个芯片就是通过IIC总线和单片机通信的;
(2) 通过GPIO软件模拟IIC通信 , 实现对24C02芯片内部数据的读写操作 .
注:
本次实验的代码是用的原子的底层代码, 修改了部分代码, 和Cube配置的工程以及HAL库函数匹配. 野火的例程没有看过,如果这个代码又有什么限制或者问题, 可以评论或者私信告诉我, 共同学习,感激不尽.
6.1 软件流程图
开机检测24C02--->主循环检测按键--->串口打印相关信息...
6.2 硬件接口
以我用的单片机为例:
但是这里并没有用板子上的硬件 IIC, 只是用这两个对应的引脚做软件模拟 IIC
Step1 : STM32CubeMX配置
(1) 像前面那样配置好基础的东西[RCC--SYS--时钟树配置不变]
- 还要配置 串口 和 按键 ; 时钟树的配置跟之前的博客都一样
- Tips: Click the blue word to open the corresponding blog link
(2) 配置IIC通信用的两个引脚(SCL&SDA)
两个引脚都配置为输出模式, 在程序中需要改变引脚方向, 那个时候直接操作寄存器改动引脚输入输出即可, 配置的时候先默认配置一个输出;
补充: 后面又加上了两个LED引脚, 用以做指示
(3) Project Manager and Generate Code
Step2 : IAR或Keil编程
(1) IIC部分代码
我把我改过部分的底层代码分享在网盘里面
链接:https://pan.baidu.com/s/17ogW2r-WzN9u-w511VzBJQ
提取码:9m4v.c文件放在 src 文件夹,.h文件复制到 Inc 文件夹
在myiic.h里面有两句宏定义SDA_OUT()和SDA_IN(); 如果你用的是F4的板子是可以直接用的, 但是如果用的是F1的或者其他的, 这个宏定义要改一下, 因为不同的芯片寄存器的名字和操作不太一样. 如果有人用的F1在这里遇到困难可以评论或者私信我, 这里就不单独写了
说明 : 24cxx文件是24CXX系列芯片的底层驱动文件, myiic文件是修改后的iic通信的驱动文件; 在主函数里面就是调用myiic里面的函数去实现通信的功能
部分底层代码分析
大概说一下底层驱动, 24cxx文件是通过iic协议对24c02芯片通信的底层驱动,直接用就可以了。
myiic文件是iic的关键.
关于起始信号, 结束信号就不多说了
在myiic.h中宏定义了SDA引脚的输入输出模式, 因为读数据的时候需要SDA这根线为输入模式, 往里面读数据
关于应答信号之类的几个函数,有兴趣可以去了解一下具体的IIC的协议总结或者数据手册
发送字节函数
IIC协议发送字节, 一个字节8位, 通过一个for循环发送;
txd是要发送的一个字节, IIC是先传输最高位, 所以让txd和0x80相与, 再右移7位
数据为1就给数据线(SDA)引脚写高电平, 然后txd左移一位,进入下一循环, 逐渐把8bits的数据发送完毕
读一个字节函数
IIC发送数据是往外发送数据, 所以SDA为输出模式, 但是读取字节是把外面的读进来;
举个形象一点的例子, 你的大脑就是24C02储存芯片, 你的身体器官就是IIC,即你的身体器官是通过IIC协议与外界进行数据交换的
发送字节就是你用嘴巴给别人说话把你脑子里想的东西告诉别人; 而接收字节就是你通过眼睛读书, 把知识记到脑子里
这样就很好理解了吧
(2) 按键部分
- 新建一个文件Ctrl+N—>Ctrl+S保存为 key.c到Src文件夹 ; 再新建一个保存在Inc文件夹, 命名为key.h
- 把.c和.h文件添加到工程中
+- 写代码
#include "key.h"
#include "main.h" /*******************************************************************************************************【文件名称】 : key.c*【文件描述】 : 核心板板载按键驱动代码*【文件功能】 : 实现按键输入扫描功能*【主控芯片】 : STM432F407zg*【实验平台】 : STM32F4xx开发板*【编写环境】 : IAR 8.30.1*【编写时间】 : 2019-12-31*【作 者】 : 李剀(KevinLee)*【历史记录】 : <1> $【修改时间】$【修改内容】$【修改详情】$【修改人员】*******************************************************************************************************//*** @brief 按键处理函数* @param mode:0,不支持连续按;1,支持连续按;* @retval 0: 没有任何按键按下 1: KEY0按下* 2: WKUP按下 WK_UP*/
uint8_t KEY_Scan(uint8_t mode)
{ static uint8_t key_up = 1;//按键按松开标志if (mode)key_up=1; //支持连按 if (key_up && (KEY0 == 0 || WK_UP != 0)){HAL_Delay(10);//去抖动 key_up = 0;if(KEY0 == 0)return 1;else if(WK_UP != 0)return 2;}else if(KEY0 != 0 && WK_UP == 0)key_up = 1;return 0;// 无按键按下
}
key.h代码如下
#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
/*******************************************************************************************************【文件名称】 : key.h*【文件描述】 : 核心板板载按键驱动代码*【文件功能】 : 实现按键输入扫描功能*【主控芯片】 : STM432F407zg*【实验平台】 : STM32F4xx开发板*【编写环境】 : IAR 8.30.1*【编写时间】 : 2019-12-31*【作 者】 : 李剀(KevinLee)*【历史记录】 : <1> $【修改时间】$【修改内容】$【修改详情】$【修改人员】*******************************************************************************************************/#define KEY0 HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) //PE4
#define WK_UP HAL_GPIO_ReadPin(WKUP_GPIO_Port, WKUP_Pin) //PA0#define KEY0_PRES 1 // 宏定义按键按下的键值
#define WKUP_PRES 2uint8_t KEY_Scan(uint8_t); //按键扫描函数 #endif
(3) 串口重定向printf
- 参考第三节: 串口通信(用CubeMX学习STM32);
(4) main.c文件
① 包含头函数
② 自定义变量
- TEXT_Buffer数组存放的是等会要写入24c02芯片的数据
③ 主函数变量定义
- key用于获取扫描按键值; datatemp数组作为传输数据的暂存地点
④ 初始化操作
- 在/ USER CODE BEGIN 2 /下, 先初始化IIC, 在测试串口, 并用串口打印提示信息, 然后检测存储芯片是否存在
/* USER CODE BEGIN 2 */AT24CXX_Init(); //IIC初始化printf("Usart is Ok!!!\n");printf("***************************\n");printf("** STM32 IIC TEST **\n");printf("** Kevin_8_Lee **\n");printf("** KEY0:Write WKUP:Read **\n"); // 打印提示信息; KEY0按下写数据;WKUP按下读数据printf("***************************\n");// 检测24C02芯片是否存在while(AT24CXX_Check()){printf("未检测到24C02!\n");HAL_Delay(500);HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin); // LED0闪烁}printf("24C02 Ready!\n");/* USER CODE END 2 */
⑤ while(1)循环
- 循环进行安检扫描, 如果KEY0按下, 就把之前定义的一个字符串数组的数据写入24C02, 如果检测到WKUP按键按下就把24C02内部的数据读取出来并打印在串口
while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */key = KEY_Scan(0); // 按键扫描获取键值// 如果KEY0按下,则向24C02芯片写入指定数据if (key == KEY0_PRES){printf("开始写入24C02...\n");AT24CXX_Write(0,(uint8_t *)TEXT_Buffer,SIZE);printf("传输完成\n\n");}// 如果WKUP按键按下,则从24C02芯片读出数据, 并打印在串口if (key == WKUP_PRES){printf("开始读24C02......\n");AT24CXX_Read(0,datatemp,SIZE);printf("读取到的数据为 : %s", datatemp);}// 下面的是进行一定的延时, 保证上面扫描安全运行, 同事// 以LED闪烁提示系统正在运行i++;HAL_Delay(10);if (i == 20){HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);i = 0;}}/* USER CODE END 3 */
实际效果
串口助手打印出的结果:
2020年4月19日2020年4月19日18:00:01补充:完整工程链接—>IIC通信
Don’t ever let somebody tell you, you can’t do something!!!
Author : 李光辉
date : Sun Apr 19 16:28:12 CST 2020
blog ID: Kevin_8_Lee
blog site : https://blog.csdn.net/Kevin_8_Lee
第六节:STM32基于HAL库的IIC通信相关推荐
- STM32 (基于HAL库) 硬件IIC读写任意AT24CXX芯片
HAL任意AT24Cxx芯片读写: 原理我就不讲了,直接实操: 一.配置 1.使用STM32CUBEMX进行引脚配置,IIC配置如下: 2.利用串口进行数据查看,串口配置如下: 3.时钟我们选择最高7 ...
- 正点原子STM32(基于HAL库)0
目录 开发环境搭建与使用 常用开发工具简介 MDK 安装 仿真器驱动安装 CH340 USB 虚拟串口驱动安装 使用MDK5 编译例程 使用串口下载程序 使用DAP 下载与调试程序 使用DAP 下载程 ...
- 正点原子STM32(基于HAL库)5
目录 SRAM 实验 存储器简介 SRAM 方案简介 硬件设计 程序设计 程序流程图 程序解析 下载验证 内存管理实验 内存管理简介 硬件设计 程序设计 程序流程图 程序解析 下载验证 SD 卡实验 ...
- 【STM32】HAL库——串口DMA通信(三)
前期准备: STM32CubeMX STM32RCT6核心板 IDE Keil(MDK-ARM) 关于DMA 1. 什么是DMA? DMA(Direct Memory Access,直接存储器访问) ...
- 正点原子STM32(基于HAL库)3
目录 高级定时器实验 高级定时器简介 高级定时器输出指定个数PWM 实验 高级定时器输出指定个数PWM原理 TIM1/TIM8 寄存器 硬件设计 课堂源码(输出指定个数PWM灯就闪几次) 程序设计 下 ...
- 正点原子STM32(基于HAL库)4
目录 ADC 实验 ADC 简介 单通道ADC 采集实验 ADC 寄存器 硬件设计 程序设计 下载验证 单通道ADC 采集(DMA 读取)实验 ADC & DMA 寄存器 硬件设计 程序设计 ...
- STM32基于HAL库自由启动和关闭定时器:
最近在利用hal库做STM32的按键消抖的时候采用进入外部中断后开启10ms定时器中断的方式,但是要求进入定时器中断后就关闭定时器,也就相应需要开启和关闭定时器的函数,然后遇到了一个兄台发布的问题及解 ...
- [笔记]STM32基于HAL库的SDIO+FATFS文件系统
1.背景 要用到Bootloader升级,APP部分要写运行日志.所以在Bootloader部分的FATFS要做裁剪,裁剪到只剩只读的操作就可以了,而APP端做可读可写. 2.开发板 用的是野火的ST ...
- STM32机器人控制开发教程No.1驱动电机(基于HAL库)
01 前言 本教程使用的机器人控制板拥有4个带编码器的电机接口,4个舵机接口,串口通信接口.SWD下载调试接口.航模遥控接口.USB5V输出接口以及方便与树莓派直接连接的40PIN接口等,板载资源丰富 ...
- STM32 串口DMA接收 Openmv / K210 整数、小数字符串数据 (基于HAL库)
目录 前言 一.工程配置 二.串口DMA部分代码 1.源文件UART_DMA.c 2.头文件UART_DMA.h 3.stm32f1xx_it.c的修改 4.串口收发DMA测试 三.字符串数字提取代码 ...
最新文章
- HarmonyOS Java工程目录结构
- 指针都没搞懂,还能算得上 C++ 老司机?
- XDR3020 WiFi6 11ax使用体验 11ax性能数据
- Java开发:(执行系统(例cmd)命令)Runtime.getRuntime().exec()参数解释
- HTTP 错误 404.13 - Not Found 请求筛选模块被配置为拒绝超过请求内容长度的请求
- 利用局域网性能测试仪保障企业网络环境
- 转换汇编到shellcode的过程
- Web前端开发面试考点指南
- [INS-20802] Oracle Net Configuration Assistant failed
- PHP5.3, PHP5.4, PHP5.5新特性
- 【build your own xxx】实现你自己的bind函数
- mysql java.util.date_jdbc-java.sql.date和java.util.date之间转换
- 解析 PowerJob 的序列化方案
- JavaScript 的call 与 apply
- 哲理短文一则:揭示最好的成功法则
- java string 数组 个数,Java - 定义一个接收String的方法,并返回一个整数数组,其中包含每个元音的数量...
- 为什么烂软件大行其道而好软件无人问津?
- 2022年华为杯中国研究生数学建模竞赛A题思路
- android 平板键盘布局,7款Android平板输入法横向评测,安卓平板软件HD/THD下载
- tp5小程序生成二维码保存到七牛云