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

益阳营销网站建设网站二维码制作

益阳营销网站建设,网站二维码制作,安徽省住房和城乡建设厅官网网站,企业oa系统免费1. I2C 协议 IC(Inter-Integrated Circuit,简称 IIC 或 IC)是一种半双工、同步串行通信协议,主要用于短距离、低速的设备间通信。它由 Philips(现 NXP) 公司在 1982 年提出,广泛应用于嵌入式系…

1. I2C 协议

I²C(Inter-Integrated Circuit,简称 IIC 或 I²C)是一种半双工、同步串行通信协议,主要用于短距离、低速的设备间通信。它由 Philips(现 NXP) 公司在 1982 年提出,广泛应用于嵌入式系统、传感器通信、EEPROM 、常见4pin脚OLED屏等场景。

速度在100 kbps ~ 3.4 Mbps之间。一般是低速100 kbps ~ 400 kbps

1.1 连接方式

所有I2C设备的SCL连在一起,SDA连在一起,设备的SCL和SDA均要配置成开漏输出模式(因为IIC经常切换输入输出,如果使用推挽容易造成短路),SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右。

双线通信

  • 数据线(SDA, Serial Data):传输数据。

  • 时钟线(SCL, Serial Clock):同步数据传输的时钟信号。

 

1.2 主从结构

  • 主设备(Master):控制通信的设备。可以是微控制器、计算机等,它生成时钟信号并发起通信。

  • 从设备(Slave):被主设备控制的设备。可以是传感器、外部设备、存储器等。

支持多设备通信:一条I2C总线上可以连接多个主设备和从设备。每个从设备通过一个唯一的地址来进行识别,主设备通过该地址来选择与哪个从设备通信。

1.3 I2C协议的时序

起始信号 → 设备地址 + 方向位(读写指示位) → ACK(应答信号)→ 发送数据字节(仅读模式,主机发送) → ACK → 停止信号

主设备发送 7 位或 10 位地址,然后发送 读/写位(R/W)。

读(1):主设备想从从设备读取数据。

写(0):主设备想向从设备写入数据。

1.3.1 起始/终止信号
  • 起始条件:SCL高电平期间,SDA从高电平切换到低电平

  • 终止条件:SCL高电平期间,SDA从低电平切换到高电平

1.3.2 发送/接收数据

发送数据:数据传输是以字节为单位进行的。每个字节(8位数据)后都需要一个ACK信号。发送起始条件和地址帧后,SCL在低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节。

接收数据:与接收数据一致,只是SDA线的控制权交给了从机,从机将数据位依次放到SDA线上(高位先行)。

1.3.3 应答信号
  • ACK(Acknowledge):设备在收到正确数据后,将 SDA 拉低表示应答。

  • NACK(Not Acknowledge):设备未收到或数据错误时,SDA 维持高电平。

1.3.4 信号帧解读

指定地址写:

指定地址读:

