【51单片机快速入门指南】4: 软件 I2C

目录

  • 硬知识
    • I2C 介绍
    • I2C 物理层
    • I2C 协议层
      • 数据有效性规定
      • 起始和停止信号
      • 应答响应
      • 总线的寻址方式
      • 数据传输
  • 示例程序
    • Soft_I2C.c
    • Soft_I2C.h

普中51-单核-A2
STC89C52
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0


硬知识

       摘自《普中 51 单片机开发攻略》

I2C 介绍

       I2C(Inter-Integrated Circuit)总线是由 PHILIPS 公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单, 器件封装形式小,通信速率较高等优点。I2C 总线有两根双向信号线。一根是数据线 SDA,另一根是时钟线 SCL。由于其管脚少,硬件实现简单,可扩展性强等特点,因此被广泛的使用在各大集成芯片内。下面我们就从 I2C 的物理层与协议层来了解 I2C。

I2C 物理层

       I2C 通信设备常用的连接方式如下图所示:
在这里插入图片描述
它的物理层有如下特点:

  1. 它是一个支持多设备的总线。“总线”指多个设备共用的信号线。在 一个 I2C 通讯总线中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。
  2. 一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA),一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。
  3. 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。
  4. 总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平
  5. 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
  6. 具有三种传输模式:标准模式传输速率为 100kbit/s,快速模式为 400kbit/s,高速模式下可达 3.4Mbit/s,但目前大多 I2C 设备尚不支持高速模式。
  7. 连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制。

I2C 总线常用的一些术语:

  1. 主机:启动数据传送并产生时钟信号的设备;
  2. 从机:被主机寻址的器件;
  3. 多主机:同时有多于一个主机尝试控制总线但不破坏传输;
  4. 主模式:用 I2CNDAT 支持自动字节计数的模式; 位 I2CRM,I2CSTT,I2CSTP 控制数据的接收和发送;
  5. 从模式:发送和接收操作都是由 I2C 模块自动控制的;
  6. 仲裁:是一个在有多个主机同时尝试控制总线但只允许其中一个控制总线并使传输不被破坏的过程;
  7. 同步:两个或多个器件同步时钟信号的过程;
  8. 发送器:发送数据到总线的器件;
  9. 接收器:从总线接收数据的器件。

I2C 协议层

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

数据有效性规定

       I2C 总线进行数据传送时,时钟信号高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。如下图:
在这里插入图片描述
       每次数据传输都以字节为单位,每次传输的字节数不受限制。

起始和停止信号

       SCL 线为高电平期间,SDA 线由高电平向低电平的变化表示起始信号;SCL 线为高电平期间,SDA 线由低电平向高电平的变化表示终止信号。如下图:
在这里插入图片描述
       起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。

应答响应

       每当发送器件传输完一个字节的数据后,后面必须紧跟一个校验位,这个校验位是接收端通过控制 SDA(数据线)来实现的,以提醒发送端数据我这边已经接收完成,数据传送可以继续进行。这个校验位其实就是数据或地址传输过程中的响应。响应包括“应答(ACK)”和“非应答(NACK)”两种信号。作为数据接收端时,当设备(无论主从机)接收到 I2C 传输的一个字节数据或地址后,若希望对方继续发送数据,则需要向对方发送“应答(ACK)”信号即特定的低电平脉冲, 发送方会继续发送下一个数据;若接收端希望结束数据传输,则向对方发送“非应答(NACK)”信号即特定的高电平脉冲,发送方接收到该信号后会产生一个停止信号,结束信号传输。应答响应时序图如下:
在这里插入图片描述
       每一个字节必须保证是 8 位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有 9 位)。
       由于某种原因从机不对主机寻址信号应答时(如从机正在进行实时性的处理工作而无法接收总线上的数据),它必须将数据线置于高电平,而由主机产生一个终止信号以结束总线的数据传送。如果从机对主机进行了应答,但在数据传送一段时间后无法继续接收更多的数据时,从机可以通过对无法接收的第一个数据字节的“非应答”通知主机,主机则应发出终止信号以结束数据的继续传送。当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号。这个信号是由对从机的“非应答”来实现的。然后,从机释放 SDA 线,以允许主机产生终止信号。这些信号中,起始信号是必需的,结束信号和应答信号都可以不要。

