51单片机IIC时序详细分析并驱动EEPROM存储方案应用------day9

news2025/1/4 19:20:16

51单片机IIC驱动EEPROM存储方案应用------day9
1.常见存储器件: 铁电, E2PROM, FLASH。
共同特点: 掉电后数据不丢失
各自特点:
铁电: 理论上可以无限次擦写, 操作简单, 但是容量小。
E2PROM: 理论上擦写次数在30W到100W的不等,操作简单, 容量中等。 应用: 考勤机。
FLASH: 理论上擦写次数在10W到100W不等, 容量很大, 但操作较复杂, 若要改变一个字节就要改变整个扇区。 STC单片机的EEPROM是由FLASH模拟的。
2.IIC总线
I2C总线最主要的优点是其简单性和有效性。 由于接口直接在组件之上, 因此I2C总线占用的空间非常小, 减少了电路板的空间和芯片管脚的数量, 降低了互联成本。 I2C总线的另一个优点是, 它支持多主机, 其中任何能够进行发送和接收的设备都可以成为主机。 一个主控能够控制信号的传输和时钟频率。当然, 在任何时间点上只能有一个主机。
2、 I2C总线是由数据线SDA和时钟SCL构成的串行总线, 可发送和接收数据。 各种I2C均并联在这条总线上, 但就像电话机一样只有拨通各自的号码才能工作, 所以每个电路和模块都有唯一的地址。
3.硬件原理图:
在这里插入图片描述
WP为高电平时只能读不能写,防止误写。
WR为低电平时可读可写。
4.I2C的起始和停止
起始信号:SCL线为高电平期间, SDA线由高电平向低电平的变化表示起始信号;
停止条件:SCL线为高电平期间, SDA线由低电平向高电平的变化表示终止信号。
SCL是主裁判, SDA是副裁判。
在这里插入图片描述

//SCL为高电平时SDA由高电平变为低电平表示IIC开始信号
void I2C_Start_Fun(void)
{
	I2C_SDA_DA = 1;    //SDA置高
	Delay_I2C();      // 延时子程序
	I2C_SCL_CK = 1;		//SCL置高
	Delay_I2C();  // 延时子程序
	I2C_SDA_DA = 0;	  //SDA置低
	Delay_I2C();  // 延时子程序
	I2C_SCL_CK = 0;	
}
//SCL为高电平期间SDA由低电平变为高电平为停止信号
void I2C_Stop_Fu(void)
{
	I2C_SCL_CK = 0;
    Delay_I2C();
	I2C_SDA_DA = 0;
	Delay_I2C();
	I2C_SCL_CK = 1;
	Delay_I2C();
	I2C_SDA_DA = 1;
	Delay_I2C();
}

IIC数据传输:
SCL为高电平期间, 数据线上的数据必须保持稳定, 只有SCL信号为低电平期间SDA状态才允许变化
在这里插入图片描述
I2C与UART不同的地方首先在于先传高位, 后传送低位。 UART先传低位后传高位
UART发送时序如下图:低位在前
在这里插入图片描述
I2C先传高位后传低位时序如下图所示:
在这里插入图片描述
主机写数据时, 每发送一个字节, 接收机需要回复一个应答位“0”, 通过应答位来判断从机是否接收成功
主机读数据时, 接收一个字节结束后, 主机也需要发送一应答位“0”, 但是当接收最后一个字节结束后, 则需发送一个非应答位(应答位取反)“1”, 发完了1后, 再发一个停止信号, 最终结束通信。

写数据流程:
首先I2C起始信号, 然后发送首字节, 即器件( EEPROM)地址。并且在读写方向位上选择“ 写操作” 方向。 (0xa0) <哪一个芯片>
第二个字节, 发送数据的存储地址, 就是要读取的数据所存
储在EEPROM中的位置。 <存在芯片的哪个位置>
第三个字节, 发送要存储的数据第一个字节, 第二个字
节……
在写数据的过程中, 都要等待EEPROM返回一个“ 应答位” 。
EEPROM的地址根据电路的A2A1A0决定,接地为0.高电平为1
最后一位R/W为读写位,读为1,写为0
故:写地址为0xa0 1010 0000
读地址为0xa1 1010 0001
在这里插入图片描述
在这里插入图片描述

