当前位置: 首页 > news >正文

4.4 I2C写数据

目录

1.I2C模块的内部结构框图

2.数据发送过程简介

3.等待总线空闲

4.发送起始位

5.发送地址

6.发送数据

7.发送停止位

8.oled屏幕地址0x78

9.代码


写数据也就是发送数据

主机(单片机)发送,从机接收数据

1.I2C模块的内部结构框图

2.数据发送过程简介

3.等待总线空闲

定义发送函数

4.发送起始位

给START位写1就代表发送

当SB标志位从0变成1的时候就代表起始位发送完成

5.发送地址

主机发送7位的从机地址+RW#位(表示方向),并检测是否寻址成功(要收到ACK才成功)

如果AF标志位等于1代表寻址失败,如果ADDR等于1代表寻址成功

因为后面要使用这两个标志位,所以要先对AF和ADDR做清0,又因为ADDR比较特殊,所以就先清除AF标志位。

注意下面的Addr是数据,不是标志位ADDR,注意区分。

发送的数据(Addr)与上0xfe就可以最后一位清0,那样就可以保证RW#位是0,因为RW#位0代表写,1代表读

清除ADDR:先读SR1,再读SR2

6.发送数据

在数据发送阶段,主机发送一个字节,从机回一个ACK,主机发送一个字节,从机回一个ACK

要写入数据到数据寄存器之前,要判断一下数据寄存器有没有值,要查一下TxE标志位和AF标志位

AF标志位是用来查看是否寻址失败了,也就是查看上一个数据有没有被接收,查看一下ACK,AF等于1代表上一个数据被拒收了,那就要停止数据发送,先发一个停止位,再返回一个-2代表数据拒收

TXE标志位如果等于1,代表数据寄存器是空了,就可以发送数据了

等待发送数据寄存器和移位数据寄存器为空,就代表发送完了

BTF标志位可以判断这两个寄存器是否为空

当BTF标志位从0变成1的时候就说明数据发送完成了

在这之前也查询一下AF标志位防止数据被拒收。

7.发送停止位

8.oled屏幕地址0x78

把下面几个字节发给oled屏就亮了

9.代码

#include "stm32f10x.h"void My_I2C_Init(void);
int My_I2C_SendBytes(I2C_TypeDef *I2Cx,uint8_t Addr,uint8_t *pDate,uint16_t Size);int main(void)
{My_I2C_Init();uint8_t commands[]={0x00,0x8d,0x14,0xaf,0xa5};My_I2C_SendBytes(I2C1,0x78,commands,5);while(1){}
}void My_I2C_Init(void)
{//#1.IO引脚初始化//对I2C1进行重映射AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);//对PB8和PB9初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);// #2.初始化I2C1模块RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);//这样I2C1引脚就复位了RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,DISABLE);I2C_InitTypeDef I2C_InitStruct;I2C_InitStruct.I2C_ClockSpeed=400000;//波特率400kI2C_InitStruct.I2C_Mode=I2C_Mode_I2C;//标准I2CI2C_InitStruct.I2C_DutyCycle=I2C_DutyCycle_2; //占空比2:1I2C_Init(I2C1,&I2C_InitStruct);I2C_Cmd(I2C1,ENABLE); //闭合I2C1的总开关
}int My_I2C_SendBytes(I2C_TypeDef *I2Cx,uint8_t Addr,uint8_t *pDate,uint16_t Size)
{// #1. 等待总线空闲while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BUSY)== SET);// #2. 发送起始位I2C_GenerateSTART(I2Cx,ENABLE);while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_SB)==RESET);// #3. 寻址阶段I2C_ClearFlag(I2Cx,I2C_FLAG_AF);//AF标志位清除I2C_SendData(I2Cx, Addr & 0xfe);//等待从机呼应while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR)==SET) break;if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)==SET){I2C_GenerateSTOP(I2Cx,ENABLE);	//发送停止位return -1;	//寻址失败}}//清除ADDR(先读SR1,再读SR2)I2C_ReadRegister(I2Cx,I2C_Register_SR1);I2C_ReadRegister(I2Cx,I2C_Register_SR2);// #4.1 发送数据for(uint16_t i=0;i<Size;i++){while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)==SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -2;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_TXE)==SET) break;	}I2C_SendData(I2Cx,pDate[i]);}// 等待发送完成while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF)==SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -2;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BTF)==SET) break;	}// # 5. 发送停止位I2C_GenerateSTOP(I2Cx,ENABLE);return 0; //成功}

http://www.dtcms.com/a/398971.html

相关文章:

  • 代码审计-PHP专题MVC开发文件差异对比法模版引擎SSTI注入RCE执行1day分析
  • 使用IOT-Tree消息流MQTT模块节点实现监测数据推送功能
  • 网站开发团队取什么名字好监测网站空白栏目
  • PyTorch 神经网络构建方法总结
  • 案例分享|当Scrum沦为“精致的”形式主义
  • 【Linux网络】UDP协议
  • 【GPT入门】第70课 ragflow简单入门
  • 做任务可以给钱的网站企业网站优化要多少钱
  • 【UPPAAL】uppaal安装|含问题解决
  • 如何区分恶意爬虫与搜索引擎流量,保护数据不被窃取
  • 天津网站备案在哪照相织梦网站安装出现dir
  • Spring IOC :控制反转与依赖注入的深入剖析与实践
  • Verilog语法学习EP11:串口发送模块
  • 【UE·网络篇】ReplicationGraph入门教程
  • 安阳做推广网站html网页小游戏代码
  • HTML,CSS,JS
  • 用CodeBuddy Code CLI构建现代化Vue待办事项应用的完整实战
  • 前端实现网页水印防移除的实战方案
  • 1,LVGL(V8.3.10版本)裸机移植教程
  • 重庆做网站 外包公司百度关键词收录
  • 探索TCP与TCP6连接的关系:netstat找不到tcp接口?
  • 商城网站建设哪家效益快产品推销文案
  • display vlan 概念及题目
  • Composer Deprecation Notice 警告:为什么会出现?如何解决?
  • Python 中常用的数据分析绘图库解析
  • 甜点网站里的新闻资讯怎么做如何做国际网站
  • 怎么知道Redis 6+ 是否启用 ACL
  • three.js ——文字
  • 中山市智能h5网站建设公司wordpress电视剧
  • 个人网站域名一级a做爰片免费网站黄