学习资料
基本思想
单片机最小应用系统:单片机、晶振、复位电路、电源
电源和Vcc引脚之间有滤波电容
LED:正极引脚长,负极引脚短,正极电源和LED之间有限流电阻,防止LED灯烧坏
CPU通过控制寄存器中的数值,在通过驱动器和IO端口相连从而控制外设,同时,也可以从IO端口获得外设的状态,送给寄存器
在单片机中寄存器就是一段特殊的RAM存储器:
寄存器可以存储和读取数据,
每一个寄存器背后都连接了一根导线,控制着电路的连接方式
可位寻址:可以单独赋值 不可位寻址:只能整体赋值
单片机通电时所有IO口都是高电平
单片机的高电平驱动能力弱,低电平驱动能力强
注意寄存器高低位的方向:最左边是高位,最右边是低位
寄存器8个为一组,如果直接操作某个寄存器,则需要同时给8个赋值,现在只想操作寄存器的某一位,打开头文件,找到对位寄存器的声明
单片机IO口模式:弱上拉模式,即准双向口,即其既可以输出,又可以输入。弱上拉:输出1的驱动能力有限,输出零的驱动能力强,除此之外,还有其他模式
无符号字符型为0~255的8位二进制数据,表示一个寄存器
unsigned char
单片机通过配置寄存器来控制内部线路的连接;开关拨到哪个位置就是靠寄存器控制的
数码管
数码管 一个单独的,分为共阴极和共阳极,要使其正常工作,共阴极接0,共阳极接1
四位一体数码管静态显示:共阴极和共阳极作为位选,四个数码管公用一个段选
动态显示:高频率扫描
74LS138:38译码器,可以通过三个地址端控制八个数码管的位选
在数码管的段选和输入间一般会有双向数据缓冲器,比如74HC245,其中DIR用于控制方向,既可以给数码管提供段选信号,又可以读取数码管的段选限号,可以用于提高数据的驱动能力
动态显示数码管+模块化编程
数码管扫描(输出扫描)原理:显示第1位→显示第2位→显示第3位→……,然后快速循环这个过程,最终实现所有数码管同时显示的效果
其它.c文件想使用其中的代码时,只需要#include “XXX.h”文件即可
main.c
#include <REGX52.H> // <>是在安装目录里找这个文件 #include "Delay.h" //包含Delay头文件 ""是在自己程序目录里寻找文件 #include "Nixie.h" //包含数码管头文件 void main() { while(1) { Nixie(1,1); //在数码管的第1位置显示1 Nixie(2,2); //在数码管的第2位置显示2 Nixie(3,3); //在数码管的第3位置显示3 Nixie(4,4); //在数码管的第4位置显示4 Nixie(5,5); //在数码管的第5位置显示5 Nixie(6,6); //在数码管的第6位置显示6 } }
把各个模块的代码放在不同的.c文件里
Nixie.c
#include <REGX52.H> #include "Delay.h" //包含Delay头文件 //数码管静态、动态显示,驱动方法:38译码器+双向数据缓冲器 数码管为共阴极 //该段扫描方法:单片机直接扫描 硬件设备简单,但会耗费大量的单片机CPU时间 //另一种扫描方法:专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉它显示什么即可 //数码管段码表 unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //数码管显示子函数 void Nixie(unsigned char Location,Number) { 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]; //段码输出 Delay(1); //形成数字以后先延时,否则直接清零数码管会比较暗 P0=0x00; //段码清0,消影 } //位选 段选 清零 位选 段选
在.h文件里提供外部可调用函数的声明
Nixie.h
#ifndef __NIXIE_H__ #define __NIXIE_H__ void Nixie(unsigned char Location,Number); #endif
按键
- 轻触按键:在原理图中,若其公共端接低电平,按键松开,读寄存器,值为1;按下时读寄存器为0
- 按键在按下时不其作用,在松手的一瞬间才起作用,消抖:按键按下时延时20ms,松手时也延时20ms
int main()
{
while(1)
{
if(P3_1==0)
{
//如果P31是按下状态,那么延时20ms
Delay(20);
//按下不操作,松手才操作;while(P3_1==0)检测松手,不能不加
while(P3_1==0);
//松手以后,消除松手抖动
Delay(20);
//可以操作了,然后取反
P2_0=~P2_0;
}
}
}
- 矩阵按键
采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态
矩阵键盘扫描(输入扫描)原理:读取第1行(列)→读取第2行(列) →读取第3行(列) → ……,然后快速循环这个过程,最终实现所有按键同时检测的效果
- 检测矩阵按键状态,此处采用逐列扫描
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
*/
unsigned char MatrixKey()
{
unsigned char KeyNumber=0; //局部变量引用必须赋初始值
P1=0xFF;
P1_3=0; // 扫描第一列
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
//在扫描第一列时,如果P1_7==0,那么此时是判断开关1的状态
//由于是机械按键,加入延时函数消除抖动,然后判断是否松手;如果松手,继续消除抖动
//返回值KeyNumber
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
P1=0xFF;
P1_2=0; // 扫描第二列
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
P1=0xFF;
P1_1=0; // 扫描第三列
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
P1=0xFF;
P1_0=0; // 扫描第四列
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
return KeyNumber;
}
定时器
定时器属于单片机的内部资源
- 用于计时系统,可实现软件计时
- 替代长时间的Delay
工作原理
- SYSclk:系统时钟,即晶振周期
中断系统
串口通信
- 51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机的串口通信。
- TTL电平:+5V表示1,0V表示0,TTL:Transistor-Transistor Logic 晶体管-晶体管逻辑(电路);(单片机就是用的TTL)
- 如果操作的是端口的寄存器,用的就是IO口;如果操作的是串口的寄存器,就通过IO口发送数据
- 简单双向串口通信有两根通信线(发送端TXD和接收端RXD)