1、学习三极管的使用
C51学习笔记 1、学习三极管的使用
三极管一共有 3 个极,从图 3-6 来看,横向左侧的引脚叫做基极(base),中间有一个箭头, 一头连接基极,另外一头连接的是发射极 e(),那剩下的一个引脚就是集电极 c()。箭头朝内 PNP,导通电压顺箭头过,电压导通, 电流控制。
只要箭头外侧比箭头内侧电压高0.7V,e和c级就会导通。也就是通过b级控制ec级,并且可以用低电压去控制高电压如下图使用NPN三极管:
当IO输出高电平,OUT输出0V,IO输出低电平,OUT输出12V。
同时ec间电流由eb间电流控制 Ieb*β=Iec . 特殊值:红色贴片LED压降约为2V,硅三极管导通时be间压降约为0.7V。
2、学习定时器
时钟周期T 是时序中最小的时间单位,T=1/时钟源频率。开发板上用的晶振11.0592M,那么T=1/ 秒。C51的机器周期一般为12个始终周期,12/ 秒。定时器内部有一个寄存器,每过一个机器周期寄存器的值就会加一。可以通过该寄存器来知晓经过的时间。
C51有以下重要寄存器
TCON:控制寄存器 TMOD:模式寄存器
TMOD可以用来确定寄存器的工作模式,通常使用定时器模式1和模式2.
模式1是 THn 和 TLn 组成了一个 16 位的定时器,计数范围是 0~65535,溢出后,只 要不对 THn 和 TLn 重新赋值,则从 0 开始计数。模式 2,是 8 位自动重装载模式,只有 TLn 做加 1 计数,计数范围 0~255,THn 的值并不发生变化,而是保持原值,TLn 溢出后,TFn 就直接置 1 了,并且 THn 原先的值直接赋给 TLn,然后 TLn 从新赋值的这个数字开始计数。 这个功能可以用来产生串口的通信波特率。
C/T = 0 的时候,一个机器周期 TL 就会加 1 一次, C/T =1 的时候,T0 引脚即 P3.4 引脚来一个脉冲,TL 就加 1 一次,这也就是计数器功能。
使用步骤:
第一步:设置特殊功能寄存器 TMOD,配置好工作模式。
第二步:设置计数寄存器 TH0 和 TL0 的初值。
第三步:设置 TCON,通过 TR0 置 1 来让定时器开始计数。
第四步:判断 TCON 寄存器的 TF0 位,监测定时器溢出情况。
用定时器定时时间:设一个机器周期T,计数次数x ,假设定时0.02S,
则x = 0.02/Tx*12/=0.02,得到 x= 18432。那么初值 y = 65536 - 18432 = 47104, 16进制是,也就是 TH0 = 0xB8,TL0 = 0x00。
3、学习中断
以下是C51的一些中断寄存器
在触发中断时,会进入一个中断函数,需要使用 X 来“绑定”中断函数。X为对应的中断部件的编号。如void () 1 绑定了该函数为定时器0中断函数。
抢占优先级
这些位中被赋1的位能够抢占未赋1的中断。
使用外部中断的例子:
//中断初始化
void ()
EX0 = 1; //开启外部中断0
IT0 = 1; //中断触发0:下降沿触发 1:高电平触发
EA = 1; //开启总中断
PX0 = 1; //将外部中断的优先级提高
//外部0中断服务函数
void int0() 0
uchar j = 0;
for(j = 0;j>8); //高电平重载值拆分为高低字节
= ( char)high;
LowRH = ( char)(low>>8); //低电平重载值拆分为高低字节
LowRL = ( char)low;
TMOD &= 0xF0; //清零T0的控制位
TMOD |= 0x01; //配置T0为模式1
TH0 = ; //加载T0重载值
TL0 = ;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
= 1; //输出高电平
/* 关闭PWM */ void ()
TR0 = 0; //停止定时器
ET0 = 0; //禁止中断
= 1; //输出高电平
/* T0中断服务函数,产生PWM输出 */
void () 1
if ( == 1) //当前输出为高电平时,装载低电平值并输出低电平
TH0 = LowRH; TL0 = LowRL;
= 0;
else //当前输出为低电平时,装载高电平值并输出高电平
TH0 = ; TL0 = ;
= 1;
6、单片机UART使用
单片机 1 想给单片机 2 发送数据时,比如发送一个 0xE4 这个数据,用二进制形式表示就是 ,在 UART 通信过程中,是低位先发,高位后发的原则,那么就让 TXD 首先拉低电平,持续一段时间,发送一位 0,然后拉高,再持续一段时间,发送了一个1
这段“持续的时间”就是1/baud(波特率)。在通信时两个单片机波特率要一致。
在实际发送时发一个字节要发10位,因为要加上起始位和中止位。
51 单片机内部存在这样一个 UART 模块,控制它的寄存器为SCON:
其中模式1便是8位数据加一位起始位和一位停止位的模式。
要使用此模块,需要用定时器给此模块提供采样定时,也就是给它提供波特率,作为它的波特率发生器。对于 单片机来讲,这个波特率发生器只能由定时器 T1 或定时器 T2 产生,采用T1产生波特率时,需要使用T1的模式2(自动重装载模式),且必须关闭T1的中断。
定时器的重载值计算公式: TH1 = TL1 = 256 - 晶振值/12 /2/16 /波特率
其中“16”指的是在数据采集时,模块实际上会将一个位检测16次。和波特率有关的还有一个寄存器,是一个电源管理寄存器 PCON,他的最高位可以把波特率提高一倍,也就是如果写 PCON |= 0x80 以后,计算公式就成了: TH1 = TL1 = 256 - 晶振值/12 /16 /波特率
可以设需要计数的次数为X,那么X* (12/晶振值) = 一次采样的时间 = 1/(波特率*16).
使用代码
/* 串口配置函数,baud-通信波特率 */
void ( int baud)
SCON = 0x50; //配置串口为模式1
TMOD &= 0x0F; //清零T1的控制位
TMOD |= 0x20; //配置T1为模式2
TH1 = 256 - (/12/32)/baud; //计算T1重载值
TL1 = TH1; //初值等于重载值
ET1 = 0; //禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
/* UART中断服务函数 */
void () 4
{ if (RI) //接收到字节
RI = 0; //手动清零接收中断标志位
SBUF = SBUF + 1; //接收的数据+1后发回,左边是发送SBUF,右边是接收SBUF
if (TI) //字节发送完毕
TI = 0; //手动清零发送中断标志位
7、基于1602液晶的时序图学习
读操作时序的 RS 引脚和 R/W 引脚,这两个引脚先进行变化,不管它原来是什么。读指令还是读数据,都是读操作,而且都有可能,所以 RS 引脚既有可能是置为高电平,也有可能是置为低电平,而 RS 和 R/W 变化了经过 Tsp1 这么长时间后,使能引脚 E 才能从低电平到高电平发生变化。
而使能引脚 E 拉高经过了 tD 这么长时间后, 输出 DB 的数据就是有效数据了,我们就可以来读取 DB 的数据了。读完了之后,先把使能 E 拉低,经过一段时间tHD1、tHD2后 RS、R/W 和 DB 才可以继续变化。
tC:指的是使能引脚 E 从本次上升沿到下次上升沿的最短时间是 400ns,而我们单片机因为速度较慢,一个机器周期就是 1us 多,而一条 C 语言指令肯定是一个或者几个机器周期的,所以这个条件完全满足。
tPW:指的是使能引脚 E 高电平的持续时间最短是 150ns,同样由于我们的单片机比较慢,这个条件也完全满足。
tR, tF:指的是使能引脚 E 的上升沿时间和下降沿时间,不能超过 25ns,别看这个数很小,其实这个时间限值是很宽裕的,我们实际用示波器测了一下开发板的这个引脚上升沿和下降沿时间大概是 10ns 到 15ns 之间,完全满足。
tSP1:指的是 RS 和 R/W 引脚使能后至少保持 30ns,使能引脚 E 才可以变成高电平,这个条件同样也完全满足。
tHD1:指的是使能引脚 E 变成低电平后,至少保持 10ns 之后,RS 和 R/W 才能进行变化,这个条件也完全满足。
tD:指的是使能引脚 E 变成高电平后,最多 100ns 后,1602 就把数据送出来了,那么我们就可以正常去读取状态或者数据了。
tHD2:指的是读操作过程中,使能引脚 E 变成低电平后,至少保持 20ns,DB 数据总线才可以进行变化,这个条件也完全满足。
tSP2:指的是 DB 数据总线准备好后,至少保持 40ns,使能引脚 E 才可以从低到高进行使能变化,这个条件也完全满足。
tHD2:指的是写操作过程中,要引脚 E 变成低电平后,至少保持 10ns,DB 数据总线才可以变化,这个条件也完全满足。
驱动代码:
/* 向液晶写入一字节命令,cmd-待写入命令值 */
void ( char cmd)
();
= 0;
= 0;
= cmd;
= 1;
= 0;
/* 向液晶写入一字节数据,dat-待写入数据值 */
void ( char dat)
();
= 1;
= 0;
= dat;
= 1;
= 0;
8、单片机IIC通信学习
I2C 总线是由时钟总线 SCL 和数据总线 SDA 两条线构成,连接到总线上的所有器件的 SCL 都连到一起,所有 SDA 都连到一起。I2C 总线是开漏引脚并联的结构,因此要添加上拉电阻。对于开漏电路外部加上拉电阻,就组成了线“与”的关系。总线上线“与”的关系就是说,所有接入的器件保持高电平,这条线才是高电平,而任何一个器件输出一个低电平,那这条线就会保持低电平,因此可以做到任何一个器件都可以拉低电平,也就是任何一个器件都可以作为主机,
IIC位时序:先发送起始信号:在保证SCL和SDA都是高电平的情况下,SDA产生一个下降沿。IIC通信和UART通信相反,是先发送高位。SDA数据线在SCL处于低电平时由发送方操作,在SCL处于高电平时,接收方会来读取SDA。停止信号:在保证SCL和SDA都是低电平后,先给SCL一个上升沿,再给SDA一个上升沿。
IIC字节时序:要完成完整IIC通讯,主机先在总线上发送起始信号,然后要先发送一个从机地址,从机地址只有7位,发完7位之后需要紧接着发一位读写位,0表示要发数据,1表示要读数据。在从机接收完8位后,主机再将SCL拉低,并把SDA拉高,(可理解为发送第9位0),再接着将SCL拉高,然后检测SDA的状态,如果SDA还为高,那么从机没有响应,若SDA为低,则从机发来了响应。
void ()
= 1; //首先确保SDA、SCL都是高电平
= 1;
();
= 0; //先拉低SDA
();
= 0; //再拉低SCL
/* 产生总线停止信号 */
void ()
= 0; //首先确保SDA、SCL都是低电平
= 0;
();
= 1; //先拉高SCL
();
= 1; //再拉高SDA
();
/* I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 */
bit ( char dat)
{ bit ack; //用于暂存应答位的值 char mask; //用于探测字节内某一位值的掩码变量
for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
{ if ((mask&dat) == 0) //该位的值输出到SDA上
= 0; else
= 1;
();
= 1; //拉高SCL
();
= 0; //再拉低SCL,完成一个位周期
= 1; //8位数据发送完后,主机释放SDA,以检测从机应答
();
= 1; //拉高SCL
ack = ; //读取此时的SDA值,即为从机的应答值
();
= 0; //再拉低SCL完成应答位,并保持住总线
(~ack); //应答值取反以符合通常的逻辑:
//0=不存在或忙或写入失败,1=存在且空闲或写入成功
在整个过程中,SCL均由单片机来操作。无论是起始、读、写操作函数,在调用这些函数之后SCL被提前拉低。
I2C 通信分为低速模式 /s、快速模式 /s 和高速模式 3.4Mbit/s。在使用/s时需要SCL 的高低电平持续时间都不短于 5us。
单片机与用IIC通信的例子:
单片机写:
第一步,发送 I2C 的起始信号,接着跟上I2C 的器件地址,在读写方向上选择“写”操作。
第二步,发送数据的存储地址。24C02 一共 256 个字节的存储空间,地址从 0x00~0xFF,我们想把数据存储在哪个位置,此刻写的就是哪个地址。
第三步,发送要存储的数据第一个字节、第二个字节…在写数据的过程中, 每个字节都会回应一个“应答位 0”,来告诉我们写 数据成功,如果没有回应答位,说明写入不成功。
在写数据的过程中,每成功写入一个字节, 存储空间的地址就会自动加 1,当加到 0xFF 后,再写一个字节,地址会溢出又变成了 0x00。
/* 向中写入一个字节,addr-字节地址 */
void ( char addr, char dat)
();
(0x50