STM32基于IIC通信协议的OLED模块使用(详解)

article/2025/6/23 17:44:58

目录

前言

一、项目内容

实验简介

二、IIC模块

1、IIC协议简介

2、物理层

3、协议层

4、硬件IIC代码配置

5、软件模拟IIC配置

1、起始信号与停止信号

2、从机应答信号

3、数据的有效性

4、数据传输

三、OLED模块

1、软件配置

2、OLED原理

1、OLED初始化函数

2、写入起始坐标

3、清屏函数

4、显示字符串

5、显示文字

6、显示图片(bmp)

4、总结


前言

本篇文章对IIC通信协议的原理做了总结,并在硬件IIC配置和软件模拟IIC上做了代码输出,由此来进行一个OLED屏幕的操作总结。

一、项目内容

本项实验的硬件组成有STM32F103C8T6芯片的开发板、OLED模块(0.96寸4针IIC接口OLED显示屏),时间用系统滴答定时器SysTick,主要模块配置是硬件IIC配置和软件模拟IIC配置。

实验简介

根据IIC通讯原理,来进行数据传输,进行一个OLED屏幕的显示,文字,图像。

二、IIC模块

1、IIC协议简介

IIC通讯协议(Inter---Integrted Circuit)是由Phiips飞利浦公司开发的,由于他引脚少,硬件实现简单,可拓展性强,不需要UASRT,CAN通讯协议的外部收发设备,现在被广泛使用在系统内多个集成电路IC(芯片)间的通讯。

IIC模块接收和发送数据,并将数据从串行转换成并行,或并行转换成串行,可以开启或禁止中 断。同步串行也就是半双工的通讯方式,接口通过数据引脚(SDA)和时钟引脚(SCL)连接到IIC总线。允许连接到标准(高达100kHz)或 快速(高达400kHz)的IIC总线。

接口可以下述4种模式中的一种运行:

1、从发送器模式

2、从接收器模式

3、主发送器模式(本文学习)

4、主接收器模式

该模块默认地工作于从模式。接口在生成起始条件后自动地从从模式切换到主模式;当仲裁丢失或产生停止信号时,则从主模式切换到从模式。允许多主机功能。

2、物理层

 图片来源:零死角玩转 STM32F103—霸道>>>第24章  I2C—读写EEPROM>>>常见的 I2C 通讯系统

它的物理层有如下特点:

1、它是一个支持设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线 中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。

2、 一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线 (SCL)。数据线即用来表示数据,时钟线用于数据收发同步。

3、总线通过上拉电阻接到电源,当IIC设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态,由上拉电阻把总线拉成高电平。
4、多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定哪个设备占用总线。
具有三种传输模式:标准模式传输速率为100kbit/s,快速模式为400kbit/s,高速模式下可达3.4M/s,但目前大多1IC设备尚不支持高速模式。

当然,本次要分两个本分来写,硬件IIC和软件IIC。

硬件IIC:对应芯片上的IIC外设,有相对应的IIC驱动电路,其所使用的IIC脚位也是专用的。速度快并可用于DMA。

软件IIC:一般是用GPIO脚位,用软件控制管脚状态以及模拟IIC通信波形,可以在任何脚位上来模拟。

区别:硬件IIC的效率要远高于软件的,而软件IIC不受引脚限制,接口比较灵活。
软件IIC是通过GPIO,软件模拟寄存器的工作方式,而硬件IIC是直接调用内部寄存器进行配
置。如果要从具体硬件上来看,可以去看下芯片手册。因为固件IIC的端口是固定的,所以会有所区别。
 

3、协议层

IIC 的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。

图片来源:零死角玩转 STM32F103—霸道>>>第24章  I2C—读写EEPROM>>>图 24-4 I2C 通讯复合格式

 IIC通讯概括

