第二周蓝桥杯核心笔记整理

第二周核心笔记整理

(一)LED 与 IO 口控制

1. 点灯原理

  • 电路逻辑

    • 接法:VCC — LED — 单片机 IO 口。

    • 控制

      • 0 (低电平) —有压差 — (灌电流)。

      • 1 (高电平) — 无压差 —

  • 编程方式

    1. 整体赋值:操作寄存器(如 P1)。

      • P1 = 0xAA; // 二进制 10101010,实现间隔点亮。

      • 注意:二进制最低位对应 P1.0(最右边)。

    2. 位寻址:单独操作某一个引脚。

      • P1 = 0;

2. 流水灯实现方案

  • 方式1(暴力法):挨个赋值 0,中间加 Delay()

  • 方式2(移位法):使用 C 语言移位运算符 <<>>,配合逻辑运算。

  • 方式3(库函数法 - 推荐)

    • 头文件:#include <intrins.h>

    • 函数:_crol_(变量, 位数) (循环左移) / _cror_ (循环右移)。

    • 优势:移出的位会补回到另一头,不会丢失。


(二)按键检测 (Key)

1. 基础逻辑

  • 电平状态

    • 0:代表按下(导通接地)。

    • 1:代表松开(上拉电阻拉高)。

2. 按键分类

  • 独立按键

    • 一端接 IO 口,另一端直接接地 (GND)。

    • 程序直接读 IO 口电平即可。

  • 矩阵按键

    • 结构:行线 + 列线交叉。

    • 扫描原理“先选行,后查列”

      1. 选行:将某一行置 0,其余行置 1(激活该行)。

      2. 查列:读取列引脚。如果某列读到 0,则说明该“行-列”交叉点的键被按下。

      3. 循环:快速轮流激活每一行,利用视觉暂留实现全键盘检测。

3. 【重点模型】按键消抖与边缘检测

不要只判断“当前是0”,要判断“刚才没按,现在按了”。

 // 核心公式:检测下降沿(按下的瞬间)
 Key_Down = Key_Val & (Key_Val ^ Key_Old); 
 Key_Up   = ~Key_Val & (Key_Val ^ Key_Old);
 Key_Old  = Key_Val; // 必须更新历史状态

(三)数码管与定时器中断

1. 数码管显示原理

  • 结构

    • 段选 (Segment):控制显示什么字(a, b, c, d, e, f, g, dp)。

    • 位选 (Common):控制哪个位置的数码管亮。

  • 极性(共阴极为例)

    • 段码:给 1 亮(高电平驱动)。

    • 位码:给 0 选中(低电平接地选通)。

2. 74HC573 锁存器(P0口复用核心)

  • 总体思路:“谁接听,谁处理”。P0 口是公共数据线,锁存器是开关。

  • 控制引脚

    • P2.6 (段选锁存):控制显示的内容。

    • P2.7 (位选锁存):控制显示的位置。

  • 操作口诀:先 1 后 0

    1. Latch(锁存器) = 1; // 打开门,让 P0 的数据进去。

    2. P0 = Data; // 送数据。

    3. Latch = 0; // 关上门,锁住数据(此时 P0 变了也不影响里面)。

3. 定时器中断 (Timer0)

这就像一个“看不见的闹钟”,后台自动运行,不占用 Delay 时间。

  • 配置三部曲(初始化)

    1. 设置模式TMOD (通常用模式1: 16位定时器)。

    2. 装初值TL0, TH0 (决定定时的长短)。

    3. 开开关

      • ET0 = 1; (允许定时器0说话)(打开闹钟)。

      • EA = 1; (允许总中断说话)(开始计时)。

  • 【重点模型】定时器标准代码模板

    (假设 12MHz 晶振,1ms 中断)

 // 1. 初始化函数
 void Timer0_Init()
 {
     TMOD &= 0xF0;   // 清零低四位
     TMOD |= 0x01;   // 设置为模式1
     TL0 = 0x18;     // 设置初值低8位 (65536-1000)
     TH0 = 0xFC;     // 设置初值高8位
     TF0 = 0;        // 清除溢出标志
     TR0 = 1;        // 开始计时
     ET0 = 1;        // 打开闹钟
     EA = 1;         // 开始计时
 }
 ​
 // 2. 中断服务函数 (每1ms自动执行一次)
 void Timer0_Routine() interrupt 1
 {
     // 每次进来先重装初值!(重要)
     TL0 = 0x18; 
     TH0 = 0xFC; 
 }
 void main(){
     Timer0_Init();
     while(1)
     {
     }
 }

中断配置方法

1.在生成的定时器初始化函数内增加中断打开命令 ET0=1;EA=1;

2.书写中断服务函数(Timer0Server)

3.在服务函数内初始化计数值

4.在主程序内添加定时器0初始化函数

应用

 unsigned char Seg_Pos;
 unsigned char Seg_Buf[]={10,10,10,10,10,10};
 unsigned char Time=500;
 unsigned char Key_Val,Key_Down,Key_Up,Key_Old;
 bit System_Flag=1;//流转状态标识位 0-停止 1-启动
 ​
 //定时器初始化函数
 void Timer0_Init(void)      //1毫秒@12.000MHz
 {
     TMOD &= 0xF0;           //设置定时器模式
     TMOD |= 0x01;           //设置定时器模式
     TL0 = 0x18;             //设置定时初始值
     TH0 = 0xFC;             //设置定时初始值
     TF0 = 0;                //清除TF0标志
     TR0 = 1;                //定时器0开始计时
     ET0=1;                  //打开闹钟
     EA=1;                   //开始计时
 }
 ​
 //定时器0中断服务函数
 void Timer0Server() interrupt 1
 {
     TL0 = 0x18;             //设置定时初始值
     TH0 = 0xFC;             //设置定时初始值
     if(++Seg_Pos == 6) Seg_Pos = 0;
     Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]);
 }
 ​
 void main()
 {
     Timer0_Init();
     while(1)
     {
         Key_Read();
         Key_Val=Key_Read();//读取键码值
         Key_Down=Key_Val&(Key_Val^Key_Old);//检测下降沿
         Key_Up=~Key_Val&(Key_Val^Key_Old);//检测上升沿
         Key_Old=Key_Val;//扫描辅助变量
         
         switch(Key_Down)
         {
             case 1:
                 System_Flag=1;
             break;
             case 2:
                 System_Flag=0;
             break;
             case 3:
                 Time +=100;
             break;
             case 4:
                 Time -=100;
             break;  
         }
         
         Seg_Buf[0]=Time/100%10;
         Seg_Buf[1]=Time/10%10;
         Seg_Buf[2]=Time/1%10;
     }
 }