51单片机—电动车报警器

一. 入门
1.1 开发环境的安装
  • 用什么写代码--语言是C,环境是keil
  • Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。
  • Keil安装
  • Keil 破戒
  • 使用
  1. 创建项目工程文件夹,可以当作模板Template
  2. 创建文件,取名main.c (要打开拓展名,在文件夹窗口上找 “查看”,勾选“文件拓展名”)
  3. 进入keil主页面,工具栏project->new uVision project->选择第一步的工程文件夹位置->输入
    工程名字->选择芯片类型AT89c52->会提示是否拷贝STARTUP.A51,选择是->生成了工程目录-

在工程目录Source Group1上右键鼠标->add Exiting file to Source Group1...->选择代码文
件main.c

  1. 编程,新手如果看不懂以下代码,可以忽略,这次实验只是强调开发流程
  2. 编译,选择输出文件有hex
#include "reg52.h"
sbit led1 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit led2 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口
void main()
{
    led1 = 0;//根据电路图,低电平点亮led
    led2 = 0;
    while(1);
}
1.2 用什么把代码放进单片机里面

STC-ISP 是一款单片机下载编程烧录软件,是针对STC系列单片机而设计的,可下载STC89系列、12C2052系列和12C5410等系列的STC单片机,使用简便。

  • 单片机通过type-C数据线和电脑连接(如果不识别,安装ch340驱动,在资料包中)
  • 选择单片机型号STC89C52RC
  • 选择生成的执行程序文件template.hex
  • 点击”下载/编程“按钮
  • 单片机开关拨动重新上电
  • 自动检测并下载了程序,看到灯亮。如果失败,仔细对照 以上每一步内容
二、 初识单片机
1.2.1 什么是单片机
  • 单片机(Single-Chip Microcomputer)是一种集成电路芯片,
  • 把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、
  • 多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)
  • 集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。
什么是单片机开发板
  • 基于单片机设计一些外接电路,模块以满足学习,日常调研等工作需求
  • STC89系列单片机
  • 命名规则,封装LQFP44, 特性 定时器,计数器,串口,看门狗,IO
三、 基本IO口控制
1.2.1 关于灯LED的那些事儿

思维发散:

  • 单片机编程是什么:人类要求单片机干具体的活,有点像提前写个小纸条贴冰箱上,告诉你女朋友
    煮鸡蛋不加水
  • 单片机执行程序怎么理解: 女朋友看到纸条后,照做!
  • 单片机能做什么事情: IO口供电,串口数据传输等
  • 肉眼可见的引脚是什么:方便人类对单片机IO口,串口接东西
  • 单片机CPU怎么找到IO口:通过寻址,说白了有一些地址数据,头文件帮你做很多了
  • 怎么写纸条(编程)找到IO口呢:ANSI C

sfr"指令": 用来直接描述硬件地址,小白先理解成"一组IO口"的起始地址中数据 sfr P0 = 0x80; P0 = 0;

  • 怎么找到IO口的具体一个引脚呢:

sbit"指令",对应可位寻址空间的一个位,小白先理解成"一个IO口/针脚"的地址中数据 sbit led2 = P3^6

c语言的一个字节,char型就是8位

注:sfr sbit 非c的标准库 只有在51单片机中使用
上官一号89C52有5组这样的输入输出口,分别为P0,P1,P2,P3每组对应8个针脚,P4是RC系列才有只有7个
针脚

1. sfr 指令

"sfr" 是 Special Function Register 的缩写,用于定义特殊功能寄存器的地址。通常这些寄存器用于控制微控制器的各种外设(例如I/O端口,定时器,中断控制器等)。例如,sfr P0 = 0x80; 这行代码定义了一个名为 P0 的寄存器,并将其地址设置为 0x80

sfr P0 = 0x80;  // 定义特殊功能寄存器 P0,其地址为 0x80
P0 = 0;         // 将 P0 寄存器的值设置为 0

在这个例子中,P0 是微控制器的一个 I/O 端口。通过设置 P0 的值,我们可以控制这个端口上的所有引脚。例如,将 P0 设置为 0 意味着将端口 P0 上的所有引脚都拉低(即设置为 0)。

2. sbit 指令

"sbit" 是用于定义单个位的地址。例如,可以用它来定义某个 I/O 端口的特定引脚。下面的代码定义了 P3 端口的第 6 位(引脚)。