1.4 软件IIC代码实现

 #include "I2C_demo.h"​// ======================= I²C 配置 =======================#define I2C_GPIO_PORT      GPIOB                // I²C 端口#define I2C_SCL_PIN        GPIO_Pin_x           // SCL 引脚#define I2C_SDA_PIN        GPIO_Pin_x           // SDA 引脚#define I2C_RCC            RCC_APB2Periph_GPIOB // RCC 时钟​// 延时宏(可优化)#define I2C_DELAY_US       10#define I2C_Delay()        Delay_us(I2C_DELAY_US)​// ======================= I²C 基础操作 =======================// SCL 控制#define Write_SCL(x)       GPIO_WriteBit(I2C_GPIO_PORT, I2C_SCL_PIN, x ? GPIO_PIN_SET : GPIO_PIN_RESET); I2C_Delay()// SDA 控制#define Write_SDA(x)       GPIO_WriteBit(I2C_GPIO_PORT, I2C_SDA_PIN, x ? GPIO_PIN_SET : GPIO_PIN_RESET); I2C_Delay()​// 读取 SDA#define Read_SDA()        GPIO_ReadInputDataBit(I2C_GPIO_PORT, I2C_SDA_PIN)​// ======================= I²C 函数实现 =======================void I2C_Init(void){RCC_APB2PeriphClockCmd(I2C_RCC, ENABLE);​GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(I2C_GPIO_PORT, &GPIO_InitStructure);​// 设置初始状态Write_SCL(1);Write_SDA(1);}​// I2C 起始信号void I2C_Start(void){Write_SDA(1);Write_SCL(1);Write_SDA(0);Write_SCL(0);}​// I2C 停止信号void I2C_Stop(void){Write_SDA(0);Write_SCL(1);Write_SDA(1);}​// 发送一个字节void I2C_SendByte(uint8_t Byte){for (uint8_t i = 0; i < 8; i++){Write_SDA(Byte & (0x80 >> i)); // 最高位先传输Write_SCL(1);Write_SCL(0);}}​// 读取一个字节uint8_t I2C_ReceiveByte(void){uint8_t i, Byte = 0;Write_SDA(1); // 释放 SDA​for (i = 0; i < 8; i++){Write_SCL(1);if (Read_SDA()) Byte |= (0x80 >> i);Write_SCL(0);}return Byte;}​// 发送 ACK(0)或 NACK(1)void I2C_SendAck(uint8_t AckBit){Write_SDA(AckBit);Write_SCL(1);Write_SCL(0);}​// 接收 ACK(0)或 NACK(1)uint8_t I2C_ReceiveAck(void){uint8_t AckBit;Write_SDA(1); // 释放 SDAWrite_SCL(1);AckBit = Read_SDA();Write_SCL(0);return AckBit;}​/*** @brief  I2C 向从设备写入 1 字节数据* @param  slave_addr  7 位 I2C 设备地址(不含 R/W 位)* @param  data        要发送的 1 字节数据* @retval 0: 成功, 1: 失败*/uint8_t I2C_WriteByte(uint8_t slave_addr, uint8_t data){I2C_Start();I2C_SendByte((slave_addr << 1) | 0); // 发送地址+写位 (0)if (I2C_ReceiveAck()) {I2C_Stop();return 1; // 失败}I2C_SendByte(data);if (I2C_ReceiveAck()) {I2C_Stop();return 1; // 失败}I2C_Stop();return 0; // 成功}​/*** @brief  I2C 读取从设备的 1 字节数据* @param  slave_addr  7 位 I2C 设备地址(不含 R/W 位)* @param  p_data      读取到的数据存放地址* @retval 0: 成功, 1: 失败*/uint8_t I2C_ReadByte(uint8_t slave_addr, uint8_t *p_data){I2C_Start();I2C_SendByte((slave_addr << 1) | 1); // 发送地址+读位 (1)if (I2C_ReceiveAck()) {I2C_Stop();return 1; // 失败}*p_data = I2C_ReceiveByte();I2C_SendAck(1); // 发送 NACK,表示读取完成I2C_Stop();return 0; // 成功}

2. SPI 协议

SPI(Serial Peripheral Interface,串行外设接口)是一种 高速、全双工、同步 的串行通信协议,常用于 微控制器、传感器、存储器(如 Flash)、显示屏、音频 IC、常见七Pin脚OLED屏 等设备间的数据传输。

2.1 连接方式

SPI 总线通常由 4 条信号线 组成:

  • MOSI(Master Out Slave In):主设备数据输出,连接到从设备的数据输入。

  • MISO(Master In Slave Out):主设备数据输入,连接到从设备的数据输出。

  • SCLK(Serial Clock):时钟信号,由主设备生成,从设备接收同步。

  • CS(Chip Select) / SS(Slave Select):片选信号,低电平有效,选择特定从设备(根据从机的数量增加)。

    • 输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入

    • 从机未被选中时,该从机的 MISO 引脚必须切换位高阻态(防止从机推挽模型下的点平冲突,从机一般内部自动完成)

 

2.2 主从结构

一主多从

  • 每个从设备都需要一个独立的 CS 线,否则多个从设备可能同时响应主设备。

  • 主设备 只会在选中的从设备上进行数据传输。

2.3 SPI 通信模式

其数据传输是基于 时钟信号(SCK)上升沿下降沿 进行数据的移位(Shift)和采样(Latch)。这一过程依赖于 时钟极性(CPOL)时钟相位(CPHA) 的设置(仅移位和采样的触发时刻不同),主机和从机必须按照相同的规则进行移位,以保证数据正确传输。