总线的寻址方式

       I2C 总线寻址按照从机地址位数可分为两种,一种是 7 位,另一种是 10 位。采用 7 位的寻址字节(寻址字节是起始信号后的第一个字节)的位定义如下:
在这里插入图片描述

       D7~D1 位组成从机的地址。D0 位是数据传送方向位,为“ 0”时表示主机向从机写数据,为“1”时表示主机由从机读数据
       10 位寻址和 7 位寻址兼容,而且可以结合使用。10 位寻址不会影响已有 的 7 位寻址,有 7 位和 10 位地址的器件可以连接到相同的 I2C 总线。这里以 7 位寻址为例进行介绍。
       当主机发送了一个地址后,总线上的每个器件都将头 7 位与它自己的地址比较,如果一样,器件会判定它被主机寻址,其他地址不同的器件将被忽略后面的数据信号。至于是从机接收器还是从机发送器,都由 R/W 位决定的。从机的地址由固定部分和可编程部分组成。在一个系统中可能希望接入多个相同的从机,从机地址中可编程部分决定了可接入总线该类器件的最大数目。如一个从机的 7 位寻址位有 4 位是固定位,3 位是可编程位,这时仅能寻址 8 个同样的器件,即可以有 8 个同样的器件接入到该 I2C 总线系统中。

数据传输

       I2C 总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。在起始信号后必须传送一个从机的地址(7 位),第 8 位是数据的传送方向位(R/W),用“ 0”表示主机发送(写)数据(W),“ 1”表示主机接收数据(R)。每次数据传送总是由主机产生终止信号结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。
       在总线的一次数据传送过程中,可以有以下几种组合方式:

  1. 主机向从机发送数据,数据传送方向在整个传送过程中不变
    在这里插入图片描述
    注意:有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。A 表示应答,A 非表示非应答(高电平)。S 表示起始信号,P 表 示终止信号。
  2. 主机在第一个字节后,立即从从机读数据
    在这里插入图片描述
  3. 在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好相反在这里插入图片描述

示例程序

       由于89C5x 单片机没有硬件 IIC 接口,这里给出的是IO模拟的I2C程序

       stdint.h见【51单片机快速入门指南】1:基础知识和工程创建

Soft_I2C.c

修改自普中的例程,原版应答后未把SDA恢复高电平,且起始和结束的时序有误,将导致通信错误。
加入了对器件特定寄存器的连续读写函数。

