蓝桥杯第一次笔记

单片机入门

入门一

LED 灯输入低电平/高电平原理

![image-20251101082414548](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101082414548.png?lastModify=1762947949)

  • LED 灯左为 VCC,右必须为低电平(0),LED 才导通

控制 LED 灯亮灭

  • 对 P1 整体进行赋值

    ![image-20251101125228108](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101125228108.png?lastModify=1762947949)

  • 对 P1 中 8 个 IO 口单独赋值

延时函数(可赋变量)

  1. 在 STC-ISP 中搜索延时函数(1ms)

![image-20251101125405624](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101125405624.png?lastModify=1762947949)

  1. 赋变量,加 while

     void Delay(unsigned int x)      //@12.000MHz
     {
         unsigned char i, j;
         while(x--)
         {
             i = 2;
             j = 239;
             do
             {
                 while (--j);
             } while (--i);
         }
     }
    

流水灯

  • 通过给 P1 口赋不同的值从而达到流水灯的效果

  • 通过内置函数库实现流水灯效果 __crol__:循环左移 `_cror_:循环右移 所属库:intrins.h

 /*变量声明区域*/
 unsigned char ucLed = 0xfe;
 ​
 /*Main*/
 void main()
 {
     while(1)
     {
         ucLed = _crol_(ucLed,1);
         P1 =  ucLed;
         Delay(100);
     }
 }

入门二

按键原理(简略)

  • 按键为输入模式,输入0(低电平)

  • ![image-20251101150827615](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101150827615.png?lastModify=1762947949)

按键函数代码

 unsigned char Key_Read()
 {
     unsigned char temp = 0;
     if(P3_4 == 0) temp = 1;
     if(P3_5 == 0) temp = 2;
     if(P3_6 == 0) temp = 3;
     if(P3_7 == 0) temp = 4;
     return temp;
 }
 ​
 /** 
 * @函数名 矩阵键盘扫描函数
 * @函数功能 返回按下的按键键码值
 * @入口参数 无
 * @返回值 按键键码值
 */
 unsigned char Key_Read_Pro()
 {
     unsigned char temp = 0;
     P3_0 = 0; P3_1 = 1; P3_2 = 1; P3_3 = 1;
     if(P3_4 == 0) temp = 1;
     if(P3_5 == 0) temp = 2;
     if(P3_6 == 0) temp = 3;
     if(P3_7 == 0) temp = 4;
     P3_0 = 1; P3_1 = 0; P3_2 = 1; P3_3 = 1;
     if(P3_4 == 0) temp = 5;
     if(P3_5 == 0) temp = 6;
     if(P3_6 == 0) temp = 7;
     if(P3_7 == 0) temp = 8;
     P3_0 = 1; P3_1 = 1; P3_2 = 0; P3_3 = 1;
     if(P3_4 == 0) temp = 9;
     if(P3_5 == 0) temp = 10;
     if(P3_6 == 0) temp = 11;
     if(P3_7 == 0) temp = 12;
     P3_0 = 1; P3_1 = 1; P3_2 = 1; P3_3 = 0;
     if(P3_4 == 0) temp = 13;
     if(P3_5 == 0) temp = 14;
     if(P3_6 == 0) temp = 15;
     if(P3_7 == 0) temp = 16;
     return temp;
 }
 ​
 /* Main */
 void main()
 {
     while(1)
     {
         #if 0
         /* 模块化编程 */
         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: //按键S1为低电平,即按键按下
                 P1_0 ^= 1; //反转LED1的亮灭状态
             break;
             case 2: //按键S2为低电平,即按键按下
                 P1_1 ^= 1; //反转LED2的亮灭状态
             break;
             case 3: //按键S3为低电平,即按键按下
                 P1_2 ^= 1; //反转LED3的亮灭状态
             break;
             case 4: //按键S4为低电平,即按键按下
                 P1_3 ^= 1; //反转LED4的亮灭状态
             break;
         }

彩灯控制系统

####代码(从里向外亮,从外向里亮)

!(file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101151909277.png?lastModify=1762947949)

![image-20251102220906113](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251102220906113.png?lastModify=1762947949)

!(file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101151934361-1761981585790-1-1761981598631-3.png?lastModify=1762947949)

入门三

数码管原理

数码管位码

  • 亮为1(高电平),灭为0(低电平)–视情况而定

![image-20251101153209692](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101153209692.png?lastModify=1762947949)

数码管断码

  • 灭为1(高电平),亮为0(低电平)

    ![image-20251101153437248](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101153437248.png?lastModify=1762947949)

动态数码管

  • 定时器结束后自动进入中断函数(原理)

  • 函数代码

    1. 搜索定时器函数

      ![image-20251101154053837](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101154053837.png?lastModify=1762947949)

    2. 编写中断函数

       /* 定时器0初始化函数 */
       void Timer0Init(void)       //1毫秒@12.000MHz
       {
           TMOD &= 0xF0;       //设置定时器模式
           TMOD |= 0x01;       //设置定时器模式
           TL0 = 0x18;     //设置定时初值
           TH0 = 0xFC;     //设置定时初值
           TF0 = 0;        //清除TF0标志
           TR0 = 1;        //定时器0开始计时
           ET0 = 1;   //定时器0中断打开
           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]);
           if(++Timer_200Ms == 200)//当计时到200Ms时
           {
               Timer_200Ms = 0;
               Led = ~Led;
           }
           if(Enable_Flag == 1)//当计时功能打开时
           {
               if(++Timer_1000Ms == 1000)
               {
                   Timer_1000Ms = 0;
                   Time_Count++;
               }
           }
       }
      

入门四

模板建立步骤(底层)

  1. 如图所示创建好工程文件夹(新增 Driver 文件夹,用于存放底层驱动)

![image-20251101154913904](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101154913904.png?lastModify=1762947949)

  1. 使用 Keil5 在工程的 User 文件夹内新建工程

![image-20251101155014365](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101155014365.png?lastModify=1762947949)

  1. 配置工程“品”字工具栏**(第二栏内新增 Driver 组,用于工程存放底层)**

![image-20251101155256114](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101155256114.png?lastModify=1762947949)

  1. 配置魔术棒**(新增对头文件引用路径添加)**

    ![image-20251101155338587](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101155338587.png?lastModify=1762947949)

![image-20251101155425352](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101155425352.png?lastModify=1762947949)

![image-20251101155430561](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101155430561.png?lastModify=1762947949)

![image-20251101155504063](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101155504063.png?lastModify=1762947949)

  1. User 组**内添加 main.c,并编写程序主体框架**

    ![image-20251101155621439](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101155621439.png?lastModify=1762947949)

    1. 新建 Key 底层文件(Key.c、Key.h),并保存在 Driver 文件夹中

      ![image-20251101155702660](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101155702660.png?lastModify=1762947949)

      1. Key.c 内编写按键底层

         #include "Key.h"
         ​
         unsigned char Key_Read()
         {
             unsigned char temp = 0;
             if(P3_4 == 0) temp = 1;
             if(P3_5 == 0) temp = 2;
             if(P3_6 == 0) temp = 3;
             if(P3_7 == 0) temp = 4;
             return temp;
         }
        
        1. 在 Key.h 内声明按键底层

           #include <REGX52.H>
           ​
           unsigned char Key_Read();
          
        2. 在 Seg.c 内编写数码管底层

           #include "Seg.h"
           ​
           unsigned char Seg_Dula[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
           unsigned char Seg_Wela[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
           ​
           void Seg_Disp(unsigned char wela,dula)
           {
               P0 = 0x00; //消影
               P2_6 = 1;
               P2_6 = 0;
               
               P0 = Seg_Wela[wela];
               P2_7 = 1;
               P2_7 = 0;   
           ​
               P0 = Seg_Dula[dula];
               P2_6 = 1;
               P2_6 = 0;   
           }
          
          1. 在 Seg.h 内声明数码管底层

             #include <REGX52.H>
             ​
             void Seg_Disp(unsigned char wela,dula);
            
            1. 添加底层到工程中

              ![image-20251101160234456](file:///D:/Users/27206/Desktop/Typora/files/Single_Chip/%E5%8D%95%E7%89%87%E6%9C%BA%E5%85%A5%E9%97%A8.assets/image-20251101160234456.png?lastModify=1762947949)

              1. 在 main.c 内编写国赛大模板(多敲就可记住)

                /* 头文件声明区 */
                #include <REGX52.H>//单片机寄存器专用头文件
                #include <Key.h>//按键底层驱动专用头文件
                #include <Seg.h>//数码管底层驱动专用头文件
                
                /* 变量声明区 */
                unsigned char Key_Val,Key_Down,Key_Old;//按键专用变量
                unsigned char Key_Slow_Down;//按键减速专用变量
                unsigned char Seg_Buf[6] = {10,10,10,10,10,10};//数码管显示数据存放数组
                unsigned char Seg_Pos;//数码管扫描专用变量
                unsigned int Seg_Slow_Down;//数码管减速专用变量
                
                
                /* 键盘处理函数 */
                void Key_Proc()
                {
                	if(Key_Slow_Down) return;
                	Key_Slow_Down = 1;//键盘减速程序
                
                	Key_Val = Key_Read();//实时读取键码值
                	Key_Down = Key_Val & (Key_Old ^ Key_Val);//捕捉按键下降沿
                	Key_Old = Key_Val;//辅助扫描变量
                
                }
                
                /* 信息处理函数 */
                void Seg_Proc()
                {
                	if(Seg_Slow_Down) return;
                	Seg_Slow_Down = 1;//数码管减速程序
                
                }
                
                /* 其他显示函数 */
                void Led_Proc()
                {
                
                }
                
                /* 定时器0中断初始化函数 */
                void Timer0Init(void)		//1毫秒@12.000MHz
                {
                	TMOD &= 0xF0;		//设置定时器模式
                	TMOD |= 0x01;		//设置定时器模式
                	TL0 = 0x18;		//设置定时初始值
                	TH0 = 0xFC;		//设置定时初始值
                	TF0 = 0;		//清除TF0标志
                	TR0 = 1;		//定时器0开始计时
                	ET0 = 1;        //定时器0中断打开
                	EA = 1;         //总中断打开
                }
                
                /* 定时器0中断服务函数 */
                void Timer0Server() interrupt 1
                {
                 	TL0 = 0x18;		//设置定时初始值
                	TH0 = 0xFC;		//设置定时初始值   
                	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//键盘减速专用
                	if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;//数码管减速专用
                	if(++Seg_Pos == 6) Seg_Pos = 0;//数码管显示专用
                	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]);
                }
                
                /* Main */
                void main()
                {
                	Timer0Init();
                	while (1)
                	{
                		Key_Proc();
                		Seg_Proc();
                		Led_Proc();
                	}
                }