sbit led2 = P3^6;  // 定义 led2 位,表示 P3 端口的第 6 引脚

在这个例子中,P3 是一个 I/O 端口,而 P3^6 表示这个端口的第 6 位。通过操作 led2,可以单独控制 P3 端口的第 6 引脚。例如:

led2 = 1;  // 将 P3 端口的第 6 引脚设置为高电平
led2 = 0;  // 将 P3 端口的第 6 引脚设置为低电平
总结
  • sfr 指令:用于定义整个 I/O 端口或特殊功能寄存器。例如:sfr P0 = 0x80; 定义了地址为 0x80 的寄存器 P0
  • sbit 指令:用于定义特定 I/O 端口的某个位。例如:sbit led2 = P3^6; 定义了 P3 端口的第 6 引脚。
四、 输入&&输出

是对单片机来讲的,IO口的 输入(把外面东西拿回来)/输出(给东西给外面)

89C52比较简单粗暴,关于引脚输入还是输出的功能不需要配置

  • 比如
sbit IFfire = P1^0;
int main()
{
    int io_data;
    //什么情况叫做输入
    io_data = IFfire; // 给变量赋值,就是输入 —— 或者理解为,这个针脚有数据啦,拿个变量来
    保存
    if(io_data == 0){
    }
    //什么情况叫做输出
    IFfire = 1; // 被给予一个数值,引起IO口电压变化(一般1输出高电平,0输出低电平),此时为输
出,来影响外接的电路
return 0;
}

如何使用 sbit 指令来定义和操作一个单独的 I/O 引脚。以下是逐行的中文解释:

sbit IFfire = P1^0;  // 定义一个名为 IFfire 的位变量,它代表 P1 端口的第 0 引脚
  • sbit IFfire = P1^0;:这行代码使用 sbit 指令定义了一个位变量 IFfire,它表示 P1 端口的第 0 位(即第 0 引脚)。
int main()          // 主函数入口
{
    int io_data;    // 定义一个整型变量 io_data
  • int io_data;:定义一个整型变量 io_data,用于存储 I/O 引脚的数据。
io_data = IFfire; // 读取 P1 端口第 0 引脚的值,并赋值给变量 io_data
  • io_data = IFfire;:这行代码将 P1 端口第 0 引脚的电平状态(高或低)读入到变量 io_data 中。这就是所谓的“输入”操作,因为它是从引脚读取数据。
if(io_data == 0){
    // 如果 io_data 的值为 0,则执行这里的代码
}
  • if(io_data == 0){}:检查 io_data 的值是否为 0。如果是 0,则表示 P1 端口第 0 引脚当前为低电平。
IFfire = 1; // 将 P1 端口第 0 引脚的电平设置为高电平(输出)
  • IFfire = 1;:这行代码将 P1 端口第 0 引脚的电平设置为高电平。这是“输出”操作,因为它改变了引脚的电平,从而影响外部电路。
return 0; // 返回 0,表示程序正常结束
}
  • return 0;:主函数返回 0,表示程序正常结束。
总结
  • sbit IFfire = P1^0;:定义了 P1 端口第 0 引脚为 IFfire
  • io_data = IFfire;:读取 P1 端口第 0 引脚的电平状态到变量 io_data 中(输入操作)。
  • if(io_data == 0){}:检查 P1 端口第 0 引脚的电平状态是否为低电平。
  • IFfire = 1;:将 P1 端口第 0 引脚的电平设置为高电平(输出操作)。
五、52开发板入门
5.1 为什么灯会亮

得看电路图,但是不要怕,初中电路知识而已!也叫单片机原理图,是硬件设计者设计的

记住:原理图中标号一样代表是同一根“电线”

简单的串联电路,D4,D5,D6板子上有标记, D5一端通过电阻接5v,另外一端接着"LED1标志的线",我

们发现在89C52RC的电路图中也有LED1的标志,是在P3的IO口组中,在P3.7引脚,所以编程让P3.7出

低电平(0)就让D5灯完成一个串联电路,所以亮

led 表示二极管,key表示按键。

D4是完整的串联电路,通过电源5v->电阻->二极管,然后接地(GND)即可点亮。

GND 就是低电平 0;

D4不是完整的串联电路,通过电源5v->电阻->二极管,然后将P3^7口等于0,即接地(GND)可点亮。