#include "Soft_I2C.h"#define I2C_TIMEOUT_TIMES 100	//超时倍数//延时 用于等待应答时的超时判断 移植时需修改
void i2c_timeout_delay(void)	
{}void i2c_delay()	//每步的间隔 用于等待电平稳定和控制通讯速率
{}//SCL拉高 移植时需修改
void I2C_SCL_H(void)
{I2C_SCL = 1;
}//SCL拉低 移植时需修改
void I2C_SCL_L(void)
{I2C_SCL = 0;
}//SDA拉高 移植时需修改
void I2C_SDA_H(void)
{I2C_SDA = 1;
}//SDA拉低 移植时需修改
void I2C_SDA_L(void)
{I2C_SDA = 0;
}//读取SDA 移植时需修改
uint8_t I2C_SDA_Read(void)
{return I2C_SDA;
}/*******************************************************************************
* 函 数 名       : i2c_start
* 函数功能		 : 产生I2C起始信号
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void i2c_start(void)
{I2C_SDA_H();I2C_SCL_H();i2c_delay();I2C_SDA_L();	//当SCL为高电平时,SDA由高变为低i2c_delay();I2C_SCL_L();	//钳住I2C总线,准备发送或接收数据
}/*******************************************************************************
* 函 数 名         : i2c_stop
* 函数功能		   : 产生I2C停止信号
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void i2c_stop(void)
{I2C_SDA_L();I2C_SCL_H();i2c_delay();I2C_SDA_H();	//当SCL为高电平时,SDA由低变为高i2c_delay();
}/*******************************************************************************
* 函 数 名         : i2c_ack
* 函数功能		   : 产生ACK应答
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void i2c_ack(void)
{I2C_SCL_L();I2C_SDA_L();	//SDA为低电平i2c_delay();I2C_SCL_H();i2c_delay();I2C_SCL_L();I2C_SDA_H();	
}/*******************************************************************************
* 函 数 名         : i2c_nack
* 函数功能		   : 产生NACK非应答
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void i2c_nack(void)
{I2C_SCL_L();I2C_SDA_H();	//SDA为高电平i2c_delay();I2C_SCL_H();i2c_delay();I2C_SCL_L();
}/*******************************************************************************
* 函 数 名         : i2c_wait_ack
* 函数功能		   : 等待应答信号到来
* 输    入         : 无
* 输    出         : 1,接收应答失败0,接收应答成功
*******************************************************************************/
uint8_t i2c_wait_ack(void)
{uint16_t time_temp = 0;I2C_SCL_H();i2c_delay();while(I2C_SDA_Read())				//等待SDA为低电平{time_temp++;i2c_timeout_delay();if(time_temp > I2C_TIMEOUT_TIMES)	//超时则强制结束I2C通信{i2c_stop();return 1;}}I2C_SCL_L();return 0;
}/*******************************************************************************
* 函 数 名         : i2c_write_byte
* 函数功能		   : I2C发送一个字节
* 输    入         : dat:发送一个字节
* 输    出         : 无
*******************************************************************************/
void i2c_write_byte(uint8_t dat)
{uint8_t i = 0;I2C_SCL_L();for(i = 0; i<8; i++)	//循环8次将一个字节传出,先传高再传低位{if((dat & 0x80) > 0)I2C_SDA_H();elseI2C_SDA_L();dat <<= 1;i2c_delay();I2C_SCL_H();i2c_delay();I2C_SCL_L();i2c_delay();}
}/*******************************************************************************
* 函 数 名         : i2c_read_byte
* 函数功能		   : I2C读一个字节
* 输    入         : ack = 1时,发送ACK,ack = 0,发送nACK
* 输    出         : 应答或非应答
*******************************************************************************/
uint8_t i2c_read_byte(uint8_t ack)
{uint8_t i = 0, receive = 0;for(i = 0; i < 8; i++ )	//循环8次将一个字节读出,先读高再传低位{I2C_SCL_L();i2c_delay();I2C_SCL_H();receive <<= 1;if(I2C_SDA_Read())receive++;i2c_delay();}if (!ack)i2c_nack();elsei2c_ack();return receive;
}/*******************************************************************************
* 函 数 名         : i2c_mem_write
* 函数功能		   : I2C对指定器件、指定寄存器连续写入
* 输    入         : 器件地址、器件寄存器地址、待输入数据首地址、待输入数据长度
* 输    出         : 0: 成功 1:失败
*******************************************************************************/
uint8_t i2c_mem_write(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pData, uint16_t Len)
{i2c_start();i2c_write_byte(DevAddress << 1);if(i2c_wait_ack())return 1;i2c_write_byte(MemAddress);if(i2c_wait_ack())return 1;while(Len--){i2c_write_byte(*pData++);if(i2c_wait_ack())return 1;}i2c_stop();return 0;
}/*******************************************************************************
* 函 数 名         : i2c_mem_read
* 函数功能		   : I2C对指定器件、指定寄存器连续读取
* 输    入         : 器件地址、器件寄存器地址、数据缓冲区首地址、数据长度
* 输    出         : 0: 成功 1:失败
*******************************************************************************/
uint8_t i2c_mem_read(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pBuffer, uint16_t Len)
{				  i2c_start();  i2c_write_byte(DevAddress << 1);		//发送写命令	   if(i2c_wait_ack())return 1;i2c_write_byte(MemAddress); 			//发送字地址  if(i2c_wait_ack())return 1;   i2c_start();  	 	   i2c_write_byte(DevAddress << 1 | 1); 	//进入接收模式         			   if(i2c_wait_ack())return 1;while(Len--){*pBuffer++ = i2c_read_byte(Len!=0);	//读取字节	}i2c_stop();								//产生一个停止条件  return 0;
}/**写入8位寄存器的一个位。
* @参数 DevAddress	I2C从器件地址
* @参数 addr    	I2C从器件内部地址
* @参数 bitNum  	写入的比特位(0-7)
* @参数 data    	写入数据
* @返回值 返回状态 (0=成功)
*/
uint8_t i2c_write_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t Data)
{uint8_t b;if (!i2c_mem_read(DevAddress, addr, &b, 1)){b = (Data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));return i2c_mem_write(DevAddress, addr, &b, 1);	//写入数据}elsereturn 1;
}/**写入8位寄存器的多个位。
* @参数 DevAddress	I2C从器件地址
* @参数 addr     I2C从器件内部地址
* @参数 bitStart 第一位的写入位置(0-7)
* @参数 length   写的比特数(不超过8)
* @参数 Data     写入数据
* @返回值 返回状态 (0=成功)
*/
uint8_t i2c_write_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t Data)
{//      010 要写入的值// 76543210 比特位//    xxx   args: bitStart=4, length=3// 00011100 掩码字节// 10101111 原始值(样本)// 10100011 原始值 & ~掩码// 10101011 掩码 | 原始值uint8_t b, mask = 0;if (!i2c_mem_read(DevAddress, addr, &b, 1)){mask = (((1 << length) - 1) << (bitStart - length + 1));	//掩码Data <<= (bitStart - length + 1);	//把写入的数据移动到位Data &= mask;b &= ~(mask);b |= Data;return i2c_mem_write(DevAddress, addr, &b, 1);	//写入数据}elsereturn 1;
}
/**读取一个位从8位器件的寄存器。
* @参数 DevAddress	I2C从器件地址
* @参数 addr    I2C从器件内部地址
* @参数 bitNum  位的位置来读取(0-7)
* @参数 *data   数据存储地址
* @返回值(0=成功)
*/
uint8_t i2c_read_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t *Data)
{uint8_t b;if (!i2c_mem_read(DevAddress, addr, &b, 1)){*Data = b & (1 << bitNum);return 0;}else{return 1;}
}
/**读取8位寄存器的多个位。
* @参数 DevAddress	I2C从器件地址
* @参数 addr    I2C从器件内部地址
* @参数 bitStart第一位的位置读取(0-7)
* @参数 length  位读取@参数长度数(不超过8)
* @参数 *data   数据存储地址(即'101'任何bitStart位置读取将等于0X05)
* @返回值(0=成功)
*/
uint8_t i2c_read_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t *Data)
{// 01101001 读取字节// 76543210 比特位//    xxx   args: bitStart=4, length=3//    010   masked//   -> 010 shifteduint8_t b, mask = 0;if (!i2c_mem_read(DevAddress, addr, &b, 1)){mask = ((1 << length) - 1) << (bitStart - length + 1);b &= mask;b >>= (bitStart - length + 1);*Data = b;return 0;}elsereturn 1;
}