/*****************************************************************************
** 函数名称:write_eeprom
** 功能描述:读取EEPROM数据函数(可多片共存)
** 输    入:E2中目的地址addr
** 输    出:读取的数据
******************************************************************************/
void write_eeprom(uchar addr, uchar databyte)
{
	I2C_Start_Fun();
	I2C_Write_Data(0xa0);		//<哪一个芯片>
	I2C_Write_Data(addr);		//	<存在芯片的哪个位置>
	I2C_Write_Data(databyte);
	I2C_Stop_Fu();				//停止位

}
/*****************************************************************************
** 函数名称:I2C_Write_Data
** 功能描述:向I2C总线发送一个字节数据,并检测应答
** 输    入:待发送字节byte
** 输    出:无
** 全局变量:无
** 调用模块:Delay_I2C()
** 可移植性:直接移植
******************************************************************************/
void I2C_Write_Data(uchar Byte)
{
	uchar mask;
	uchar i;
	uchar j;

	mask = 0x80;
	for(i = 0; i < 8; i++)      //发送8位数据
	{
		I2C_SCL_CK = 0;     	//SCL为低电平时才允许SDA数据变化
		Delay_I2C();			//延时,保证时序稳定
		if((mask & Byte) == 0)	//1000 0000 &Byte 设Byte=95H 1000 0000& 1001 0101   如果最高位为0则SDA发送0 如果最高位为1则发送SDA为高
		{
			I2C_SDA_DA = 0;
		}
		else
		{
			I2C_SDA_DA = 1;
		}
		mask >>= 1;  //0x40   0100 0000&1001 0101
		Delay_I2C();
		I2C_SCL_CK = 1;  //拉高保持数据
		Delay_I2C();     
	}
	I2C_SCL_CK = 0;
	I2C_SDA_DA = 1;  //释放总线
	Delay_I2C();
	I2C_SCL_CK = 1;
	j = I2C_SDA_DA;  //读取应答位
	Delay_I2C();
	I2C_SCL_CK = 0;	//方便下次使用
}

在这里插入图片描述

I2C总线通过上拉电阻接正电源。 当总线空闲时, 两根线均为高电平。 连到总线上的任一器件输出的低电平, 都将使总线的信号变低, 即各器件的SDA及SCL都是线“ 与” 关系(只要有一个器件是低电平总线都是低电平)
在这里插入图片描述
IIC读数据流程:<根据手册的时序图来>
首先I2C起始信号, 然后发送首字节, 即器件( EEPROM)地址。 并且在读写方向位上选择“ 写操作” 方向。
第二个字节, 发送数据的存储地址, 就是要读取的数据所
存储在EEPROM中的位置。
第三个字节, 重新发送I2C起始信号和器件地址, 并且在方向位上选择**“ 读操作”** 方向。
在前三个字节操作过程, 都要等待器件给与回应一个“ 应答位0”
第四个字节, 接收从器件发回的首字节后, 单片机要主动返回一个“ 非应答位1”……
注意事项: 读数据前, 必须将SDA口置为1
在这里插入图片描述

/*****************************************************************************
** 函数名称:read_eeprom
** 功能描述:读取EEPROM数据函数(可多片共存)
** 输    入:E2中目的地址addr
** 输    出:读取的数据
** 全局变量:无
** 调用模块:I2CStart(),I2CSend(),I2CStop()
******************************************************************************/
uchar read_eeprom(uchar addr)
{
	uchar databyte;

	I2C_Start_Fun(); //开始
	I2C_Write_Data(0xa0);  //<哪一个芯片>
	I2C_Write_Data(addr);//将读取的地址告诉EEPROM
	I2C_Start_Fun();//开始
	I2C_Write_Data(0xa1); //发送读取命令
	databyte = I2C_Read_LData(); //读取数据
	I2C_Stop_Fu();  //停止
	return databyte;	
}

读取子函数:

/*****************************************************************************
** 函数名称:I2C_Read_Ack
** 功能描述:从I2C总线读取一个字节数据,并发送应答
** 输    入:无
** 输    出:接收到的字节byte
** 全局变量:无
** 调用模块:Delay_us()
** 可移植性:直接移植
******************************************************************************/
uchar I2C_Read_Ack(u8 ack)
{
	uchar i;
	uchar Byte;
	Byte = 0;
	for(i=0;i<8;i++)
	{
		I2C_SCL_CK = 0;
		I2C_SDA_DA = 1;//先释放总线线与关系
		Delay_I2C();
		I2C_SCL_CK = 1;//高电平时才会把数据读取出来
		Delay_I2C();
		Byte <<= 1;  //0x00<<1=0x00
		if(I2C_SDA_DA==1) {Byte |= 0x01;}//0x00|0x01=0x01
		Delay_I2C();
	}
	I2C_SCL_CK = 0;
	Delay_I2C();
	I2C_SDA_DA = 0;	//发送应答位
	Delay_I2C();
	I2C_SCL_CK = 1;//保持数据
	Delay_I2C();
	I2C_SCL_CK = 0;//方便下次使用
	
	return Byte;
}	
/*****************************************************************************
** 函数名称:I2C_Read_LData
** 功能描述:从I2C总线读取最后一个字节数据,并发送非应答位
** 输    入:无
** 输    出:接收到的字节Byte
** 全局变量:无
** 调用模块:Delay_I2C()
** 可移植性:直接移植
******************************************************************************/
uchar I2C_Read_LData(void)
{
	uchar Byte;
	uchar i;

	Byte = 0;
	for(i = 0; i < 8; i++)
	{
		I2C_SCL_CK = 0;
		I2C_SDA_DA = 1;
		Delay_I2C();
		I2C_SCL_CK = 1;
		Delay_I2C();
		Byte <<= 1;	 
		if(I2C_SDA_DA == 1)
		{
			Byte |= 0x01;
		}
		Delay_I2C();
	} 
	I2C_SCL_CK = 0;
	I2C_SDA_DA = 1;
	Delay_I2C();
	I2C_SCL_CK = 1;
	Delay_I2C();
	I2C_SCL_CK = 0;
	
	return Byte;
}

在这里插入图片描述
在第9个时钟时,数据发送端会释放SDA的控制权,由数据接收端控制SDA,若SDA为高电平,表示非应答信号(NACK)低电平表示应答信号ACK
程序源码:

IIC文件:
#define I2CDelay()  {_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL_IO = P0^6;
sbit I2C_SDA_IO = P0^7;

/* 产生总线起始信号 */
void I2C_Start_Fun()
{
    I2C_SDA_IO = 1; //首先确保SDA、SCL都是高电平
    I2C_SCL_IO = 1;
    I2CDelay();
    I2C_SDA_IO = 0; //先拉低SDA
    I2CDelay();
    I2C_SCL_IO = 0; //再拉低SCL
}


/* 产生总线停止信号 */
void I2C_Stop_Fun()
{
    I2C_SCL_IO = 0; //首先确保SDA、SCL都是低电平
    I2C_SDA_IO = 0;
    I2CDelay();
    I2C_SCL_IO = 1; //先拉高SCL
    I2CDelay();
    I2C_SDA_IO = 1; //再拉高SDA
    I2CDelay();
}


/* I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 */
bit I2C_Write_Fuc(unsigned char dat)
{
    bit ack;  //用于暂存应答位的值
    unsigned char mask;  //用于探测字节内某一位值的掩码变量

    for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
    {
        if ((mask&dat) == 0)  //该位的值输出到SDA上
            I2C_SDA_IO = 0;
        else
            I2C_SDA_IO = 1;
        I2CDelay();
        I2C_SCL_IO = 1;       //拉高SCL
        I2CDelay();
        I2C_SCL_IO = 0;       //再拉低SCL,完成一个位周期
    }
    I2C_SDA_IO = 1;           //8位数据发送完后,主机释放SDA,以检测从机应答
    I2CDelay();
    I2C_SCL_IO = 1;           //拉高SCL
    ack = I2C_SDA_IO;         //读取此时的SDA值,即为从机的应答值
    I2CDelay();
    I2C_SCL_IO = 0;           //再拉低SCL完成应答位,并保持住总线

    return (~ack);            //应答值取反以符合通常的逻辑:
	                          //0=不存在或忙或写入失败,1=存在且空闲或写入成功
}