1、其中 S 表示由主机的 I2C 接口产生的传输起始信号(S),这时连接到 I2C 总线上的所有从机都会接收到这个信号。 起始信号产生后,所有从机就开始等待主机紧接下来广播的从机地址信号 (SLAVE_ADDRESS)。

2、在 I2C 总线上,每个设备的地址都是唯一的,当主机广播的地址与某个设备地址相同时,根据 I2C协议,这个从机地址可以是 7 位或 10 位。 在地址位之后,是传输方向的选择位,该位为 0即主机向从机写数据。该位为1时,则相反,即主机由从机读数据。在此传输后选择数据寄存器和命令寄存器两种,传输到对应寄存器表示要传输数据/命令。

3、从机接收到匹配的地址后,主机或从机会返回一个应答(ACK)或非应答(NACK)信号, 只有接收到应答信号后,主机才能继续发送或接收数据。重复这个过程,可以向从机传输N个数据, 这个N没有大小限制

4、主要有以下4个部分,①起始信号与停止信号,②应答信号,③数据的有效性,④数据传输。在后面软件模拟IIC中进行一个详细概括。

4、硬件IIC代码配置

STM32f10x的IIC片上外设专门负责实现IIC通讯协议,它们的IIC 通讯信号引出到不同 GPIO引脚上,使用时必须配置到这些指定的引脚自动根据协议的要求产生通讯信号,收发数据并缓存起来,CPU只要检测该外设的状态和访问数据寄存器就能完成数据收发。

 图片来源:STM32F1xx中文参考手册 >>> 8.3.9 I2C1 复用功能重映射>>>表48

为此我们一般用的PB6和PB7的引脚。在此之中需要对GPIO的引脚进行配置和IIC功能进行配置。其中配置的内容在代码中有注释。

#include "stm32f10x.h"
#include "oled.h"
#include "SysTick.h"
#include "codetab.h"void I2C_Configuration(void)
{I2C_InitTypeDef    I2C_InitStructure;GPIO_InitTypeDef   GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ,  ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE );I2C_DeInit( I2C1);I2C_InitStructure.I2C_Ack									= I2C_Ack_Enable;//使能应答位I2C_InitStructure.I2C_AcknowledgedAddress	= I2C_AcknowledgedAddress_7bit;//指定地址长度,可为7或者10I2C_InitStructure.I2C_ClockSpeed					= 400000;//时钟速度400kHZ,参数值不高于400KHZI2C_InitStructure.I2C_DutyCycle						= I2C_DutyCycle_2;//时钟占空比,可选low/high(低电平比高电平)= 2:0或16:9I2C_InitStructure.I2C_Mode								= I2C_Mode_I2C;//模式I2C_InitStructure.I2C_OwnAddress1					= 0x30;//主机地址,可为7或者10位,但只有IIC1能配置10位的I2C_Init( I2C1, &I2C_InitStructure); //初始化I2C外设配置I2C_Cmd(I2C1,ENABLE); //使能I2C外设//PB6---SCL   PB7---SDAGPIO_InitStructure.GPIO_Mode							= GPIO_Mode_AF_OD;  //高阻态运用开漏GPIO_InitStructure.GPIO_Pin								=	GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed							= GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);}

使用 I2C 外设通讯时,在通讯的不同阶段它会对“状态寄存器(SR1 及 SR2)”的不同数据位写入参数,我们通过读取这些寄存器标志来了解通讯状态

 

 图片来源:STM32F1xx中文参考手册>>>24 I2C接口>>>24.3.1 模式选择>>>图245 主发送器传送序列图

 主发送器的流程和事件说明在图中有说明,所以IIC写入字节参数函数需要流程如下,都是在IIC.h文件中查找相应的结构体配置。