Soft_I2C.h

#ifndef SOFT_I2C_H_
#define SOFT_I2C_H_#include <STC89C5xRC.H>
#include "stdint.h"//定义I2C控制脚
sbit I2C_SCL = P2^1;				//SCL时钟线
sbit I2C_SDA = P2^0;				//SDA数据线//I2C所有操作函数				 
void i2c_start(void);				//发送I2C开始信号
void i2c_stop(void);	  			//发送I2C停止信号
uint8_t i2c_wait_ack(void); 		//I2C等待ACK信号
void i2c_ack(void);					//I2C发送ACK信号
void i2c_nack(void);				//I2C不发送ACK信号void i2c_write_byte(uint8_t txd);	//I2C发送一个字节
uint8_t i2c_read_byte(uint8_t ack);	//I2C读取一个字节
uint8_t i2c_mem_write(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pData, uint16_t Len);	//I2C对指定器件、指定寄存器连续写入
uint8_t i2c_mem_read(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pBuffer, uint16_t Len);	//I2C对指定器件、指定寄存器连续读取
uint8_t i2c_write_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t Data);			//写入8位寄存器的一个位
uint8_t i2c_write_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t Data);//写入8位寄存器的多个位
uint8_t i2c_read_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t *Data);			//读取一个位从8位器件的寄存器
uint8_t i2c_read_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t *Data);//读取8位寄存器的多个位#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【51单片机快速入门指南】4.1: I2C 与 AT24C02 (EEPROM) 的跨页连续读写