D4不是完整的串联电路,通过电源5v->电阻->二极管,然后将P3^6口等于0,即接地(GND)可点亮。

D5为P3^7口,将P3^7口等于0就会亮。

D6为P3^6口,将P3^6口等于0就会亮。

  • 下面看一下代码:
#include "reg52.h"

sbit ledOne = P3^7; // i|o口赋值给变量
sbit ledtwo = P3^6; // i|o口赋值给变量

void main()
{
    // D5为P3^7口,将P3^7口给个低电平,就会亮。
    // D6为P3^6口,将P3^6口给个低电平,就会亮。
    ledOne = 0;
    ledtwo = 0;
}
5.2 怎么做,D5D6,才会闪烁
  • 使用STC-ISP自带延时函数
#include "reg52.h"
sbit ledOne = P3^7;
sbit ledTwo = P3^6;
void Delay500ms() //@11.0592MHz   //使用STC工具中的延迟生成器自动生成延时函数
{
    unsigned char i, j, k;
        i = 4;
        j = 129;
        k = 119;
        do
        {
            do
            {
                while (--k);
            } while (--j);
        } while (--i);
    }
void main()  //重复执行
{
    //灯灭,给一个高电平
    //重复执行
    while(1){
    //灯亮,给一个P3.7低电平
        ledOne = 0 ;
        ledTwo = 0 ;
        //数数,数的期间,维持低电平,灯亮,延迟
        Delay500ms();
        //灯灭,给一个高电平
        ledOne = 1;
        ledTwo = 1 ;
        //数数,数的期间,维持高电平,灯灭,延迟
        Delay500ms();
    }
}
5.2.1打开STC-ISP软件---找到软件延时计算器,按照以下我给参数进行修改。

一步使代码变万能

软件所生成的函数是延时 500ms,就是说单片机执行这个函数的程序体时用时为 500ms,那么首先我们用 while 循环把程序体框住,然后每执行一次让控制 while 循环结束的变量减一,这个变量我们通过形参传递到函数中。

注意:当使用 _nop_() 函数(可理解为软件延时)时,必须在开头添加头文件 #include <intrins.h>。不然回报错。

  • 优化后的代码如下:
void Delay500ms() //@11.0592MHz   //使用STC工具中的延迟生成器自动生成延时函数
{
    unsigned char i, j, k;
        i = 4;
        j = 129;
        k = 119;
        do
        {
            do
            {
                while (--k);
            } while (--j);
        } while (--i);
    }

至此,51 单片机的延时函数就编写完成啦, 快去试着生成一个延时函数,将它应用到你的项目当中吧。

1.2.2 按键控制灯

原理:按键和灯不是我们传统理解的思维,传统按键和灯是在同一个电路中的。而我们单片机编程按键

和灯是分开的两个电路,通过单片机作为媒介来处理数据,通过逻辑来实现按键控制灯

查询法按键控制灯

  • 怎么知道sw1按键被按下

KEY1位置和GND接通,表现为低电平,值为0

  • 怎么知道sw1按键没有被按下

KEY1位置通过上拉电阻到5V,表现为高电平,值为1

通过图a2得知

同理LED的分析,

KEY1接到STC89C52RC的P2.1口,我们只要不断检测P2.1口的值(0-按下,1-松开)就知道按键是

否被按下

  • 按键控制灯
#include "reg52.h"
    sbit key1 = P2^1;
    sbit ledOne = P3^7;
void main()
{
    while(1){
        //注意:用“==”两个等于号表示判断,新手容易犯错
        if(key1 == 0){ //KEY1位置和GND接通,表现为低电平,值为0
        //灯亮,给一个P3.7低电平
        ledOne = 0;
        }
    }
}
  • 按键控制灯,SW1开,SW2关, 软件消除抖动
#include "reg52.h"
#include <intrins.h>
    sbit key1 = P2^1;
    sbit key2 = P2^0;
    sbit ledOne = P3^7;
void Delay50ms() //@11.0592MHz
{
    unsigned char i, j, k;
        _nop_();
        _nop_();
        i = 3;
        j = 26;
        k = 223;
        do
            {
            do
                {
                while (--k);
            } while (--j);
        } while (--i);
    }
