单片机复习

单片机分类

分类

  1. 单片机由 内核、内存、IO 接口 组成。
  2. 单片机可根据 内核、位数、品牌 进行分类。
  3. 主流位数:8位、16位、32位
  4. 内核
    • Intel —— 51 内核
    • Ateml —— AVR 内核
    • ARM —— ARM 内核
  5. 开发方式分类:库开发、底层开发
  6. 什么是微型计算机:以微处理器为核心的计算机称为微型计算机

工作条件

  1. 单片机工作条件
    • 供电(4.5V ~ 5.5V 直流电)
    • 时钟(晶振)
    • 复位:手动复位、上电复位
    • 程序
  2. 计算机工作条件:供电、时钟、复位、reday

电路图

  1. 电路原理图
    • 电源
    • 负载:耗电的元件(元件三要素:标识、符号、参数
    • 控制:单片机、开关
  2. PCB 图

电流与电路

  1. 串联:电流相等,电压不同。
  2. 并联:电压相等,电流不同。
  3. 串联分压,并联分流。
  4. 交流变直流的过程称为:整流
  5. 直流遍交流的过程称为:逆变
  6. 欧姆定律及演变公式

51单片机内部结构

组成部分

  1. 中央处理单元:51 内核、CPU
  2. 内存:见下文
  3. IO口:见下文
  4. 中断控制器:5 种中断源(见下文)
  5. 定时/计数器:2 个 16 位的定时/计数器(见下文)
  6. 振荡器:内部振荡器(时钟 IC) + 外部时钟电路(晶振、电容)
  7. 总线控制器(略)

内存

  1. ROM:只读存储器,用于存储程序,断电数据不丢失。
  2. RAM:随机存储器,用于存储数据,断电数据清空。
  3. 标准 51 单片机 ROM(4KB)RAM(128B)
  4. 60S2 的 ROM(60KB)RAM(1280B)
  5. 存储器结构:哈佛结构、冯诺依曼结构
  6. 51单片机所有存储器均是 8位 的。

IO口

  1. 并行口:P0、P1、P2、P3
  2. 串行口:RxD、TxD

可编程芯片的开发框架

  1. 内部编程结构
  2. 外部引脚定义
  3. 系统组成
  4. 编程方法

外部引脚

  1. 灌电流:从外部流入单片机。

  2. 拉电流:从单片机流入外设。

  3. 每个 IO 引脚最大可接受灌电流为 20mA

  4. 整个单片机最大可接受灌电流为 120mA

  5. 单片机直驱:仅有单片机提供电流,不需要其他的驱动电路。

  6. 驱动电路:有些外设 > 120mA,可以使用驱动电路辅助单片机供电。

  7. 一个引脚实现多个功能:引脚复用

最小系统电路

  1. 供电电路
  2. 时钟电路
  3. 复位电路
  4. 最小系统电路的作用:为单片机提供基本工作条件的电路
  5. 如何判断单片机正常工作了?单片机执行了内部程序

工作模式

模式

  1. 标准双向口
  2. 强推挽输出(强推):提高了单片机的 IO 扣的拉电流
  3. 开漏模式(略)
  4. 高阻模式(略)

模式参数(第一个值:M1,第二个值:M0)

  1. 00:标准双向口,灌电流

  2. 01:强推模式,拉电流

  3. 10:开漏模式

  4. 11:高阻模式

  5. 例:给 P1.0 设置成强推模式

    1
    2
    P1M1 = 0x00;	// 0b 0000 0000
    P1M0 = 0x01; // 0b 0000 0001

LED

外形

长正短负,箭头方向即为电流方向。

欧姆定律

  1. R = U/I
  2. I = U/R
  3. U = IR

逻辑运算

  1. 指定位清零,其他位不变:与运算,指定位和 0 相与,其他位和 1 相与。
  2. 指定位置 1,其他位不变:或运算,指定位和 1 相或,其他位和 0 相或。
  3. 指定位取反,其他位不变:异或,指定位和 1 异或,其他位和 0 异或。

按键

动态扫描步骤

1
2
3
4
5
6
7
8
9
10
11
unsigned char key_scan() {
unsigned char key_num = 0;
if (!K1 || !K2) {
delay(10);
if (!K1) key_num = 1;
if (!K2) key_num = 2;
while(!K1 || !K2);
delay(10);
}
return key_num;
}

时间碎片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 拆碎前
void test1() {
int i = 100;
while(i) {
printf("%d",i);
i--;
}
}

// 拆碎后
void test2() {
static int i = 100;
printf("%d",i);
i--;
i %= 100;
}

void mian() {
while(1) {
test2();
printf("Hello");
}
}

数码管与点阵屏

  1. 共阴:公共的负极
  2. 共阳:公共的正极

动态扫描

  1. 选位|选列
  2. 送段|送行
  3. 延时|延时
  4. 灭段|灭行

选位送段

  1. 数码管:高选位,低送段
  2. 点阵屏:高选列,低送行

sizeof

  1. 计算数组所占内存的大小。

  2. 计算数组元素个数:n = sizeof(arr) / sizeof(type for arr)

    1
    2
    int arr[] = {1,2,3,4,5};
    int n = sizeof(arr) / sizeof(int);

蜂鸣器

  1. 发声原理:不断切换高低电平。

  2. 有源/无源:是否有震荡源。

  3. 给定频率输出声音:

    • 给定频率求周期:5Hz,200ms
    • 给定周期求频率:20ms,50Hz
    • GMK:1GHz = 1000MHz,1MHz = 1000KHz,1KHz = 1000Hz
    • smu:1s = 1000ms,1ms = 1000 us(1m = 1kms = 1mus)
  4. 人耳可听见的声音频率范围:5 Hz ~ 20 KHz(200ms ~ 50us)

  5. 例题:用蜂鸣器发出一个 440Hz 的声音,写出 TH0 和 TL0 的值。

    1
    2
    TH0 = (65536 - 1000000 / 440 / 2) / 256;
    TL0 = (65536 - 500000 / 440) % 256;

中断

定义

  1. 中断定义:打断 CPU 当前工作的一个事件。事件的集合称为中断源。
  2. 5 个中断源
    • 外部中断类
      • 外部中断 0
      • 外部中断 1
    • 定时计数器类
      • 定时计数器 0 中断
      • 定时计数器 1 中断
    • 串行类:串行中断
  3. 数字信号
    • 高电平
    • 低电平
    • 上升沿
    • 下降沿
  4. 51 单片机里只支持低电平、下降沿的外部中断。

外部中断

  1. 步骤

    • 开中断
    • 设置中断请求模式
    • 中断处理子函数
  2. 开外部中断

    • IE 寄存器:可以位寻址

    • 8 7 6 5 4 3 2 1
      名称 EA ES ET1 EX1 ET0 EX0
    • 0-关,1-开

  3. 设置外部中断请求类型

    • TCON:可以位寻址

    • 8 7 6 5 4 3 2 1
      名称 IE1 IT1 IE0 IT0
    • IT0/IT1:设置请求信号类型。0-低电平 1-下降沿。

    • IE0/IE1:使能信号。

  4. 中断处理子函数

    • 特点
      • 无带入值、无返回值。
      • 中断处理子函数不可被其他函数调用,由 CPU 自动调用。
      • 无需声明,直接使用。
      • 必须要有中断向量号。
    • 中断向量号
      • 中断向量和中断向量号不是同一个东西,中断向量是地址,中断向量号是地址别名。
      • 中断向量用于标识中断源类型。
      • 关键字:interrupt
      • 中断向量号
        • 0 - 外部中断 0
        • 1 - 定时计数器 0 中断
        • 2 - 外部中断 1
        • 3 - 定时计数器 1 中断
        • 4 - 串行口
  5. 例题:设计一个是用外部中断 0 下降沿触发的程序。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include <STC12C5A60S2.H>
    bit flag = 0;

    void init() {
    EA = EX1 = IT0 = 1;
    }

    void main() {
    init();
    while(1) {
    if (flag) {
    flag = 0;
    // 1000 行代码
    }
    }
    }

    void inter() interrupt 0 {
    EX0 = 0;
    flag = 1;
    EX0 = 1;
    }

定时计数器

知识点

  1. 51 单片机里有两个 16 位的定时计数器。
  2. 16 位定时计数器最大计算能力:65536(0~65535)
  3. 分类
    • 加法计数器(51):计数初值 = 最大计数值 - 计数值。
    • 减法计数器:计数初值 = 计数值
  4. 工作模式
    • 定时模式
    • 计数模式
  5. 工作方式:方式0 ~ 方式3(方式1最常用)
    • 方式 0:13 位。
    • 方式 1:16 位。
    • 方式 2:8 位,有 8 位自动装载。
    • 方式 3(略)

步骤

  1. 模式方式设置

    • TMOD 寄存器:不可进行位寻址

    • 8 7 6 5 4 3 2 1
      GATE C/~T M1 M0 GATE C/~T M1 M0
    • GATE:门控信。0-软件开启,1-硬件开启。

    • C/~T:工作模式。0-定时模式,1-计数模式。

    • M1M0:工作方式

      • 00-方式0
      • 01-方式1(常用)
      • 10-方式2
      • 11-方式3
  2. 写入计数初值

    • 寄存器:TH0、TH1、TL0、TL1

    • T1高 8 位 T1低 8 位 T0高 8 位 T0低 8 位
      TH1 TL1 TH0 TL0
    • 计算高 8 位:计数初值 / 256

    • 计算低 8 位:计数初值 % 256

  3. 开启定时计数器

    • 寄存器:TCON

    • 8 7 6 5 4 3 2 1
      TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
    • TF1/TF0:溢出标志位

    • TR1/TR0:定时计数器开关 0-关 1-开

  4. 查询法:设置一个计数器 T0,计数 3 次为一个周期,每个周期切换一次 LED(P1.0) 的亮灭状态。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <STC12C5A60S2.H>
    sbit LED = P1 ^ 0;

    void init() {
    LED = 1;
    TMOD = 0x05;
    TH0 = (65536 - 3) / 256;
    TL0 = (65536 - 3) % 256;
    TR0 = 1;
    }

    void main() {
    init();
    while(1) {
    if (TF0) {
    TR0 = TF0 = 0;
    TH0 = (65536 - 3) / 256;
    TL0 = (65536 - 3) % 256;
    LED = ~LED;
    TR0 = 1;
    }
    }
    }
  5. 定时计数器中断

    • 开中断:IE

    • 中断处理子函数

    • 程序1:设置一个定时器 T0,每隔 3 秒切换一次 LED(P1.0) 的亮灭状态。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      #include <STC12C5A60S2.H>
      sbit LED = P1 ^ 0;

      void init() {
      LED = 1;
      TMOD = 0x01;
      TH0 = (65536 - 50000) / 256;
      TL0 = (65536 - 50000) % 256;
      EA = ET0 = TR0 = 1;
      }

      void main() {
      init();
      while(1);
      }

      // 马
      void timer() interrupt 1 {
      static unsigned char c = 0;
      c = ++c % 60;
      if (!c) LED = ~LED;
      else {
      TR0 = 0;
      TH0 = (65536 - 50000) / 256;
      TL0 = (65536 - 50000) % 256;
      TR0 = 1;
      }
      }

      // 刘
      void timer() interrupt 1 {
      static unsigned char c = 0;
      TR0 = 0;
      TH0 = (65536 - 50000) / 256;
      TL0 = (65536 - 50000) % 256;
      if (++c == 60) {
      c = 0;
      LED = ~LED;
      }
      TR0 = 1;
      }
    • 程序2:设置一个定时器 T0,每隔 2 秒切换一次 LED_BLUE(P1.0) 的亮灭状态。每隔 3 秒切换一次 LED_RED(P1.1) 的亮灭状态。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      #include <STC12C5A60S2.H>
      sbit LED_BLUE = P1 ^ 0;
      sbit LED_RED = P1 ^ 1;
      bit F2 = F3 = 0;

      void init() {
      LED_BLUE = LED_RED = 1;
      TMOD = 0x01;
      TH0 = (65536 - 50000) / 256;
      TL0 = (65536 - 50000) % 256;
      EA = ET0 = TR0 = 1;
      }

      void main() {
      init();
      while(1);
      }

      void timer() interrupt 1 {
      static unsigned char c = 0;
      c = ++c % 120;
      if (!(c % 40)) LED_BLUE = ~LED_BLUE;
      else if (!(c % 60)) LED_RED = ~LED_RED;
      else {
      TR0 = 0;
      TH0 = (65536 - 50000) / 256;
      TL0 = (65536 - 50000) % 256;
      TR0 = 1;
      }
      }

      void timer() interrupt 1 {
      static unsigned char c = 0,k = 0;
      TR0 = 0;
      TH0 = (65536 - 50000) / 256;
      TL0 = (65536 - 50000) % 256;
      if (++k == 40) {
      k = 0;
      LED_BLUE = ~LED_BLUE;
      }
      if (++c == 60) {
      c = 0;
      LED_RED = ~LED_RED;
      }
      TR0 = 1;
      }

频率与周期

考点

  1. 给定频率求周期:5Hz,200ms
  2. 给定周期求频率:20ms,50Hz

时钟周期

  1. 时钟电路中晶振的周期即为时钟周期。
  2. 晶振频率 12MHz,时钟周期是:1s/12MHz = 1ms/12KHz = 1us/12Hz = 1/12us

机器周期

  1. 一个机器周期 = 12个时钟周期
  2. 晶振频率 12MHz,机器周期是:1us