目录硬知识AT24Cxx 介绍引脚排列引脚说明存储结构器件寻址器件操作待机模式存储复位写操作字节写页写应答查询读操作当前地址读随机读顺序读示例程序24C02.c24C02.h测试程序main.c实验现象通讯波形写入部分读取部分普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof…

iOS Application Security

文章分A,B,C,D 4个部分。 A) iOS Application Security 下面介绍iOS应用安全&#xff0c;如何分析和动态修改app。 1&#xff09;iOS Application security Part 1 – Setting up a mobile pentesting platform Part1介绍如何在越狱的设备上搭建用来测试iOS安全的环境。 2&…

【51单片机快速入门指南】4.2: SSD1306 OLED屏(0.96寸、1.3寸)的I2C控制详解

目录硬知识SSD1306简介I2C 接口从机地址位&#xff08;SA0&#xff09;I2C 总线写数据命令解码器晶振电路和显示时间发生器复位图形显示数据RAM (GDDRAM)命令表基本命令表部分指令详解为 BANK0 设置对比度控制&#xff08;81h&#xff09;全部显示开启&#xff08;A4h/A5h&…

使用GNS3和Cisco IOU搭建路由交换实验-安装篇

如何使用GNS3和Cisco IOU搭建路由交换实验-安装篇GNS3软件的安装建议大家从官网直接下载最新版本的GNS3&#xff0c;官网连接http://www.gns3.com/根据系统类型选择相应的版本&#xff0c;这里我选择的是Windwos系统的最新版本1.3.2下载好安装包后直接运行安装包&#xff0c;在…

1787: [Ahoi2008]Meet 紧急集合

1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1482 Solved: 652[Submit][Status][Discuss]Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 Sample Output 5 2 2 5 4 1 6 0 HINT Sou…

一步一步学Vue(四)

接上篇。上篇中给出了代码框架&#xff0c;没有具体实现&#xff0c;这一篇会对上篇定义的几个组件进行分别介绍和完善&#xff1a; 1、TodoContainer组件 TodoContainer组件&#xff0c;用来组织其它组件&#xff0c;这是react中推荐的方式&#xff0c;也是redux中高阶组件一般…

【51单片机快速入门指南】4.3: I2C读取MPU6050陀螺仪的原始数据

目录硬知识特性参数MPU6050 简介模块重要寄存器简介电源管理寄存器 1陀螺仪配置寄存器加速度传感器配置寄存器FIFO 使能寄存器陀螺仪采样率分频寄存器配置寄存器电源管理寄存器 2陀螺仪数据输出寄存器加速度传感器数据输出寄存器温度传感器示例程序MPU6050.cMPU6050.hmain.c实验…

OSM数据的获取及格式转换

转自 &#xff1a;http://blog.sina.com.cn/s/blog_72f0b6080102w39z.html 前言&#xff1a;本篇博文将介绍如何对OSM数据进行获取&#xff0c;以及格式的转换&#xff08;转为shapefile格式&#xff09;。以供OSM数据获取失败、OSM editor操作失败的朋友参考。由于并不是多么高…

再读TCP/IP网络7层协议

随着工作的深入&#xff0c;每次读这7层协议&#xff0c;每次都有不同的理解。 分层名 分层号 描述 比喻 应用层Application La…

oracle复习笔记