unsigned char I2C_Read_NAK()
{
	unsigned char mask;
	unsigned char dat;

	I2C_SDA_IO = 1;
	for(mask=0x80; mask!=0; mask>>=1)
	{
		I2CDelay();
		I2C_SCL_IO = 1;
		if(I2C_SDA_IO == 0)
			dat &= ~mask;
		else
			dat |= mask;
		I2CDelay();
		I2C_SCL_IO = 0;
	}
	I2C_SDA_IO = 1;
	I2CDelay();
	I2C_SCL_IO = 1;
	I2CDelay();
	I2C_SCL_IO = 0;

	return dat;
}

unsigned char I2C_Read_ACK()
{
	unsigned char mask;
	unsigned char dat;

	I2C_SDA_IO = 1;
	for(mask=0x80; mask!=0; mask>>=1)
	{
		I2CDelay();
		I2C_SCL_IO = 1;
		if(I2C_SDA_IO == 0)
			dat &= ~mask;
		else
			dat |= mask;
		I2CDelay();
		I2C_SCL_IO = 0;
	}
	I2C_SDA_IO = 0;
	I2CDelay();
	I2C_SCL_IO = 1;
	I2CDelay();
	I2C_SCL_IO = 0;

	return dat;
}
main.c文件
#include <reg52.h>
#include "inc/hc595.h"
#include "inc/delay.h"

code unsigned char ucDataOneTab[10] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f,0x6f};
//uchar code LEDSEG1[]= {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xc6,0X89};//0~9,C,H,正
//uchar code LEDSEG2[]= {0xC0,0xCF,0xA4,0x86,0x8B,0x92,0x90,0xC7,0x80,0x82,0xF0,0X89};//0~9,C,H,倒
code unsigned char ucDataTwoTab[8] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};
unsigned char disbuf[8] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07};

extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
extern void I2C_Start_Fun();
extern void I2C_Stop_Fun();
extern unsigned char I2C_Read_NAK();
extern bit I2C_Write_Fuc(unsigned char dat);
unsigned char E2ReadByte(unsigned char addr);
void E2WriteByte(unsigned char addr, unsigned char dat);

void main()
{
    unsigned char dat,i;
    unsigned char str[10];

	//E2WriteByte(0x02, 0);    //再写回到对应的地址上

    //InitLcd1602();   //初始化液晶
    dat = E2ReadByte(0x02);    //读取指定地址上的一个字节
    str[0] = (dat/100);  //转换为十进制字符串格式
    str[1] = (dat/10%10) ;
    str[2] = (dat%10) ;
    //str[3] = '\0';
    //LcdShowStr(0, 0, str);     //显示在液晶上
    dat++;                     //将其数值+1
    E2WriteByte(0x02, dat);    //再写回到对应的地址上
	//disbuf[2] = ucDataOneTab[str[2]];
	//disbuf[1] = ucDataOneTab[str[1]];
	//disbuf[0] = ucDataOneTab[str[0]];
	
	disbuf[2] = ucDataOneTab[str[2]];
	disbuf[1] = ucDataOneTab[str[1]];
	disbuf[0] = ucDataOneTab[str[0]];		
    
    while (1)
	{
	   for (i = 0; i < 8; i++ )
	  {
           SendData(disbuf[i], ucDataTwoTab[i]);   
		   Delay1ms(1);
      }	  
	}
}

unsigned char E2ReadByte(unsigned char addr)
{
	unsigned char dat;

	I2C_Start_Fun();
	I2C_Write_Fuc(0x50<<1);
	I2C_Write_Fuc(addr);
	I2C_Start_Fun();	
	I2C_Write_Fuc((0x50<<1) |0x01);
	dat = I2C_Read_NAK();
	I2C_Stop_Fun();

	return dat;
}

void E2WriteByte(unsigned char addr, unsigned char dat)
{
	I2C_Start_Fun();
	I2C_Write_Fuc(0x50<<1);
	I2C_Write_Fuc(addr);
	I2C_Write_Fuc(dat);
	I2C_Stop_Fun();
}

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

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

