第一次接触 51 单片机时,我被它强大的功能和广泛的应用所吸引。一块小小的芯片,却能控制各种外部设备,实现诸如灯光闪烁、电机转动等有趣的功能,这让我对它充满了好奇和期待,这自然而然也就激发了我对于单片机的学习兴趣(其中自然也包括为了打比赛而做准备doge),然而,学习的道路并非一帆风顺。面对复杂的硬件电路和晦涩的编程语言,我感到了前所未有的迷茫。寄存器、引脚、指令集…… 这些陌生的概念像一团乱麻,让我无从下手。特别是在学习汇编语言时,那些看似简单却又含义深刻的指令,常常让我花费大量的时间去理解和记忆。
在学习过程中令我记忆特别深刻的是中断系统和I2C总线,通讯协议那里,在学习过程这两个模块的过程中我深表煎熬,一个两小时的课程要花费我一天的时间观看,在听不懂的时候及时暂停,稍加思索,来回观看从而加深自己的理解。现在来讲述一下自己在学习这两个模块自己的一些心得与体会。
一、中断系统
首先你的知道什么是中断系统,顾名思义中断系统是指计算机在执行程序的过程中,当出现某些紧急事件或特殊情况时,暂时停止正在执行的程序,转去处理这些事件或情况,处理完毕后再返回原来的程序继续执行的机制和相关硬件、软件的总称(过程如下表所示)。
然后你就要知道中断系统有哪些作用可以实现什么功能,这样你才能对中断系统有更进一步的认识和了解。
作用:
提高 CPU 的工作效率:CPU 无需一直查询外部设备的状态,外部设备可以在需要时主动向 CPU 发送中断请求,让 CPU 及时为其服务,使 CPU 和外部设备能并行工作,大大提高了整个系统的运行效率。
实现实时处理:对于一些实时性要求较高的任务,如工业控制中的数据采集和处理、航空航天中的飞行控制等,中断系统可以确保这些任务在规定的时间内得到及时处理,保证系统的稳定性和可靠性。
方便故障处理:当计算机系统出现故障或异常时,如硬件错误、软件运行错误等,中断系统可以及时捕捉到这些事件,并转去执行相应的故障处理程序,进行错误诊断和恢复操作,提高系统的容错能力。
当然在学习51单片机过程中尚且只需用到提高CPU效率的作用,在主函数需要请求中断的时候进入中断系统,执行完之后回到进入前的位置继续完成相应的功能。
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18;
TH0 = 0xFC;
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
}
}
这就是51单片机定时器所需要的一个中断模块,该模块的作用是让主函数定时器部分计时1ms秒后进入中断,在中断执行1000次循环从而起到溢出一次就代表着1s计时的作用,最后在循环往复的递增实现定时器数字时钟的功能。
二、I2C总线与时序结构
1.I2C总线的结构
I2C总线的结构大概包括两根信号线和上拉电阻两部分。两根信号线分别是串行数据线(SDA),串行时钟线(SCL)。SDA用于在主设备和从设备之间传输数据,是双向的,数据的传输方向可以根据通信的需要进行改变。SCL由主设备产生,用于同步 SDA 线上的数据传输,所有数据传输都在 SCL 的时钟信号控制下进行。
上拉电阻:SDA 和 SCL 线都需要通过上拉电阻连接到正电源。当总线空闲时,这两条线都处于高电平状态。任何连接到总线上的设备都可以通过将线路拉低来驱动总线。
2.时序结构
时序结构主要包括起始条件、停止条件、数据传输、应答信号等部分,只有将这几部分结构完美的融合在一起才能完成一次数据的传输。
void I2C_Start(void)
{
I2C_SDA=1;
I2C_SCL=1;
I2C_SDA=0;
I2C_SCL=0;
}
当串行时钟线(SCL)为高电平时,串行数据线(SDA)由高电平向低电平的跳变,被定义为起始条件。起始条件标志着一次新的 I2C 通信的开始。
void I2C_Stop(void)
{
I2C_SDA=0;
I2C_SCL=1;
I2C_SDA=1;
}
当 SCL 为高电平时,SDA 由低电平向高电平的跳变,代表停止条件。停止条件表示一次 I2C 通信的结束。
在发送一位之前SCL处于低电平,然后主机把发送的数据放在SDA上,之后拉高SCL,从机读取发送的一位数据,然后低位在前依次循环八次读取一个字节的数据。
void I2C_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
I2C_SDA=Byte&(0x80>>i);
I2C_SCL=1;
I2C_SCL=0;
}
}
unsigned char I2C_ReceiveByte(void)
{
unsigned char i,Byte=0x00;
I2C_SDA=1;
for(i=0;i<8;i++)
{
I2C_SCL=1;
if(I2C_SDA){Byte|=(0x80>>i);}
I2C_SCL=0;
}
return Byte;
}
接受一个字节跟发送一个字节类似,不过区别在于读取一位时变成了从机把数据放在SDA上拉高SCL主机读取数据,然后低位在前循环八次读取一个字节的数据。
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_SendByte(Data);
I2C_ReceiveAck();
I2C_Stop();
}
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
unsigned char Data;
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS|0x01);
I2C_ReceiveAck();
Data=I2C_ReceiveByte();
I2C_SendAck(1);
I2C_Stop();
return Data;
}
最后再根据之前的起始条件、终止条件、发送数据、接收数据、发送应答和接收应答等编辑写和读最后完成整个时序结构的拼装。
二、收获与成长
通过这段时间的学习,我收获颇丰。首先,我不仅对中断系统和通讯协议有了更深一步的理解和应用同时我掌握了 51 单片机的基本原理和编程方法。这不仅提高了我的编程能力,还让我对嵌入式系统有了更深入的理解。
其次,我学会了如何分析和解决问题。在实践过程中,难免会遇到各种问题,如程序无法正常运行、硬件故障等。通过查阅资料、调试代码和逐步排查,我逐渐掌握了一套有效的问题解决方法。这种能力不仅在学习中非常重要,在今后的工作和生活中也将发挥重要的作用。
此外,学习 51 单片机还培养了我的耐心和毅力。在调试程序的过程中,有时候一个小小的错误可能会导致整个程序无法正常运行,需要花费大量的时间和精力去查找和解决。通过不断地坚持和努力,我逐渐克服了这些困难,培养了自己的耐心和毅力。
来源: 整理文章为传播相关技术,网络版权归原作者所有,如有侵权,请联系删除。