2.3.1 起始/终止信号
  • 起始条件:SS从高电平切换到低电平

  • 终止条件:SS从低电平切换到高电平

2.3.2 发送/接收数据

发送和接收数据有四种模型可以选择:SPI 设备的数据传输受 时钟极性(CPOL)时钟相位(CPHA) 控制,这两个参数决定了数据采样的时间点。

SPI 时钟模式(由 CPOL 和 CPHA 组合)

模式CPOLCPHA时钟空闲状态数据移位时刻数据采样时刻
模式 000低电平上升沿下降沿
模式 101低电平下降沿上升沿
模式 210高电平下降沿上升沿
模式 311高电平上升沿下降沿
  • 一个周期交换一个 bit 数据,以上模式仅是触发时刻不同

  • SPI 一般采用的是向从机发送指令来完成相应功能(从机内内置指令集,由厂商规定)

2.3.3 信号帧解读

主机向从机发送指令:

主机向从机指定地址读:

2.4 软件SPI代码实现

 #include "SPI_demo.h"​// ======================= SPI 配置 =======================#define SPI_GPIO_PORT GPIOB      // SPI 端口#define SPI_SCK_PIN GPIO_Pin_10  // SCK 时钟引脚#define SPI_MOSI_PIN GPIO_Pin_11 // MOSI 数据输出引脚#define SPI_MISO_PIN GPIO_Pin_12 // MISO 数据输入引脚#define SPI_CS_PIN GPIO_Pin_13   // 片选 CS 引脚​#define SPI_RCC RCC_APB2Periph_GPIOB // RCC 时钟​// 延时宏(可优化为更精确的时间)#define SPI_DELAY_US 1#define SPI_Delay() Delay_us(SPI_DELAY_US)​// ======================= SPI 基础操作 =======================// SCK 控制#define Write_SCK(x)                                                              \GPIO_WriteBit(SPI_GPIO_PORT, SPI_SCK_PIN, x ? GPIO_PIN_SET : GPIO_PIN_RESET); \SPI_Delay()// MOSI 控制#define Write_MOSI(x)                                                              \GPIO_WriteBit(SPI_GPIO_PORT, SPI_MOSI_PIN, x ? GPIO_PIN_SET : GPIO_PIN_RESET); \SPI_Delay()// 读取 MISO#define Read_MISO() GPIO_ReadInputDataBit(SPI_GPIO_PORT, SPI_MISO_PIN)// CS 控制#define Write_CS(x)                                                              \GPIO_WriteBit(SPI_GPIO_PORT, SPI_CS_PIN, x ? GPIO_PIN_SET : GPIO_PIN_RESET); \SPI_Delay()​// ======================= SPI 函数实现 =======================void SPI_Init(void){RCC_APB2PeriphClockCmd(SPI_RCC, ENABLE);​GPIO_InitTypeDef GPIO_InitStruct;​// 配置 SCK、MOSI、CS 为推挽输出GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;​GPIO_InitStruct.GPIO_Pin = SPI_SCK_PIN;GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct);​GPIO_InitStruct.GPIO_Pin = SPI_MOSI_PIN;GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct);​GPIO_InitStruct.GPIO_Pin = SPI_CS_PIN;GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct);​// 配置 MISO 为输入GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin = SPI_MISO_PIN;GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct);​// 设置初始状态Write_SCK(0);Write_MOSI(1);Write_CS(1);}​// SPI 传输 1 字节(主机发送 & 接收)uint8_t SPI_TransferByte(uint8_t data){uint8_t i, receivedData = 0;​for (i = 0; i < 8; i++){// 设置 MOSI 线Write_MOSI((data & 0x80) ? 1 : 0);​Write_SCK(1); // 上升沿,传输数据​// 读取 MISO 线receivedData <<= 1;if (Read_MISO())receivedData |= 0x01;​Write_SCK(0); // 下降沿,准备下一位data <<= 1;   // 左移 1 位}​return receivedData;}​// SPI 发送多字节数据void SPI_WriteBytes(uint8_t *pTxData, uint16_t len){Write_CS(0); // 选中从设备for (uint16_t i = 0; i < len; i++)SPI_TransferByte(pTxData[i]);Write_CS(1); // 释放从设备}​// SPI 读取多字节数据void SPI_ReadBytes(uint8_t *pRxData, uint16_t len){Write_CS(0); // 选中从设备for (uint16_t i = 0; i < len; i++)pRxData[i] = SPI_TransferByte(0xFF); // 发送 0xFF 读取数据Write_CS(1);                             // 释放从设备}​// SPI 读写多字节数据void SPI_TransferBytes(uint8_t *pTxData, uint8_t *pRxData, uint16_t len){Write_CS(0); // 选中从设备for (uint16_t i = 0; i < len; i++)pRxData[i] = SPI_TransferByte(pTxData[i]);Write_CS(1); // 释放从设备}

