目录

前言

一、项目内容

实验简介

二、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模块的使用做了一个总结,虽然看起来多,但涉及的内容全面,一个资料一个资料总结的,认真看完肯定大有收获,如有错误和不对的地方,望及时联系改正,谢谢大家。在此放个图片给大家看看,是不是很神奇。

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

  1. STM32基于IIC协议的OLED模块的使用

    前言 一.项目涉及的内容 项目简介 二.模块实操 1. IIC模块 1.1 IIC协议格式 1.2 开始信号与停止信号 1.3 写数据 1.3.1 硬件IIC代码编写 1.3.2 软件模拟IIC代码编 ...

  2. STM32 之三 标准外设版USB驱动库详解(架构+文件+函数+使用说明+示例程序)

    写在前面 目前,ST的USB驱动有两套,一套是早期的独立版USB驱动,官方培训文档中称为Legacy library:一套为针对其Cube 系列的驱动,根据芯片不同可能有区别,具体见对应芯片的Cube ...

  3. 【嵌入式】STM32基于SPI通信协议OLED屏显示

    STM32基于SPI通信协议OLED屏显示 一.SPI协议和OLED介绍 1.SPI协议介绍 物理层 协议层 2.OLED显示屏介绍 二.显示个人学号姓名实验 1.题目要求 2.代码部分 1.完整代码 ...

  4. STM32开发 -- 惯导模块开发详解

    如需转载请注明出处:https://juyou.blog.csdn.net/article/details/93476976 STM32开发 – GPS模块开发详解 这篇文章已经对于GPS模块开发讲得 ...

  5. 基于Kubernetes构建Docker集群管理详解

    from: 基于Kubernetes构建Docker集群管理详解 Kubernetes是Google开源的容器集群管理系统,基于Docker构建一个容器的调度服务,提供资源调度.均衡容灾.服务注册.动 ...

  6. 基于MIG控制器的DDR3读写控制详解

    基于MIG控制器的DDR3读写控制详解 目的:详细介绍FPGA中基于MIG IP核控制的DDR3详细控制及内部逻辑 平台:AX7350-Xilinx 软件:Vivado 2017.4 1.MIG IP ...

  7. ngnix的upstream模块配置详解

    2019独角兽企业重金招聘Python工程师标准>>> ngnix的upstream模块配置详解 2017年04月04日 13:10:03 阿里-橙鹰-潘民兰 阅读数:15409 标 ...

  8. FPGA串口(UART)通信协议制定与设计思路详解示例

    串口(UART)通信协议制定与设计思路详解 1 概述 本文用于描述规定的串口通信协议,以及传输内容. 2 项目关于串口的要求 a) 支持BIT自检,1路UART上报BIT信息: b) 1路UART接口 ...

  9. Spring Boot的每个模块包详解

    Spring Boot的每个模块包详解,具体如下: 1.spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. 2.spring-boot-s ...

最新文章

  1. 程序员取悦女票的正确姿势---Tip1(iOS美容篇)
  2. html设置字体整体放大,请教怎么样可以只放大或缩小内容层里的字体呢?我不想让整页都放大缩小。请指教!谢谢!_html/css_WEB-ITnose...
  3. Xen虚拟化之一:Xen环境组件详解
  4. Python学习笔记:返回函数
  5. 提高ipad浏览器下大尺寸xml文件解析的性能
  6. linux下 最常用基本命令
  7. 基于git的工作流程
  8. 8个有趣的Linux提示与技巧
  9. C++中的面向对象(二)
  10. python必背入门代码-Python零基础入门学习笔记(一)
  11. 软件中Undo(撤回)和Redo(重做)的实现
  12. 您有一份Microsoft Office 365技能宝典等待签收
  13. Windows内核编程学习1:构建HelloWorld
  14. 【软件安装】MacBook 安装 MATLAB 2020a
  15. 042_Unicode对照表八
  16. Linux/centos备份系统镜像工具
  17. ULINE(插入水平线)
  18. Deeply Learned Attributes for Crowded Scene Understanding
  19. 学会做arduino交通灯
  20. 围成一圈的排列组合问题_行测技巧:排列组合之“环形排列”问题

热门文章

  1. 如何用路由器无线网络连接
  2. 软考高项(风险分析 定量风险分析 蒙特卡洛分析 )
  3. 动态扫描数码管显示_总结
  4. 学平面设计少走弯路,选择平面设计专业培训!
  5. Android 源码编译问题总结
  6. 从接单到发货只要30分钟?是什么,让这家电子企业如此高效
  7. ECharts 全新大版本 4.0 正式发布 即将支持微信小程序中使用ECharts
  8. SJCAM发力CES展 推出可触摸屏4K运动相机
  9. 厉害了!平均年龄8岁的抽象派画家,网友笑称:这些作品,康定斯基看了都得服气!...
  10. 帕斯卡三角形html,04_帕斯卡三角形