IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 14. STM32——软件IIC -> 正文阅读

[嵌入式]14. STM32——软件IIC

IIC协议层

在这里插入图片描述

空闲状态

当IIC总线SDA以及SCL均处于高电平时,规定此状态为空闲状态,对应输出状态为高阻态(各场器件输出效应管截止,导致场效应管电阻很大),由上拉电阻将电平拉高。

起始信号

起始条件:SCL线是高电平时,SDA线从高电平向低电平切换

在这里插入图片描述

在这里插入图片描述

先写SDA,容易写程序,容易理解

//模拟IIC起始信号
static void I2C_START(void)
{
	I2C_SDA_SET();
	I2C_SCL_SET(); //将时钟线和数据线全部拉高,让其处于空闲状态
	delay_us(1);
	
	I2C_SDA_CLR(); //拉低数据线,产生下降沿
	delay_us(1);
	
	I2C_SCL_CLR(); //拉低时钟线
	delay_us(1);
}

停止信号

停止条件:SCL线是高电平时,SDA线从低电平向高电平切换

在这里插入图片描述

在这里插入图片描述

先写SDA,容易写程序,容易理解

//模拟IIC停止信号
static void I2C_STOP(void)
{
	I2C_SDA_CLR(); //拉低数据线,准备好
	delay_us(1);
	
	I2C_SCL_SET(); //拉高时钟线
	delay_us(1);
	
	I2C_SDA_SET(); //拉高数据线,产生上升沿
	delay_us(1);
}

数据有效性

SDA的高或低电平状态只有在 SCL 线的时钟信号是低电平时才能改变。

SDA在SCL的上升沿到来前准备好,并在下降沿到来之前必须稳定。
在这里插入图片描述

在这里插入图片描述

//写入一位数据
static void I2C_WriteByte(unsigned char I2C_Byte)
{
	unsigned char i = 0;
	
	for(i=0;i<8;i++) //共有8个字节,循环8次
	{
		I2C_SCL_CLR(); //拉低时钟线,为数据线的跳变提供条件
		delay_us(1);
		
		if( I2C_Byte & 0x80 ) //从最高位传输,XXXX XXXX & 1000 0000,1&X=X
		{
			I2C_SDA_SET(); //为1则拉高数据线
		}
		else
		{
			I2C_SDA_CLR(); //为0则拉低数据线
		}
		
		I2C_Byte <<= 1; //左移一位,下一位
		delay_us(1);
		
		I2C_SCL_SET(); //每传输完一位数据,拉高时钟线
		delay_us(1);
	}
	
	I2C_SCL_CLR(); //拉低时钟线
	delay_us(1);
	
	I2C_Wait_Ack(); //接收应答信号
}

应答信号

对于反馈有效应答位ACK的要求是,接收器在第九个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。

在这里插入图片描述

//IIC模拟应答信号
static unsigned char I2C_Wait_Ack(void)
{
	unsigned char Ack;
	
	I2C_SCL_CLR(); //拉低时钟线,准备好传输第9个时钟脉冲
	delay_us(1);
	
	I2C_SDA_SET(); //拉高数据线
	delay_us(1);
	
	I2C_SCL_SET(); //拉高时钟线,传输第9个时钟脉冲
	delay_us(1);
	
	if( I2C_SDA_Read() ) //判断从机数据应答信号,1则为无效应答,0则为有效应答
	{
		Ack = I2C_NO_Ack; //如果从机拉拉高数据线,反馈无效应答位Ack
	}
	else
	{
		Ack = I2C_Ack; //如果从机拉低数据线,反馈有效应答位Ack
	}
	
	I2C_SCL_SLR(); //拉低时钟线,9个脉冲传输完毕
	delay_us(1);
	
	return Ack; //返回应答
}

配置引脚初始化

void OLED_GPIO_Init(void)
{
	GPIO_InitTypeDef I2C_GPIOStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能APB2时钟
	
	//PB0 -> SCL    PB1 -> SDA
	I2C_GPIOStructure.GPIO_Mode  = GPIO_Mode_Out_OD; //连接到总线的器件必须配置为开漏输出
	I2C_GPIOStructure.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1;
	I2C_GPIOStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB, &I2C_GPIOStructure); //初始化GPIOB
	
	I2C_SDA_SET();
	I2C_SCL_SET(); //将时钟线和数据线全部拉高,让其处于空闲状态
	
}

整合软件IIC代码

oled.c

#include "stm32f10x.h"
#include "oled.h"
#include "SysTick.h"
#include "oledfront.h"

void OLED_GPIO_Init(void)
{
	GPIO_InitTypeDef I2C_GPIOStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	I2C_GPIOStructure.GPIO_Mode  = GPIO_Mode_Out_OD;
	I2C_GPIOStructure.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1;
	I2C_GPIOStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB, &I2C_GPIOStructure);
	
	I2C_SDA_SET();
	I2C_SCL_SET();
	
}

static void I2C_Start(void)
{
	I2C_SDA_SET();
	I2C_SCL_SET();
	delay_us(1);
	
	I2C_SDA_CLR();
	delay_us(1);
	
	I2C_SCL_CLR();
	delay_us(1);
}

static void I2C_Stop(void)
{
	I2C_SDA_CLR();
	delay_us(1);
	
	I2C_SCL_SET();
	delay_us(1);
	
	I2C_SDA_SET();
	delay_us(1);
}

static unsigned char I2C_Wait_Ack(void)
{
	unsigned char Ack;
	
	I2C_SCL_CLR();
	delay_us(1);
	
	I2C_SDA_SET();
	delay_us(1);
	
	I2C_SCL_SET();
	delay_us(1);
	
	if( I2C_SDA_Read() )
	{
		Ack = I2C_NO_Ack;
	}
	else
	{
		Ack = I2C_Ack;
	}
	
	I2C_SCL_CLR();
	delay_us(1);
	
	return Ack;
}

static void I2C_WriteByte(unsigned char I2C_Byte)
{
	unsigned char i = 0;
	
	for(i=0;i<8;i++)
	{
		I2C_SCL_CLR();
		delay_us(1);
		
		if(I2C_Byte & 0x80)
		{
			I2C_SDA_SET();
		}
		else
		{
			I2C_SDA_CLR();
		}
		
		I2C_Byte <<= 1;
		delay_us(1);
		
		I2C_SCL_SET();
		delay_us(1);
	}
	
	I2C_SCL_CLR();
	delay_us(1);
	
	I2C_Wait_Ack();
}

oled.h

#ifndef _OLED_H
#define _OLED_H

#define	I2C_SCL_SET()  GPIO_SetBits(GPIOB, GPIO_Pin_0)
#define I2C_SCL_CLR()  GPIO_ResetBits(GPIOB, GPIO_Pin_0)
#define I2C_SDA_SET()  GPIO_SetBits(GPIOB, GPIO_Pin_1)
#define I2C_SDA_CLR()  GPIO_ResetBits(GPIOB, GPIO_Pin_1)
#define I2C_SDA_Read() GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_1)

#define I2C_Ack    0
#define I2C_NO_Ack 1

void OLED_GPIO_Init(void);
static void I2C_Start(void);
static void I2C_Stop(void);
static unsigned char I2C_Wait_Ack(void);
static void I2C_WriteByte(unsigned char I2C_Byte);

#endif
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-23 12:39:15  更:2021-10-23 12:39:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:38:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码