单片机入门
入门一
LED 灯输入低电平/高电平原理

- LED 灯左为 VCC,右必须为低电平(0),LED 才导通
控制 LED 灯亮灭
-
对 P1 整体进行赋值

-
对 P1 中 8 个 IO 口单独赋值
延时函数(可赋变量)
- 在 STC-ISP 中搜索延时函数(1ms)

-
赋变量,加 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(低电平)
-

按键函数代码
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)

!(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(低电平)–视情况而定

数码管断码
-
灭为1(高电平),亮为0(低电平)

动态数码管
-
定时器结束后自动进入中断函数(原理)
-
函数代码
-
搜索定时器函数

-
编写中断函数
/* 定时器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++; } } }
-
入门四
模板建立步骤(底层)
- 如图所示创建好工程文件夹(新增 Driver 文件夹,用于存放底层驱动)

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

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

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




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

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

-
在
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; }-
在 Key.h 内声明按键底层
#include <REGX52.H> unsigned char Key_Read(); -
在 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; }-
在 Seg.h 内声明数码管底层
#include <REGX52.H> void Seg_Disp(unsigned char wela,dula);-
添加底层到工程中

-
在 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(); } }
-
-
-
-
-
-