void main()
{
//查询法检测,是否被按下
    while(1){
        if(key1 == 0)//KEY1位置和GND接通,表现为低电平,值为0
        {
        //感觉被按下,不知道是抖动还是人为,延迟50ms再判断一次
        //软件消除抖动
            Delay50ms();
            if(key1 == 0){
            //灯亮,给一个P3.7低电平
                ledOne = 0;
            }
        }
        if(key2 == 0){//KEY2位置和GND接通,表现为低电平,值为0
            Delay50ms();
            if(key2 == 0){
            //灯亮,给一个P3.7低电平
            ledOne = 1;//灭
        }
    }
}
  • 按键按下一次,灯状态改变
#include "reg52.h"
#include <intrins.h>
    sbit key1 = P2^1;
    sbit key2 = P2^0;
    sbit ledOne = P3^7;
void Delay50ms() //@11.0592MHz
{
    unsigned char i, j, k;
        _nop_();
        _nop_();
        i = 3;
        j = 26;
        k = 223;
        do
            {
            do
                {
                while (--k);
            } while (--j);
        } while (--i);
    }
void main()
{
   
    ledOne = 1;  //初始灯是灭的状态
    //查询法检测,是否被按下
    while(1){
        if(key1 == 0)//KEY1位置和GND接通,表现为低电平,值为0
        {
        //感觉被按下,不知道是抖动还是人为,延迟50ms再判断一次
        //软件消除抖动
        Delay50ms();
            if(key1 == 0){
            //记住,key1被按下,记住,在其他地方点灯
                 ledOne = !ledOne; 
                }
            }	
            if(key2 == 0){//KEY2位置和GND接通,表现为低电平,值为0
                 ledOne = 1;  
            }
    }
}
  • 状态位来控制LED
#include "reg52.h"
#include <intrins.h>

#define ON_STATUS   1
#define OFF_STATUS  0
    sbit key1 = P2^1;
    sbit key2 = P2^0;
    sbit ledOne = P3^7;
void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

		i = 18;
		j = 235;
		do
		{
			while (--j);
		} while (--i);
	}

void main()
{
    int ledMark = OFF_STATUS;
    ledOne = 1;  //初始灯是灭的状态
    //查询法检测,是否被按下
    while(1){
        if(key1 == 0)//KEY1位置和GND接通,表现为低电平,值为0
        {
        //感觉被按下,不知道是抖动还是人为,延迟50ms再判断一次
        //软件消除抖动
        Delay10ms();
            if(key1 == 0){
            //记住,key1被按下,记住,在其他地方点灯
                ledMark = ON_STATUS;
                }
            }
         Delay10ms();
            if(key2 == 0){//KEY2位置和GND接通,表现为低电平,值为0
                ledMark = OFF_STATUS;
            }
            if(ledMark == OFF_STATUS){
                ledOne = 1;
            }
            else{
                ledOne = 0;
            }
        }
}

六、入门项目电动车报警器

1.3.1 硬件清单列表

振动传感器模块,继电器模块,433M无线模块,反应出来的代码都是高低电平,跟以上学习按键,LED

并没有区别

但是!做出来有乐趣,好玩刺激。

1.3.2 振动传感器控制灯

通过我们已经掌握的LED来了解下振动传感器是怎么回事

  • 如何知道是否发生振动

振动传感器检测是否有振动产生。

  • 振动后的信号表现又是什么

传感器监测到振动之后,向I|0输出低电压。绿灯会亮。如果没有监测到振动时,就输出高电压

  • 振动传感器控制灯
#include "reg52.h"
sbit led1 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit vibrate = P3^3;//Do接到了P3.3口  振动传感器
void Delay2000ms() //@11.0592MHz
{
    unsigned char i, j, k;
    // _nop_();
    i = 15;
    j = 2;
    k = 235;
        do
        {
            do
            {
                while (--k);
            } while (--j);
        } while (--i);
    }
