环境配置
芯片选AT89C52
生成16进制文件,便于烧录
烧录:生成对应hex文件导入后,芯片型号为STC89C5RC。串口根据下载STC-ISP说明来操作即可,一般有CH340和PL2303两种。
下载后要重新按一下开关,冷启动
void Delay(unsigned int x) //@11.0592MHz
{unsigned char i, j;while(x--){i = 2;j = 199;do{while (--j);} while (--i);}
}
电平和阻态
高电平 和 低电平 是引脚主动输出的状态,高阻态是引脚“悬空”的被动状态,用于读取外部信号或避免干扰。
特性 | 高电平 | 低电平 | 高阻态 |
---|---|---|---|
定义 | I/O 引脚输出逻辑 1(通常为 VCC 电压,如 3.3V 或 5V)。 | I/O 引脚输出逻辑 0(通常为 GND,0V)。 | I/O 引脚处于高阻状态,像断开电路一样,既不输出高电平也不输出低电平。 |
电平输出 | 固定为高电平(逻辑 1) | 固定为低电平(逻辑 0) | 没有固定电平,外部信号决定引脚电平。 |
电流流动 | 根据外部负载电流流出引脚 | 根据外部负载电流流入引脚 | 几乎没有电流流动。 |
状态 | 主动输出电平 | 主动输出电平 | 输入状态或 “断开” 状态,无主动输出电平。 |
功耗 | 根据外部负载情况有功耗 | 根据外部负载情况有功耗 | 极低功耗,几乎没有电流消耗。 |
信号控制 | 引脚输出逻辑 1,不受外部信号影响 | 引脚输出逻辑 0,不受外部信号影响 | 引脚对外部信号无干扰,可以读取外部电平。 |
应用场景 | 控制外部设备逻辑高电平状态,如关闭 LED。 | 控制外部设备逻辑低电平状态,如点亮 LED。 | 输入模式或总线共享,避免信号冲突(如 I2C)。 |
如果指定了寄存器的电平(例如向 P1
写值),对应的 I/O 引脚会输出这个值。
如果没有明确指定寄存器电平(寄存器处于高阻态),对应的 I/O 引脚可以读取外部的输入信号。
什么时候引脚处于高阻态
引脚配置为输入模式时:当将 I/O 引脚设置为输入模式时,内部驱动电路断开,避免对外部信号施加影响。此时,引脚呈现高阻态,允许外部信号主导电平。
多设备共享总线时未被选中:在多设备共享同一数据总线的情况下(如 I²C 总线),未被选中的设备会将其相关引脚置于高阻态,以避免干扰总线上的通信。
特定引脚的默认状态:某些引脚(如 51 单片机的 P0 口)在上电后默认处于高阻态,需通过外部上拉电阻确定其电平状态。
数码管
- 找想要的数在数码管上对应位置的电平,得到对应的寄存器的值
- 在译码器那看要选第几个,得到译码器对应的输入。
消影
数码管的显示是在位选 端选 位选 端选
的不断循环的过程,但是在端选
到位选
的过程中上一个阶段的数据会有残留,导致数据窜位
寄存器
- 寄存器是连接软硬件的媒介
- 在单片机中寄存器就是一段特殊的RAM存储器,一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式
- 寄存器相当于一个复杂机器的“操作按钮”
在51单片机中,sfr用于定义特殊功能寄存器(SFR),不能用于给寄存器命别名。
如果想命别名需要用#define
sbit
可以给某一位命别名。在51单片机中,sbit
关键字用于定义特殊功能寄存器(SFR)中的某一位,或者给某一位命别名。
定时器
寻址
可位寻址:可以对单独对寄存器的某一位赋值
不可位寻址:不能单独对寄存器的某一位赋值
模式1
16位定时器/计数器。
SYSclk:系统时钟,即晶振周期
T0 Pin:外部的脉冲
模式2
8位自动重装模式
将十六位分开,一个计数,另一个存放初值,每次计数完成后AR会自动将值赋给CNT,不用代码处理,比较快,但只有八位所以记的数少了。
使用
可以在定时器里加入Loop(),来扫描。当定时器发生中断时执行Loop(),可以人为的设置20ms执行一次Loop(),也就20ms扫描一次。
用在数码管上就是20ms扫描一个位,这样就不需要内部的Delay()函数来占用CPU资源了。同时由于是利用定时器的中断来进行扫描,需要一个static unsigned char i;
来记住这次扫描到哪里,下次继续。Nixie_Scan(i,Nixie_Buf[i]);
是选择第i位显示Nixie_Buf[i]的内容。Nixie_Buf[i]
的作用是记住这一位上的数字,以免扫描到这一位上时不知道该显示什么数据
定时器扫描按键数码管
/*Nixie.h*/
#ifndef __NIXIE_H__
#define __NIXIE_H__void Nixie_Scan(unsigned char Location,Number);
void Nixie_SetBuf(unsigned char Location,Num);
void Nixie_Loop(void);#endif/*----Nixie.c*/
#include <REGX52.H>
#include "Delay.h" //包含Delay头文件unsigned char Nixie_Buf[9];//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};void Nixie_SetBuf(unsigned char Location,Num)
{Nixie_Buf[Location]=Num;
}//数码管显示子函数
void Nixie_Scan(unsigned char Location,Number)
{P0=0x00;switch(Location) //位码输出{case 1:P2_4=1;P2_3=1;P2_2=1;break;case 2:P2_4=1;P2_3=1;P2_2=0;break;case 3:P2_4=1;P2_3=0;P2_2=1;break;case 4:P2_4=1;P2_3=0;P2_2=0;break;case 5:P2_4=0;P2_3=1;P2_2=1;break;case 6:P2_4=0;P2_3=1;P2_2=0;break;case 7:P2_4=0;P2_3=0;P2_2=1;break;case 8:P2_4=0;P2_3=0;P2_2=0;break;}P0=NixieTable[Number]; //段码输出
}void Nixie_Loop(void)
{static unsigned char i;Nixie_Scan(i,Nixie_Buf[i]);i++;if(i>=9){i=1;}
}
/*main.c的中断函数*/
void Timer0_Rountine() interrupt 1
{static unsigned int T0Count1=0,T0Count2 = 0;TL0 = 0x18; // 设置定时初始值TH0 = 0xFC; // 设置定时初始值T0Count1++;T0Count2++;if (T0Count1 >= 20){T0Count1 = 0;Key_Loop();}if (T0Count2 >= 2){T0Count2 = 0;Nixie_Loop();}
}
中断系统
51单片机中断系统,只有两个中断优先级
串口
串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。
51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机的串口通信。
波特率
什么是波特率,波特率怎么计算-CSDN博客
实际用的时候直接用STC的波特率计算器就可以了
相关术语
- 全双工:通信双方可以在同一时刻互相传输数据
- 半双工:通信双方可以互相传输数据,但必须分时复用一根数据线
- 单工:通信只能有一方发送到另一方,不能反向传输
- 异步:通信双方各自约定通信速率
- 同步:通信双方靠一根时钟线来约定通信速率
- 总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)
常见通信接口
名称 | 引脚定义 | 通信方式 | 特点 |
---|---|---|---|
UART | TXD、RXD | 全双工、异步 | 点对点通信 |
I²C | SCL、SDA | 半双工、同步 | 可挂载多个设备 |
SPI | SCLK、MOSI、MISO、CS | 全双工、同步 | 可挂载多个设备 |
1-Wire | DQ | 半双工、异步 | 可挂载多个设备 |
此外还有:CAN、USB等
51单片机的UART
STC89C52有1个UART
STC89C52的UART有四种工作模式:
-
模式0:同步移位寄存器
-
模式1:8位UART,波特率可变(常用)
-
模式2:9位UART,波特率固定
-
模式3:9位UART,波特率可变
电路
-
简单双向串口通信有两根通信线(发送端TXD和接收端RXD)
-
TXD与RXD要交叉连接
-
当只需单向的数据传输时,可以直接一根通信线
-
当电平标准不一致时,需要加电平转换芯
- T——transmit(发送);
- X——exchange(交换);
- D——data(数据);
- R——receive(接收);
串口参数及时序图
波特率:串口通信的速率(发送和接收各数据位的间隔时间)
检验位:用于数据验证。
如果是偶校验,校验1的个数是否为偶。如果是0000 0011
就在后面加0变成0000 0011 0
,如果是0000 0111
就在后面加1变成0000 0011 1
停止位:用于数据帧间隔
数据是串行通信,都是从低位开始
如果是8位数据格式,发送完之后就是停止位。如果·是9位数据格式,发送完后最后加一个校验位
串口模式图
51单片机通过定时器的溢出信号来控制串口通信的波特率,从而间接控制收发器的采样时间。发送完成TI会置1引发中断
SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器
串口向电脑发送数据
接收的时候注意一系列配置
寄存器配置
SCON
SM0,SM1为0,1,设置为8位UART
SM1,SM2不用管,设为0。
REN是否接受信息,随便设置。
TB8,RB8,接受和发送时校验,不用管。
TI,RI,发送和接受控制器的最高溢出位,这里需要每次都软件置0,因为硬件置1后不会置0
SCON=0x40
,接收的时候要把REN设为1,SCON=050
定时器配置
定时器1,8位自动重载定时器。
禁止定时器中断,这里不需要溢出的时候执行什么东西
中断
串口发送数据后cpu并不需要做什么,所以不需要中断,而串口接收数据后需要保存数据,或者对数据做出一些响应,因此需要中断当前程序转而去执行中断服务程序。
打开中断后执行对应的中断函数需要判断是RI还是TI为1,借此判断是接收还是发送
LED点阵
采用纵向扫描
先向74HC595里写数据,写完后再选要写到哪一列上面,把那一列置0,其他置1。
这里用列是因为每一列都是P1的一位
DS1302(时钟芯片)
命令字
根据串行输入的不同命令字,告诉芯片在哪 写入 什么,或在哪 读出 (什么),并且在上升沿读取IO口,下降沿输出到IO口
如果输入写的命令字的话,在串行输入命令字结束后,D0~D7都是单片机来输入。
如果输入读的命令字的话,在串行输入命令字结束后,D0~D7都是DS1302来输入。
蜂鸣器
按驱动方式可分为有源蜂鸣器和无源蜂鸣器
- 有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定
- 无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音
51单片机是12T(12分频),12mhz除以12为1mhz,对应的周期是1us,1us定时器加1
I2C总线
两根通信线:SCL(Serial Clock)、SDA(Serial Data)
同步、半双工,带数据应答
电路规范
所有I2C设备的SCL连在一起,SDA连在一起
设备的SCL和SDA均要配置成开漏输出模式
SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右
当没有设备驱动总线时,SCL和SDA需要通过上拉电阻将电平拉高,以确保总线在空闲时处于高电平状态(逻辑“1”)。
开漏输出和上拉电阻的共同作用实现了“线与”的功能,此设计主要是为了解决多机通信互相干扰的问题
I2C时序结构
注意,发送应答和接受应答都是相对于主机发送和接受
I2C数据帧
DS18B20(温度芯片)
操控流程
初始化:从机复位,主机判断从机是否响应
ROM操作:ROM指令+本指令需要的读写操作
功能操作:功能指令+本指令需要的读写操作
ROM指令 | 功能指令 |
---|---|
SEARCH ROM [F0h] | CONVERT T [44h] |
READ ROM [33h] | WRITE SCRATCHPAD [4Eh] |
MATCH ROM [55h] | READ SCRATCHPAD [BEh] |
SKIP ROM [CCh] | COPY SCRATCHPAD [48h] |
ALARM SEARCH [ECh] | RECALL E2 [B8h] |
READ POWER SUPPLY [B4h] |
内部结构
64-BIT ROM:作为器件地址,用于总线通信的寻址
SCRATCHPAD(暂存器):用于总线的数据交互
EEPROM:用于保存温度触发阈值和配置参数
SCRATCHPAD结构
0和1个字节是温度,读取的时候在这读取
2和3字节是存储数据
温度存储格式
负数以补码的格式存储
单总线
介绍
单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线
一根通信线:DQ
异步、半双工
单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线
电路规范
设备的DQ均要配置成开漏输出模式
DQ添加一个上拉电阻,阻值一般为4.7KΩ左右
若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路
时序结构
默认主机发送,
PWM
PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域
PWM重要参数:
频率 = 1 / TS 占空比 = TON / TS 精度 = 占空比变化步距
DA/AD
DA
T型电阻网络DA转换器
电路中\(I_7=2I_6=4I_5=8I_4=16I_3=32I_2=64I_1=128I_0\)
输出电压$V_O=((D7~D0))/256×(V_REF×R_fb)/R $
当Rfb=R时,\(V_O=((D7~D0))/256×V_REF\)
pwm型
原理:pwm信号由直流和交流分量组成,加低通滤波器可以滤出直流分量
输出电压\(V_O=(PWM占空比)×V_H\)
AD
红外遥控
简介
红外遥控是利用红外光进行通信的设备,由红外LED将调制后的信号发出,由专用的红外接收头进行解调输出
通信方式:单工,异步
红外LED波长:940nm
通信协议标准:NEC标准
调制与解调
发送设备通过电平信号传递信息,接收设备按协议读取信号。但在无线通信中,环境中的红外波(如太阳辐射)会干扰信号。为抗干扰,发送前需调制信号,接收后解调。
调制原理:将信号电平搭载在38kHz方波(载波)上发送;接收设备先解调38kHz信号,再按协议读取数据。
基本发送接收
发送
注意这里TTL为PNP型,是低电平导通。
接收
空闲状态:红外LED不亮,接收头输出高电平
发送低电平:红外LED以38KHz频率闪烁发光,接收头输出低电平
发送高电平:红外LED不亮,接收头输出高电平
NEC协议
NEC协议特征
-
基本发送与接收:
- (发送设备)空闲状态:红外LED不亮,输出高电平(默认就是发送高电平);
- 发送低电平:红外LED以38KHZ发光,输出低电平;
- 发送高电平:红外LED不亮,输出高电平;
-
载波频率为38Khz;
-
发送的数据格式为:
地址码+地址码反码+键码+键码反码
;(共32位);数据低位在前,高位在后; -
位时间为:1.125ms或2.25ms;
NEC编码
杂
CPU通过控制寄存器来控制电路
寄存器8位一组,通过驱动器,为1输出高电平,为0输出低电平
#include <REGX51.H>
头文件内定义了这个芯片的寄存器
单片机执行完一次程序后会重新执行
电阻读数:
- 102=10*10^2=10_00=1k
- 473=47*10^3=47_000
- 1001=100*10^1=100_0
- 1002=100*10^2=100_00
P20-P27:P2端口的8个引脚,作为输入/输出(I/O)端口使用
单片机上电后,所有 IO 口的寄存器默认初始化为逻辑 1,但 IO 口并不主动输出高电平,而是处于高阻态状态,外部需要通过上拉电阻决定最终的引脚电平。
按键按下会接地,使得使对应的口变为低电平
如果寄存器设置了电平,则对应的 I/O 引脚输出该电平;如果寄存器没有设置电平,且引脚处于高阻态,则外部信号会通过 I/O 口送到寄存器中。
消抖:按下和松手都有抖动,会造成按一次执行多次的后果。
检测当按下时停顿一下再执行语句
if(P3_1==0)
{Delay(20);while(P3_1==0);Delay(20);//执行语句
}
单片机是弱上拉,强下拉。给1的时候外部给0,这个IO口输出变为0,输入变为0。给0的时候外部给1,IO口输出为0,输入为0
单片机通过配置寄存器来控制内部线路的连接
&
用来清零,|
用来置1
取一字节的某一位:Byte & 0x01
,这里0x01的1写在想要的那一位的位上
把char作为int类型的高位,int类型的默认为0时,INT |= CHAR<<8