文章转载自:

http://fxCmAtZH.Lsqxh.cn
http://zX8eZAiF.Lsqxh.cn
http://UB3v1vyM.Lsqxh.cn
http://tm6eiHce.Lsqxh.cn
http://Dirr9vwD.Lsqxh.cn
http://9QmGDNSM.Lsqxh.cn
http://TQqPM8o8.Lsqxh.cn
http://olThaSr0.Lsqxh.cn
http://ZjWrHC0B.Lsqxh.cn
http://2DQeLzfB.Lsqxh.cn
http://50WCYyTm.Lsqxh.cn
http://4UsMlc3j.Lsqxh.cn
http://6SObJhYD.Lsqxh.cn
http://QPxfVgXd.Lsqxh.cn
http://IXztSHkW.Lsqxh.cn
http://VGBxUoMa.Lsqxh.cn
http://EFuf3QtI.Lsqxh.cn
http://Hmsj9vSd.Lsqxh.cn
http://St2nQKcF.Lsqxh.cn
http://BgP7nxsS.Lsqxh.cn
http://oAXUiGq7.Lsqxh.cn
http://DUfH8z6e.Lsqxh.cn
http://YqOEIB65.Lsqxh.cn
http://1qaGqXdz.Lsqxh.cn
http://99s7LUfB.Lsqxh.cn
http://4dHIihfA.Lsqxh.cn
http://KmBn4rLh.Lsqxh.cn
http://B5Evj8mb.Lsqxh.cn
http://3IfZ4OeN.Lsqxh.cn
http://k3Nw34jL.Lsqxh.cn
http://www.dtcms.com/wzjs/711354.html

相关文章:

  • 下载住小帮app看装修seo教育
  • 襄阳建设路21号创意园网站做网站可以赚钱么
  • 网站宣传创意视频网站建设的自查报告
  • 怎么做网站变更长沙行业网站建设
  • 如何做网站需求东莞大岭山中学
  • 河池公司网站开发价格网站建设后备案多少钱
  • 用公司网站后缀做邮箱如何 申请个人网站
  • asp建站软件软件开发培训要学多久
  • 商丘市住房和城乡建设局网站做微商如何引流推广?怎么找客源?
  • 500强网站建设360收录提交入口
  • 常州网站建设选思创wordpress 显示微信
  • 建设网站技术标准布吉医院网站建设
  • 个人网站备案后可以随意建站吗php网站开发安全
  • 大型企业网站设计案例外贸网络营销如何选取关键词
  • 漯河市建设局网站网页不能运行wordpress
  • 网站微信建设方案北京做网站要多少钱
  • 如何做竞价网站数据监控wordpress装到哪里
  • 查询网站后台登陆地址网站建站商城
  • 怎么看网站是哪个系统做的关于加强网站建设的情况说明
  • cdr做的网站效果怎么直接用主流的网站建设软件
  • 深圳设计网站源码外贸型网站方案
  • 什么是分类信息网站营销广东佛山企业
  • 国家重点建设裤网站什么营销软件好用
  • 驾校官方网站 模板深圳彩票网站开发人员
  • 自行车网站模板网站页头图片
  • 仿淘宝网站源码 php西安哪家做网站好
  • 沈阳网站建设设计wordpress 中文摘要
  • 高端网站建设制作西双版纳 网站建设
  • 自己做的网站打开显示很慢硬件开发属于什么行业
  • 做宽屏网站公司网站备案名称