void main()
{
    //查询方式判断是否发生震动
    while(1){
        if(vibrate == 0)//模块说明告诉我们,震动的话,D0输出低电平
        {
            led1 = 0;//亮灯
            Delay2000ms();   // 延迟2秒
            led1 = 1;
        }
        else{
            led1 = 1;//灭灯
    }
}
1.3.3 继电器工作逻辑

其实就是电子开关,怎么开怎么关弄清楚就可以了

  • 怎么控制“闭合”开关呢
    • 传感器监测到振动之后,向I|0输出低电压。继电器开关闭合。
  • 怎么控制"断开"开关呢
    • 默认是闭合状态,如果没有监测到振动时,就输出高电压,继电器开关闭合。

通过继电器来控制电路,比如智能插座,比如220V的灯,比如我们项目不带开关的傻瓜式报警器

当设置继电器为低电平处罚时,STC89C52RC的IO输出低电平,就会导致COM口和NO口闭合,也

就是完成报警器的串联电路,开始响

现在我们就可以来写程序,完成振动控制警报的功能

#include "reg52.h"
sbit vibrate = P3^3;//Do接到了P3.3口
sbit switcher = P1^1;  //继电器
void Delay2000ms() //@11.0592MHz
{
    unsigned char i, j, k;
    // _nop_();
        i = 15;
        j = 2;
        k = 235;
    do
        {
            do
            {
                while (--k);
        } while (--j);
    } while (--i);
}
void main()
{
    //查询方式判断是否发生震动
    while(1){
        if(vibrate == 0)//模块说明告诉我们,震动的话,D0输出低电平
        {
        //当发生震动适合,导通继电器,给继电器IN一个低电平
            switcher = 0;
            Delay2000ms(); //闭合两秒之后,继电器断开
            switcher = 1;//高电平,继电器N0和COM不通
        }
        else{
            switcher = 1;
        }
    }
}
1.3.4 遥控发送接收433M

https://wenku.baidu.com/view/8fe8f444bed5b9f3f80f1c33.html

  • 遥控按下后信号怎么被接收
  • 接收后的信号表现又是什么
    • 默认低电平,按键之后是高电平。
  • 遥控控制LED
#include "reg52.h"
sbit D0_ON = P1^2;   //遥控传感器  A键
sbit D1_OFF = P1^3;  //遥控传感器  B键
sbit switcher = P1^1;   // 继电器
void main()
{
//查询方式哪个按键被按下
    while(1)
    {
        if(D0_ON == 1)//收到遥控信号A,D0表现为高电平
        {
        //A被按下,我们导通继电器,给继电器IN一个低电平
            switcher = 0;  //喇叭报警
        }
        if(D1_OFF == 1)//收到遥控信号C,D1表现为高电平
        {
        //B被按下,我们不导通继电器,给继电器IN一个高电平
            switcher = 1;  //喇叭关闭
        }
    }
}
1.3.4 项目开发

接线

  • 开发流程代码
#include "reg52.h"
#include<intrins.h>
#define J_ON 1
#define J_OFF 0
sbit switcher = P1^0;  // 继电器
sbit D0_ON = P1^1;     // A 键
sbit D1_OFF = P1^2;   // B 键
sbit vibrate = P1^3;   // 振动传感器
void Delay2000ms() //@11.0592MHz
{
    unsigned char i, j, k;
    _nop_();
    i = 15;
    j = 2;
    k = 235;
    do
        {
            do
            {
                while (--k);
            } while (--j);
        } while (--i);
    }
void Delay500ms() //@11.0592MHz
{	
        unsigned char i, j, k;
        _nop_();
        i = 4;
        j = 129;
        k = 119;
        do
            {
                do
                {
                    while (--k);
            } while (--j);
        } while (--i);
    }
void main()
{
    int mark = J_OFF;
        while(1)
        {
        //1. 如果a按键被按下,设定为开启警报模式
            if(D0_ON == 1){
            //长响,表示进入警报模式
                switcher = 0;
                Delay2000ms();
                switcher = 1;
                //设定警报模式标记
                mark = J_ON ;
            }
            //2. 如果b按键被按按下,设定为关闭警报模式
            if(D1_OFF == 1){
            //短响,表示进入解除警报模式
                switcher = 0;
                Delay500ms();
                switcher = 1;
                //设定警报解除模式标记
                mark = J_OFF ;
            }
            //3. 如果标记是在警报模式下
            if(mark == J_ON){
            //3.1 如果发生了震动
                if(vibrate == 0){
                //喇叭响,给继电器低电平,导通
                    switcher = 0;
                    Delay2000ms();//闭合2秒之后,继电器断开
                    switcher = 1;//高电平,继电器N0和COM不通
            }//3.2 如果不发生震动
            else{
            //喇叭不响,给继电器高电平,不导通
                switcher = 1;
            }
        }
    }
}

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值