//I2C写入字节参数
void I2C_WriteByte(uint8_t addr,uint8_t data)
{while ( I2C_GetFlagStatus( I2C1,  I2C_FLAG_BUSY)); //检查I2C总线是否繁忙I2C_GenerateSTART(I2C1, ENABLE );  //开启I2C1while ( !I2C_CheckEvent( I2C1,  I2C_EVENT_MASTER_MODE_SELECT)); //检查状态EV5,主模式I2C_Send7bitAddress( I2C1, OLED_ADDRESS ,  I2C_Direction_Transmitter);  //发送器件(OLED)地址while ( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ));I2C_SendData( I2C1,  addr); //发送寄存器地址while ( !I2C_CheckEvent( I2C1,  I2C_EVENT_MASTER_BYTE_TRANSMITTING));I2C_SendData( I2C1, data ); //发送数据while ( !I2C_CheckEvent( I2C1,  I2C_EVENT_MASTER_BYTE_TRANSMITTING));I2C_GenerateSTOP( I2C1, ENABLE ); //关闭I2C总线}

5、软件模拟IIC配置

软件IIC是通过GPIO管脚,软件模拟寄存器的工作方式,用软件来控制管脚的状态以及模拟IIC通讯的波形,从而达到一个IIC通讯过程。在下面就详细的来编写IIC软件模拟通讯的4个过程,①起始信号与停止信号②应答信号③数据的有效性④数据传输

其中的定时器是系统滴答定时器SysTick,详细可以看STM32的SysTick系统定时器_努力学习的多云的博客-CSDN博客

1、起始信号与停止信号

起始信号:当SCL为高电平期间,SDA有高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
停止信号:当SCL为高电平期间,SDA由低到高的跳变;停止信号也是一种高电平跳变时序信号,而不是一个电平信号。
起始信号和停止信号一般由主机产生。

数据和地址按8位/字节进行传输,高位在前。跟在起始条件后的1或2个字节是地址(7位模式为1 个字节,10位模式为2个字节)。地址只在主模式发送。

 图片来源:STM32F1xx中文参考手册>>>24 I2C接口>>>24.3 I2C功能描述>>>24.3.1 模式选择

以下为模拟起始信号和停止信号代码,软件模拟工作波形完成

#include "stm32f10x.h"                  // Device header
#include "oled_soft.h"
#include "SysTick.h"
#include "codetab.h"static void OLED_GPIO_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_OD;   //设置为通用开漏输出GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init( GPIOB, &GPIO_InitStructure );//IIC总线的SCL和SDA空闲状态下两条信号线处于高电平OLED_SCLK_Set();  //设PB0(SCL)为高电平OLED_SDAT_Set();  //设PB1(SDA)为高电平
}//模拟IIC的起始信号
static void OLED_IIC_Start(void)
{OLED_SCLK_Set();  //时钟总线高电平OLED_SDAT_Set();	//数据总线高电平us_delay(1);OLED_SDAT_Clr();us_delay(1);OLED_SCLK_Clr();us_delay(1);}//模拟IIC的停止信号
static void OLED_IIC_Stop(void)
{OLED_SDAT_Clr();us_delay(1);OLED_SCLK_Set();  //时钟总线高电平us_delay(1);OLED_SDAT_Set();	//数据总线高电平us_delay(1);}

为了更加直观方便的编写,我们可以在.h文件中进行宏定义

#ifndef _OLED_SOFT_H_
#define _OLED_SOFT_H_#include "stm32f10x.h" #define OLED_SCLK_Set()    GPIO_SetBits( GPIOB,  GPIO_Pin_0)   // PB0(SCL)输出高
#define OLED_SCLK_Clr()    GPIO_ResetBits( GPIOB,  GPIO_Pin_0) // PB0(SCL)输出低
#define OLED_SDAT_Set()    GPIO_SetBits( GPIOB,  GPIO_Pin_1)   // PB1(SDA)输出高
#define OLED_SDAT_Clr()    GPIO_ResetBits( GPIOB,  GPIO_Pin_1) // PB1(SDA)输出低
#define OLED_Read_SDAT()   GPIO_ReadInputDataBit( GPIOB,  GPIO_Pin_1)  //读取PB1(SDA)电平//应答信号为低电平时,为应答位(ACK)
//应答信号为高电平时,为非应答位(NACK)
#define IIC_ACK   0    //应答
#define IIC_NACK  1    //不应答
#define OLED_CMD  0    //写命令
#define OLED_DATA  1    //写数据
#define SIZE      16     //显示字符大小
#define Max_Column  128  //最大列数#endif

2、从机应答信号

发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位)表示接收器已经成功地接收了该字节:应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
对于反馈有效应答位ACK的要求是,接收器在第九个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。
在图中红圈可以看到,SCL为低电平后SDA再升为高电平,再SCL变为高电平,由此我们可以进行一个软件模拟IIC波形。

 代码如下:返回一个应答信号

//模拟IIC读取从机应答信号
static unsigned char IIC_Wait_Ack(void)
{unsigned char ack;OLED_SCLK_Clr();  //时钟线置低us_delay(1);OLED_SDAT_Set();  //数据总线高电平us_delay(1);OLED_SCLK_Set();  //时钟总线高电平us_delay(1);if ( OLED_Read_SDAT() ) //读取PB1(SDA)电平{ack = IIC_NACK; //1,不应答}else{ack = IIC_ACK;  //0,应答}OLED_SCLK_Clr();  //时钟线置低us_delay(1);return ack;}

 3、数据的有效性

IIC总线进行数据传输时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。SDA数据线在 SCL的每个时钟周期传输一位数据。

即:数据在SCL的上升沿到来之前就需准备好。并在下降沿到来之前必须稳定。

 

4、数据传输

3、数据的有效性中,数据位的传输是边沿触发的。在IIC总线上数据传输,传送的每一位数据都有一个时钟脉冲相对应,SCL 为高电平时SDA 表示的数据有效,即此时的 SDA 为高电平时表示数据“ 1”,为低电平时表示数据“0”。即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。

传输数据的时候,将SCL置低,然后设置SDA总线对应的引脚电平为高/低,SDA电平确定后再讲SCL置高,将8个位由高到低依次发送出去。

//IIC写入一个字节Byte
static void Write_IIC_Byte(unsigned char IIC_Byte)
{//高位先行原则unsigned char i; for (i=0;i<8;i++){OLED_SCLK_Clr();  //时钟线置低us_delay(1);if(IIC_Byte & 0x80)  //读取最高位 与上1000 0000{OLED_SDAT_Set();   //最高位为1}else{OLED_SDAT_Clr();   //最高位为0}us_delay(1);OLED_SCLK_Set();  //时钟总线置高电平,产生上升沿,把数据发送出去us_delay(1);IIC_Byte <<= 1;       //数据左移一位}OLED_SCLK_Clr();  //时钟线置低us_delay(1);while (IIC_Wait_Ack());  //等待从机应答信号}//IIC写命令
static void Write_IIC_Command(unsigned char IIC_Command)
{OLED_IIC_Start();Write_IIC_Byte(0x78);  //写入从机地址Write_IIC_Byte(0x00);  //写入命令Write_IIC_Byte(IIC_Command);  //写命令OLED_IIC_Stop();      //发送停止信号}//IIC写数据
static void Write_IIC_Data(unsigned char IIC_Data)
{OLED_IIC_Start();Write_IIC_Byte(0x78);  //写入从机地址Write_IIC_Byte(0x40);  //写入命令Write_IIC_Byte(IIC_Data);  //写数据OLED_IIC_Stop();      //发送停止信号}//对OLED写入一个字节Byte
void OLED_Write_Byte(unsigned char dat, unsigned char cmd)
{if(cmd){Write_IIC_Data(dat);  //写入数据}else{Write_IIC_Command(dat); //写入命令}}

三、OLED模块

1、软件配置

在这里我们所需要用到的是文字取模软件是PCtoLCD2002(字符模式),其中要取模的话选择C51格式,图片显示的话是需要转换成BMP格式,然后在Lmage2Lcd图片取模软件中进行取模。

2、OLED原理

本次实验用的是OLED模块(0.96寸4针IIC接口OLED显示屏)SSD1306,电源电压3.3-5.5V,总共四个接口,VCC,GND,SCL(IIC总线时钟信号),SDA(IIC总线数据信号)

SSD1306是一个为映射静态 RAM 保存位模式来显示。该 RAM 的为 128 * 64 bit大小,RAM 分为 8 页,从 PAFE0 到 PAGE7,用于单色 128 * 64 点阵显示,如下图所示

 当一个数据字节写到 GDDRAM 中,所有当前列的同一页的行图像数据都会被被填充(比如, 被列地址指针指向的整列(8 位)都会被填充)。数据位 D0 写到顶行,而数据位 D7 写到底行,如下图所示

 下面这幅图会更简单懂

1、OLED初始化函数

 一般OLED出厂厂家会给一份初始化函数,简单来说就是对OLED写入各种指令,每个都会不太一样,这里就粘贴本次实验的

//OLED屏幕初始化
void OLED_Init(void)
{OLED_GPIO_Init();	//GPIO口初始化ms_delay(200);	//延迟,由于单片机上电初始化比OLED快,所以必须加上延迟,等待OLED上复位完成OLED_Write_Byte(0xAE,OLED_CMD);	//关闭显示OLED_Write_Byte(0x00,OLED_CMD);	//设置低列地址OLED_Write_Byte(0x10,OLED_CMD);	//设置高列地址OLED_Write_Byte(0x40,OLED_CMD);	//设置起始行地址OLED_Write_Byte(0xB0,OLED_CMD);	//设置页地址OLED_Write_Byte(0x81,OLED_CMD); 	// 对比度设置,可设置亮度OLED_Write_Byte(0xFF,OLED_CMD);	//  265  OLED_Write_Byte(0xA1,OLED_CMD);	//设置段(SEG)的起始映射地址;column的127地址是SEG0的地址OLED_Write_Byte(0xA6,OLED_CMD);	//正常显示;0xa7逆显示OLED_Write_Byte(0xA8,OLED_CMD);	//设置驱动路数(16~64)OLED_Write_Byte(0x3F,OLED_CMD);	//64dutyOLED_Write_Byte(0xC8,OLED_CMD);	//重映射模式,COM[N-1]~COM0扫描OLED_Write_Byte(0xD3,OLED_CMD);	//设置显示偏移OLED_Write_Byte(0x00,OLED_CMD);	//无偏移OLED_Write_Byte(0xD5,OLED_CMD);	//设置震荡器分频OLED_Write_Byte(0x80,OLED_CMD);	//使用默认值OLED_Write_Byte(0xD9,OLED_CMD);	//设置 Pre-Charge PeriodOLED_Write_Byte(0xF1,OLED_CMD);	//使用官方推荐值OLED_Write_Byte(0xDA,OLED_CMD);	//设置 com pin configuartionOLED_Write_Byte(0x12,OLED_CMD);	//使用默认值OLED_Write_Byte(0xDB,OLED_CMD);	//设置 Vcomh,可调节亮度(默认)OLED_Write_Byte(0x40,OLED_CMD);	使用官方推荐值OLED_Write_Byte(0x8D,OLED_CMD);	//设置OLED电荷泵OLED_Write_Byte(0x14,OLED_CMD);	//开显示OLED_Write_Byte(0xAF,OLED_CMD);	//开启OLED面板显示OLED_Clear();        //清屏OLED_Set_Pos(0,0); 	 //设置数据写入的起始行、列
}  


比如说,如果页地址设置为 B2h,低列地址是 03h 高列地址为 00h,那么就意味着开始列是
PAGE2 的 SEG3.RAM 。输出数据字节将写到 RAM 列 3 的位置。简单的OLED屏幕指令表如下

由此我们进行一个各个函数的编写

2、写入起始坐标

//设置数据写入的起始坐标(行和列)
//x:列的起始低地址与起始高地址
//y:页的起始页的地址  0-7
void OLED_Set_Pos(unsigned char x,unsigned char y)
{OLED_Write_Byte(0xb0+y,OLED_CMD);   //写入页地址OLED_Write_Byte((x&0x0f),OLED_CMD);  //写入列的地址,低半个字节OLED_Write_Byte((x&0xf0)>>4 | 0x10,OLED_CMD);   //写入列地址,高半个字节}

3、清屏函数

//全屏填充
//SSD1306显存总共为128*64bit大小,分为8页,每页128个字节
void OLED_Fill(unsigned char Fill_Data)
{unsigned char m,n;for (m=0;m<8;m++){OLED_Write_Byte(0xb0 +m,OLED_CMD); //从0-7页依次写入OLED_Write_Byte(0x00,OLED_CMD);    //列低地址OLED_Write_Byte(0x10,OLED_CMD);    //列高地址for (n=0;n<128;n++){OLED_Write_Byte(Fill_Data,OLED_DATA);}}}//清屏函数
void OLED_Clear(void)
{OLED_Fill(0x00);}

4、显示字符串

//显示字符
void OLED_ShowChar(unsigned char x,unsigned char y,unsigned char chr)
{unsigned char c = 0,i = 0;c = chr - ' ';   //获取字符的偏移量if(x > Max_Column){x = 0;   //如果列超出范围(128),就从下两页的第0列开始y = y+2; //}if(SIZE == 16) //字符大小如果为16*8{OLED_Set_Pos(x , y); //从x,y开始画点for(i=0;i<8;i++){OLED_Write_Byte(F8X16[c*16+i],OLED_DATA); //找出一个字符C的数组位数,先把第一列画完}OLED_Set_Pos(x , y+1); //开始换页for(i=0;i<8;i++){OLED_Write_Byte(F8X16[c*16+i+8],OLED_DATA); //找出一个字符C的数组位数,先把第一列画完}}else if(SIZE == 6)   //如果为6*8{OLED_Set_Pos(x , y); //从x,y开始画点for(i=0;i<6;i++)OLED_Write_Byte(F6x8[c*8][i],OLED_DATA); //找出一个字符C的数组位数,先把第一列画完}}//显示字符串
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char *str)
{unsigned char j=0;while(str[j]  != '\0')   //判断是否为最后一个字符{OLED_ShowChar(x,y,str[j]);  //显示字符x+=8;    //列数+8,一个字符占8if(x >= Max_Column){x = 0;y +=2;}j++;}}

5、显示文字


//显示文字,想显示哪个直接给数字即可
void OLED_ShowChinese(unsigned char x,unsigned char y,unsigned char num)
{unsigned char t,addr=0;OLED_Set_Pos(x,y);for(t=0;t<16;t++){OLED_Write_Byte(Hzk[2*num][t],OLED_DATA);  //画num在数组位置的第1页16列的点addr+=1;  //数组地址+1}OLED_Set_Pos(x,y+1);for(t=0;t<16;t++){OLED_Write_Byte(Hzk[2*num+1][t],OLED_DATA);  //画num在数组位置的第2页16列的点addr+=1;  //数组地址+1}}

6、显示图片(bmp)

//显示图片
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{unsigned int j=0;unsigned char x,y;if (y1%8 == 0)y = y1/8;elsey = y1/8 +1;for(y = y0;y < y1;y++){OLED_SetPos(x0,y);for(x = x0;x<x1;x++){WriteDat( BMP[j++] );}}
}

4、总结

本篇文章主要是对IIC通讯协议的原理,和OLED模块的使用做了一个总结,虽然看起来多,但涉及的内容全面,一个资料一个资料总结的,认真看完肯定大有收获,如有错误和不对的地方,望及时联系改正,谢谢大家。在此放个图片给大家看看,是不是很神奇。

 


http://chatgpt.dhexx.cn/article/yseiMg36.shtml

相关文章

IIC 通信协议 (一)

目录 引言 IIC协议 1、历史 2、特点 3、信号线 4、主从关系 5、通信过程 6、协议规范 地址 1、器件地址 2、存储器地址 读写时序 1、写时序 1.1、单字节写时序 1.2、连续写时序 2、读时序 2.1、单字节读时序 2.2、连续读时序 参考声明 引言 这个专栏闲置好…

基础通信协议之 IIC (I2C) 详细讲解

IIC是当今嵌入式应用中最常见的串行通信协议之一。对比OneWire严苛的时序要求&#xff0c;SPI等更多的线缆要求&#xff0c;IIC处于一个折中的位置&#xff1a;不那么多的2根线缆的硬件要求&#xff0c;不那么复杂严苛的时序要求&#xff0c;便可进行多主多从的双向通信&#x…

IIC 通信协议 (二)

目录 引言 子模块设计 思路 单字节 IIC 发送模块 思路 Verilog 源码 多字节发送控制模块 思路 Verilog 源码 仿真 思路 test bench 仿真结果 参考声明 引言 本篇博文承接前文&#xff0c;继续做 IIC 通信协议 FPGA实现相关的内容。用Verilog 编写一个 IIC 通信控…

IIC通信协议(硬件实现IIC通信详解I)

IIC通信协议 什么是IIC协议协议层起始信号和停止信号数据的有效性 什么是IIC协议 I2C&#xff08;Inter-Integrated Circuit&#xff09;通讯协议是由 Phiilps 公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准…

详解通信协议之IIC通信协议

详解通信协议之IIC通信协议 本文结合AT24C02对IIC通信协议原理进行了描述。 IIC通信协议(以AT24C02为例) IIC通讯协议(Inter&#xff0d;Integrated Circuit)是由 Philips 公司开发双向同步半双工串行总线&#xff0c;只需要两根线(SDA、SCL)即可在连接于总线上的器件之间传…

IIC(I2C)通信协议详解

简介 I2C 是飞利浦公司设计的&#xff0c;一种很常见的总线协议&#xff0c; I2C 使用两条线在主控制器和从机之间进行数据通信。一条是 SCL(串行时钟线)&#xff0c;另外一条是SDA(串行数据线)&#xff0c;这两条数据线需要接上拉电阻&#xff0c;总线空闲的时候 SCL 和 SDA …

IIC 通信协议

一、IIC 通信协议介绍 IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备。 如今主要在服务器管理中使用&#xff0c;其中包括单个组件状态的通信。例如管理员可对各个组件进行查询&#xff0c;以管理系统…

三大通信协议(二):IIC通信协议

目录 1. 概念2. 硬件连接3. 数据传输协议3.1 开始信号3.2 地址位3.3 读写位&#xff08;R/W&#xff09;3.4 应答位&#xff08;ACK / NACK&#xff09;3.5 数据位&#xff08;8Bit&#xff09;3.6 停止信号 4. 软件编写4.1 初始化4.2 开始信号4.3 IIC发送一个字节数据4.4 IIC读…

IIC通信协议总结

&#xff08;1&#xff09;概述 I2C(Inter-Integrated Circuit BUS) 集成电路总线&#xff0c;该总线由NXP&#xff08;原PHILIPS&#xff09;公司设计&#xff0c;多用于主控制器和从器件间的主从通信&#xff0c;在小数据量场合使用&#xff0c;传输距离短&#xff0c;任意时…

IIC通信协议,搞懂这篇就够了

注&#xff1a;公众号后台发送 “IIC” 即可获取基于STM32上实现软件模拟IIC的完整代码。 I2C(IIC)属于两线式串行总线&#xff0c;由飞利浦公司开发用于微控制器(MCU)和外围设备(从设备)进行通信的一种总线&#xff0c;属于一主多从(一个主设备(Master)&#xff0c;多个从设备…

IIC通讯协议

一、简介 IIC&#xff08;Inter-integerted Circuit&#xff09;集成电路总线&#xff0c;该通信协议由NXP&#xff08;原PHILIPS&#xff09;公司设计&#xff0c;多用于主控制器和从器件间的主从通信&#xff0c;在小数据量场景下使用&#xff0c;传输距离短&#xff0c;任意…

搜狗搜索正式接入微信公众号

搜狗搜索正式接入微信公众号 6月9日中午消息&#xff0c;搜狗搜索今日宣布正式接入微信公众号数据。用户将在搜狗搜索页面查询和浏览微信公众号文章。 据悉&#xff0c;在搜狗搜索框中输入微信公众号关键词&#xff0c;便可在搜索结果页中查看相关微信公众号的文章列表&#xf…

Python爬虫 selenium自动化 利用搜狗搜索爬取微信公众号文章信息

少年最好的地方就是:虽然嘴上说要放弃,心底却总会憋着一口气。——刘同 文章目录 一、需求和网页分析二、selenium爬虫一、需求和网页分析 URL:https://weixin.sogou.com/ 你是否有特别喜欢的一些公众号文章,比如说关于网易云热评的。 我那么多遗憾,那么多期盼,你知道…

RSS订阅微信公众号初探-feed43

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

python爬虫爬取微信公众号历史文章链接

一、最近公司有了要爬取微信公众号文章链接的需求&#xff0c;之前最初接触爬公众号文章的时候&#xff0c;用的是搜狗微信&#xff0c;在这个上面可以搜到相关的微信公众号文章&#xff0c;但是这些链接是有时效性的&#xff0c;第二天链接就打不开了&#xff08;不知道现在是…

python抓取搜狗微信公众号文章

初学python&#xff0c;抓取搜狗微信公众号文章存入mysql mysql表&#xff1a; 代码&#xff1a; import requests import json import re import pymysql# 创建连接 conn pymysql.connect(host你的数据库地址, port端口, user用户名, passwd密码, db数据库名称, charsetut…

搜狗微信文章采集php,[造轮子]爬取搜狗微信公众号文章

背景&#xff1a;想做一个公众号文章资源APP&#xff0c;发现搜狗有搜索公众号文章功能&#xff0c;果断开撸。http://wxiread.com (用CMS搭了个简易的站)。 Step1.分析栏目及接口 搜狗分了20个栏目&#xff0c;分别是 热门,推荐,段子手,养生堂,私房话… 对应地址从 /pcindex/p…

微信公众号的“温柔一刀”,搜狗微信搜索部分功能将被下线

作为搜狗的单一最大股东&#xff0c;腾讯与搜狗之间的联系向来就很紧密&#xff0c;其中包括搜搜被并入搜狗、微信公众号的搜索功能划分给搜狗、腾讯新闻、QQ浏览器等腾讯系产品的搜索功能全部换成搜狗。腾讯对搜狗的支持是显而易见的&#xff0c;但若有利益冲突的情况下&#…

【scrapy爬虫】最新sogou搜狗搜索 机智操作绕过反爬验证码(搜狗微信公众号文章同理)

前情提要 此代码使用scrapy框架爬取特定“关键词”下的搜狗常规搜索结果&#xff0c;保存到同级目录下csv文件。并非爬取微信公众号文章&#xff0c;但是绕过验证码的原理相同。如有错误&#xff0c;希望大家指正。 URL结构 https://www.sogou.com/web?query{关键词}&p…

利用搜狗抓取微信公众号文章

微信一直是一个自己玩的小圈子&#xff0c;前段时间搜狗推出的微信搜索带来了一丝曙光。搜狗搜索推出了内容搜索和公众号搜索两种&#xff0c;利用后者可以抓取微信公众号的最新内容&#xff0c;看了下还是比较及时的。 每个公众号都有一个openid&#xff0c;最早可以直接利用…