相关文章

进销存管理系统

技术&#xff1a;Java等摘要&#xff1a;进销存管理系统是为了实现企业仓库商品管理的系统化、规范化和自动化&#xff0c;从而提高企业管理效率而设计开发的管理信息系统。它完全取代了过去一直用人工管理的工作方式&#xff0c;避免了由于管理人员手工操作上的疏忽以及管理质…

【Linux】基本系统维护命令

&#x1f60a;&#x1f60a;作者简介&#x1f60a;&#x1f60a; &#xff1a; 大家好&#xff0c;我是南瓜籽&#xff0c;一个在校大二学生&#xff0c;我将会持续分享C/C相关知识。 &#x1f389;&#x1f389;个人主页&#x1f389;&#x1f389; &#xff1a; 南瓜籽的主页…

P6专题:P6模块/组件简要介绍(P6,Professional,API,TeamMember,WebService)

目录 一 引言 二 P6组件 P6 P6 Professional Team Member PC Team Member App Integration API WebService 一 引言 Oracle Primavera P6 EPPM 是基于“角色”设计的企业级项目管理专业软件&#xff0c;包含了如下几个组件/模块&#xff0c;解决不同维度的问题&#x…

linux入门---shell感性认识

命令行解释器 我们目前学了很多的指令&#xff0c;并且这些指令在磁盘上都是以文件的形式存在的&#xff1a; 通过file可以查看这些文件的信息&#xff0c;我们发现这些文件都含有executable这个单词&#xff0c;那么executable的意思就是这个文件在x86-64平台下是可以执行的…

【巨人的肩膀】JAVA面试总结(五)

1、&#x1f4aa; 目录1、&#x1f4aa;1.1、什么是Spring框架1.2、Spring、SpringMVC、SpringBoot三者关系1.3、谈谈对于Spring IoC 和 DI 的理解1.4、什么是依赖注入&#xff1f;可以通过多少种方式完成依赖注入1.5、什么是Spring Bean1.6、将一个类声明为Bean的注解有哪些1.…

PMP是什么意思?适合哪些人学呢?

PMP简而言之&#xff0c;就是提高项目管理理论基础和实践能力的考试。 官方一点的说明呢&#xff0c;就是&#xff1a;PMP证书全称为Project Management Professional&#xff0c;也叫项目管理专业人士资格认证。 PMP证书由美国项目管理协会(PMI)发起&#xff0c;是严格评估项…

Docker镜像的内部机制

Docker镜像的内部机制 镜像就是一个打包文件&#xff0c;里面包含了应用程序还有它运行所依赖的环境&#xff0c;例如文件系统、环境变量、配置参数等等。 环境变量、配置参数这些东西还是比较简单的&#xff0c;随便用一个 manifest 清单就可以管理&#xff0c;真正麻烦的是文…

【VC 7/8】vCenter Server 基于文件的备份和还原Ⅱ——使用 FTP 协议备份 VC(VAMI 英文)

目录2. 备份 vCenter Server2.1 使用 FTP 协议备份 VC&#xff08;1&#xff09;登录 vCenter Server 管理界面&#xff08;2&#xff09;进入Backup页面&#xff08;3&#xff09;配置 Backup Schedule&#xff08;4&#xff09;开始备份&#xff08;5&#xff09;备份成功&am…

信息安全与数学基础-笔记-④二次同余方程

知识目录二次同余方程的解欧拉判别式Legendre (勒让德符号)二次同余方程的解 什么是二次同余方程的解 注意这里二次同余方程和一次同余方程是不一样的 在x2x^2x2 三 a (mod m) 方程中举例 ↓ 解即剩余类&#xff0c;因为是模m&#xff0c;所以我们在 [ 0, m-1 ]中逐个代入看是…

HTML DOM

通过 HTML DOM&#xff0c;可访问 JavaScript HTML 文档的所有元素。HTML DOM (文档对象模型)当网页被加载时&#xff0c;浏览器会创建页面的文档对象模型&#xff08;Document Object Model&#xff09;。HTML DOM 定义了用于 HTML 的一系列标准的对象&#xff0c;以及访问和处…