2019独角兽企业重金招聘Python工程师标准>>> 1.oracle相关认证&#xff1a;OCA:Oracle认证专员&#xff0c;OCP:Oracle专家认证&#xff0c;OCM:Oracle认证大师。 2.1979年,Oracle2发布。 3.Oracle数据库特点&#xff1a;支持多用户&#xff0c;大事务量的事务处理&…

【51单片机快速入门指南】4.3.1: MPU6050调用DMP库获取四元数和欧拉角

目录相关介绍DMP库相关DMP加载步骤&#xff1a;DMP设置数据写入更新DMPDMP数据包结构程序实现DMP.cDMP.h测试程序四元数实验现象欧拉角的获取普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 上位机&#xff1a;Vofa 1.3.10 相关…

cardsui-for-android

https://github.com/Androguide/cardsui-for-android cardsui-for-android-master.zip

spoj 2 Prime Generator

题目&#xff1a;Prime Generator 思路&#xff1a;分段筛素数 #include <cstdio> #include <iostream> #include <cmath> #include <algorithm> #include <cstring> #include <map> using namespace std; #define maxn 40000 int n_prime…

LTDC/DMA2D—液晶显示

本章参考资料&#xff1a;《STM32F4xx 参考手册 2》、《STM32F4xx 规格书》、库帮助文档《stm32f4xx_dsp_stdperiph_lib_um.chm》。关于开发板配套的液晶屏参数可查阅《5.0 寸液晶屏数据手册》配套资料获知。 显示器简介显示器属于计算机的 I/O 设备&#xff0c;即输入输出设备…

【51单片机快速入门指南】4.3.2: MPU6050:一阶互补滤波、二阶互补滤波和卡尔曼滤波获取欧拉角

目录源码MPU6050_Filter.cMPU6050_Filter.h使用方法测试程序一阶互补滤波效果二阶互补滤波效果卡尔曼滤波效果总结普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 上位机&#xff1a;Vofa 1.3.10 参考资料&#xff1a; MPU6050…

NGUI基础-三大基础组件之Root组件

NGUI NGUI&#xff08;Next-Gen UI&#xff09;是一款用于Unity游戏引擎的UI插件&#xff0c;它提供了一套功能强大、灵活易用的界面开发工具。在NGUI中&#xff0c;Root&#xff08;根节点&#xff09;是一个重要的概念。 基础组件之Root Root是NGUI中的最高层级节点&#…

【转】android 中如何限制 EditText 最大输入字符数

原文网址&#xff1a;http://blog.csdn.net/fulinwsuafcie/article/details/7437768 方法一&#xff1a; 在 xml 文件中设置文本编辑框属性作字符数限制 如&#xff1a;android:maxLength"10" 即限制最大输入字符个数为10 方法二&#xff1a; 在代码中使用InputFilte…

【51单片机快速入门指南】4.3.3: MPU6050使用Mahony AHRS算法实现六轴姿态融合获取四元数、欧拉角

目录源码Mahony_6.cMahony_6.h使用方法测试程序main.c效果STC89C516 32MHz Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 上位机&#xff1a;Vofa 1.3.10 移植自MPU6050姿态解算——Mahony互补滤波 —— 大写的小写字母 加入了输入数据范围的自动处理…

linux文件系统及bash基础特性

linux文件系统 一、根文件系统 linux被识别的第一个被称为根之间关联的文件系统叫做根文件系统&#xff08;rootfs&#xff09;&#xff0c;其他分区要想被读到&#xff0c;需要挂载到根目录的某个挂载点&#xff08;根的子目录&#xff09;上。根文件系统至关重要&#xff0c;…

【51单片机快速入门指南】4.3.4: MPU6050使用Madgwick AHRS算法实现六轴姿态融合获取四元数、欧拉角

目录源码Madgwick_6.cMadgwick_6.h使用方法测试程序main.c效果STC89C516 32MHz Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 上位机&#xff1a;Vofa 1.3.10 移植自AHRS —— LOXO&#xff0c;算法作者&#xff1a;SOH Madgwick 源码 为了避免所用R…