Compaction的原理与Hbase Compaction实现

HBase中的用户数据在LSM树体系架构中最终会形成一个一个小的HFile文件。我们知道&#xff0c;HFile小文件如果数量太多会导致读取低效。为了提高读取效率&#xff0c;LSM树体系架构设计了一个非常重要的模块——Compaction。Compaction核心功能是将小文件合并成大文件&#xff…

现代C++教程 笔记

写在前面 记录一下《现代C教程》中的要点。 现代C是指C11之后的语法特性&#xff0c;如无特别说明&#xff0c;下面的语法特性均是C11后才可使用。 一、语言可用性的强化 1. 常量 1.1 nullptr 作用&#xff1a; 代替NULL赋空指针&#xff1b; 使用&#xff1a; char *a …

进制的转换:

任意进制转换成十进制&#xff1a;十进制数位置上数*当前进制的位权二进制与八进制、十六进制之间的转换&#xff1a;3个二进制一个8进制4个二进制一个16进制各种进制的书写方式:十进制转换任意进制,分为整数部分和小数部分&#xff1a;整数部分&#xff08;除基取余法&#xf…

SpringCloud的五大组件功能

SpringCloud的五大组件 EurekaRibbonHystrixZuulConfig 一、Eureka 作用是实现服务治理&#xff0c;即服务注册与发现。 Eureka服务器相当于一个中介&#xff0c;负责管理、记录服务提供者的信息。服务调用者不需要自己寻找服务 &#xff0c;而是把需求告诉Eureka &#x…

IronWebScraper 2023.2.2 Crack

关于 .NET 的 IronWebScraper 用于从 HTML Web 应用程序中提取干净的结构化数据的 C# 框架。 IronWebScraper for .NET 是一个 C# 网络抓取库&#xff0c;它允许开发人员模拟和自动化人类浏览行为&#xff0c;以从 Web 应用程序中提取内容、文件和图像作为本机 .NET 对象。Iron…

基于Flink SQL CDC Mysql to Mysql数据同步

基于Flink SQL CDC Mysql to Mysql数据同步 Flink CDC有两种方式同步数据库&#xff1a; 一种是通过FlinkSQL直接输入两表数据库映射进行数据同步&#xff0c;缺点是只能单表进行同步&#xff1b;一种是通过DataStream开发一个maven项目&#xff0c;打成jar包上传到服务器运行…

考研第一天,汤家凤基础班,连续与极限复习笔记

函数连续极限性质保号性证明极值点&#xff1a;夹逼准则二项式展开根号下&#xff0c;大于一&#xff0c;小于一的讨论直接放缩求和分子分母齐次&#xff0c;且分母大一次&#xff0c;用积分单调有界存在极限几个重要的切线放缩证明有界&#xff0c;然后放缩求单调证明有界&…

智慧高校数字化校园数据中心建设方案

本资料来源网络&#xff0c;知识分享&#xff0c;仅供个人学习&#xff0c;请勿商用。完整资料阅览见文末&#xff0c;部分资料内容&#xff1a; 一、 云数据中心建设规划云计算平台逻辑架构图 云设施即服务(IaaS&#xff0c;Cloud Infrastructure as a Service)&#xff1a;系…

信息系统项目管理师——信息化和信息系统

信息的特征&#xff08;掌握&#xff09; 1、客观性 2、普遍性 3、无限性 4、动态性&#xff1a;信息是随着时间的变化而变化的。 5、相对性 6、依附性&#xff1a; 1&#xff09;信息是客观世界的反映&#xff0c;任何信息必然由客观事物所产生&#xff0c;不存在无源的信息。…

视觉SLAM十四讲ch5 相机与图像笔记

视觉SLAM十四讲ch5 相机与图像本讲目标上讲回顾相机模型小孔成像模型&#xff08;单目模型&#xff09;畸变双目模型RGB-D相机本讲目标 ●理解理解针孔相机的模型、内参与径向畸变参数。 ●理解一个空间点是如何投影到相机成像平面的。 ●掌握OpenCV的图像存储与表达方式。 ●…