【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来!

《QT开发实战》

《嵌入式通用开发实战》

《从0到1学习嵌入式Linux开发》

《Android开发实战》

《实用硬件方案设计》

长期持续带来更多案例与技术文章分享;

欢迎商业项目咨询,10年+软硬全栈内功,助力解决您的尊贵需求。

——————————————————————————————————

目录

0 引言

1 功能需求

2 方案设计

2.1 硬件设计

2.1.1 STC12C5A60S2单片机最小系统

2.1.2 步进电机

2.1.3 按键/显示接口电路

2.1.4 传感器

2.2 软件设计

2.2.1 主程序软件设计

2.2.2 步进电机子程序设计

2.2.3 显示子程序设计

2.2.4 按键子程序设计

2.2.5 定时子程序设计

3 总结

附1:作品实拍

附2:汇编语言代码


0 引言

整理资料时,发现了学生时代一些好的电子设计,这些设计在当时也是比较不错的,到现在看来已经年代久远了,不过放在今天自己DIY下给小朋友,培养兴趣爱好,也是很好的。

今天分享的是基于STC单片机设计的自动窗帘控制升降系统,根据其不同控制模式,实现半自动控制、自动控制、定时控制和无线控制的相互转换控制窗帘机。该设计由光电开关电路、按键控制模块、无线遥控模块等组成,可实现窗帘自动升降。这个小电子设计当时得了校电子设计大赛一等奖,翻看了下,连编程语言都是用汇编写的,现在想想,那时候真是初生牛犊不怕虎啊。

1 功能需求

自动窗帘主要有以下几大功能:

  • 1)手动控制:电动窗帘具有手动正转、手动反转 和手动停止的功能;
  • 2)工作状态指示:电机工作在正转、反转和停止状态的时候,数码管均有不同工作状态指示;
  • 3)半自动控制:在需要关闭或打开窗帘的时候,只需要人工按一下“正转”或“反转”按键后,窗帘到位自动停止;
  • 4)无线控制:通过远程遥控器,控制窗帘的正转、反转 和停止;
  • 5)环境亮度控制:通过自动感知环境亮度完成窗帘的开启或关闭操作控制,“天黑关闭,天亮打开”具有智能管理,不产生误动作;
  • 6)定时控制:根据设置输入的开启或关闭时间,来控制窗帘的关闭和打开。

2 方案设计

基于以上需求,使用基于单片机的方案实现,单片机应用系统由硬件和软件组成。硬件由单片机,输入/出设备以及各种实现单片机系统控制要求的接口电路和有关的外围电路芯片或部件组成;软件由单片机应用系统实现其特定控制功能的各种工作程序和管理程序组成。

本自动窗帘控制升降系统采用STC12C5A60S2单片机作为主控器,窗帘的正转、反转和停止功能可由单片机输出电平来控制步进电机的运转实现;环境亮度的控制通过光敏电阻和运放组成的电路来控制单片机输出电平继而控制电机的正转和反转;时间自动控制可以由定时器来控制;无线控制由无线收发模块完成。由光电传感器来探测外界的光强,后的信号由单片机控制器,来实现电机的运行与停止。显示部件用来显示电动窗帘控制器的各种状态信息。键盘是主要的输入设备,控制单片机的各种参量。

窗帘控制器可以使用无线遥控器进行远程手动开、手动关和手动停控制;可以执行事先输入的开启时间和关闭时间进行时间控制。三种工作方式可以方便地进行选择,当选择时间控制的方案时,数码管还能显示当时小时和分钟时间。

2.1 硬件设计

当时是使用Protues仿真软件设计的电路图,该软件可以进行仿真,验证设计的功能是否正确。系统总体的硬件接线图如下:

总体硬件电路图包括单片机外围电路、检测电路、键盘/显示接口电路、步进电机控制电路等模块。单片机外围电路提供各模块所需的5V电源和时钟模块;单片机的P2口控制步进电机的运行从而控制窗帘的升降。显示和键盘让人机交换变得更容易。以上各模块组成了电动窗帘控制器的总体电路。因当时proteus器件库中不含STC12C5A60S2,仿真电路中单片机芯片采用AT89C51。

2.1.1 STC12C5A60S2单片机最小系统

(1)STC12C5A60S2单片机

89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—Falsh Programmable and Erasable Read Only Memory)的低电压,高性能CMOS8位微处理器,俗称单片机。STC12C5A60S2/AD/PWM系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。STC12C5A60S2单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。

(2)晶振电路

电路中的晶振即石英晶体震荡器。由于石英晶体震荡器具有非常好的频率稳定性和抗外界干扰的能力,所以,石英晶体震荡器是用来产生基准频率的。通过基准频率来控制电路中的频率的准确性。同时,它还可以产生振荡电流,向单片机发出时钟信号。

下图是单片机的晶振电路。电路中的电容C1和C2的典型值通常选择为30PF左右,该电容的大小会影响振荡电路频率的高低、振荡器的稳定性和起振的快速性。晶体振荡频率的范围通常在1.2~12MHz。晶体的频率越高,系统的时钟频率越快,单片机的运行速度越快。但反过来,运行速度对于存储器的速度要求就越高,对印刷电路板的工艺要求也就越高,即要求线间的寄生电容要小。晶体和电容应该尽可能安装得与单片机芯片靠近,以减少寄生电容,更好地保证振荡器稳定、可靠地工作。

(3)复位电路

复位是单片机的初始化操作,只需要给STC12C5A60S2的复位引脚RST加上大于2个机器周期(即24个时钟振荡周期)的高电平就可以使STC12C5A60S2复位。复位时,单片机初始化为0000H,从0000H单元开始执行程序。除了进入系统的正常初始化之外,当程序运行错误(如程序跑飞)或操作错误使系统处于锁死状态时,也需要复位键使RST脚为高电平,使STC12C5A60S2摆脱“跑飞”或“死锁”状态而重新启动。

2.1.2 步进电机

步进电机是一种将电脉冲转化为角位移的执行机构。通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时也可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
        步进电机28BYJ48型四相八拍电机,电压为DC5V—DC12V。当对步进电机施加一系列连续不断的控制脉冲时,它可以连续不断地转动。每一个脉冲信号对应步进电机的某一相或两相绕组的通电状态改变一次,也就对应转子转过一定的角度(一个步距角)。当通电状态的改变完成一个循环时,转子转过一个齿距。四相步进电机可以在不同的通电方式下运行,常见的通电方式有单(单相绕组通电)四拍(A-B-C-D-A。。。),双(双相绕组通电)四拍(AB-BC-CD-DA-AB-。。。),八拍(A-AB-B-BC-C-CD-D-DA-A。。。)

步进电机控制系统的方框图如下:

选用的步进电机接线方式:

红线接电源5V,其他四根线接单片机IO口,由于单片机接口驱动能力不足,需要使用ULN2003进行电机驱动:

2.1.3 按键/显示接口电路

按键在单片机应用系统中能实现向单片机输入数据,传送命令等功能,是人工干预单片机的主要手段。本设计中的功能按键有:当前时间设定键(调整时间 分);闹铃时间设定键(调整时间时);自动窗帘开和关的定时控制键;确定键,时间设定完成后确定输入;复位键,在程序出错或者有误操作的时候;正转键,使步进电机正转,窗帘打开;反转键,使步进电机反转,窗帘关闭;停止键,步进电机停止运转。

按键的触点在闭合和断开时均会产生抖动,这时触点的逻辑电平是不稳定的,如果不妥善处理,将会引起按键命令的错误执行或重复执行。一般消除抖动采用软件方法来解决,将在软件部分介绍这点。

显示部分则主要显示时间,用于设置时间。采用LED数码管进行显示是一种经济实用的方法。每位数码管由7个笔画加上小数点共8个发光二极管组成;有共阴极和共阳极两种类型,公共端用来进行位控制,笔画端用来进行字符控制;数码管显示有静态显示和动态显示两种方法。

在数码管显示中,有2个技术问题需要解决,这就是整数高位和闪烁显示问题。虽然某些新型LED驱动芯片本身具有闪烁控制和熄灭控制功能,但通过合理的软件设计,采用廉价芯片组成的驱动电路同样可以实现整数高位灭零和闪烁显示功能,达到降低系统硬件成本的目的。本设计采用的就是4位LED数码管的串行驱动电路来达到显示时间和消除闪烁显示的目的。驱动器采用74LS245,显示电路图如下:

2.1.4 传感器

电动窗帘要根据光照的情况而自动开关窗帘,因而需要使用到光电传感器。这里使用光敏电阻,光敏电阻是用光电导体制成的光电器件,又称光导管,他是基于半导体光电效应工作的。光敏电阻没有极性,纯粹是一个电阻器件,使用时可以加直流偏压,也可以加交流电压。当无光照时,光敏电阻值(暗电阻)很大,电路中电流很小。当光敏电阻受到一定波长范围的光照时,它的阻值急剧减少,因此电路中电流迅速增加。光敏电阻具有很高的灵敏度,很好的光谱特性,光谱响应从紫外区一直到红外区。而且体积小、重量轻、性能稳定。因此在自动化技术中得到广泛的应用。光敏电阻器一般用于光的测量、光的控制和光电转换(将光的变化转换为电的变化)。通常,光敏电阻器都制成薄片结构,以便吸收更多的光能。当它受到光的照射时,半导体片(光敏层)内就激发出电子—空穴对,参与导电,使电路中电流增强。

根据光敏电阻的光谱特性,可分为三种光敏电阻器:

  • 1)紫外光敏电阻器:对紫外线较灵敏,包括硫化镉、硒化镉光敏电阻器等,用于探测紫外线。
  • 2)红外光敏电阻器:主要有硫化铅、碲化铅、硒化铅。锑化铟等光敏电阻器,广泛用于导弹制导、天文探测、非接触测量、人体病变探测、红外光谱,红外通信等国防、科学研究和工农业生产中。
  • 3)可见光光敏电阻器:包括硒、硫化镉、硒化镉、碲化镉、砷化镓、硅、锗、硫化锌光敏电阻器等。主要用于各种光电控制系统,如光电自动开关门户,航标灯、路灯和其他照明系统的自动亮灭,自动给水和自动停水装置,机械上的自动保护装置和“位置检测器”,极薄零件的厚度检测器,照相机自动曝光装置,光电计数器,烟雾报警器,光电跟踪系统等方面。这里选用可见光光敏电阻器。

应用光控原理工作,天亮窗帘自动打开,天黑窗帘自动关闭。上图中使用LM358做的比较电路,同相输入端有两个电阻分压得到一个电压值,作为基准电压进行比较,而反相输入端用一个光敏电阻对外部环境的光线进行采集,利用光敏电阻暗时电阻大,亮时电阻小的特点,来确定反向输入端的电压值。再两者进行比较,比较后的信号再送入单片机89C2051的IO口,输出高/低电平,从而通过单片机来控制电机的正反转。来实现天亮窗帘自动打开,天黑窗帘自动关闭这一自动控制功能。另外反相输入端可以通过可变电阻改变分压值,进而调节感光的灵敏度。

2.2 软件设计

系统软件设计主要包括显示子程序,键盘子程序,时钟程序,步进电机控制程序设计及部分构成。本章节系统的介绍了电动窗帘的主程序和各主要功能子程序的设计流程,具体的程序代码见附录。

2.2.1 主程序软件设计

主程序大循环,主要完成单片机初始化,关中断,菜单显示内容初始化,按键扫描,电机运行,计时等功能。

启动主程序,先关中断并且设置堆栈,接着初始化寄存器,初始化显示内容;然后执行按键查询,执行相应的操作。如果是设定键,则设定时间,开始计时;到时间后步进电机开始相应的工作,工作完成后停机。如果是电机控制键,则也执行相应的工作。如果都不是,则是复位键,采取复位操作。

2.2.2 步进电机子程序设计

步进电机程序设计的主要任务有三点:

  • 1)判断旋转方向;
  • 2)按顺序传送控制脉冲;
  • 3)判断所要求的控制步数是否传送完毕。

2.2.3 显示子程序设计

显示程序开始后,起始地址60H发送到R0,01H发送至显示位代码R2,再将位代码发送到单片机A口,单片机取显示数据查表转换成显示代码发送至单片机B口,延时2ms,指针R0加1,然后判断6显示是否完成。如果完成则返回,没完成则位代码R2左移一位,继续显示查表,一直到6位显示完成后返回。

2.2.4 按键子程序设计

按键的触点在闭合和断开时均会产生抖动,这时触点的逻辑电平是不稳定的,如不妥善处理,将会引起按键命令的错误执行或者重复执行。现在用软件延时的方法来避开抖动阶段。在判断是否有键闭合后都延时5ms,按下键后再延时12ms就可以避免键盘的抖动。然后键码分析,执行相应的模块,显示后返回。

2.2.5 定时子程序设计

定时的主要功能是在设定时间单片机能够得到中断信号,从而控制窗帘的开关。时钟发出50ms的信号给单片机,计数器计数,当计数到20,则过了1秒,秒单元数值加1,当秒单元到达60,分单元数值加1,秒单元清零。当时单元到达24,时单元清零。标志1天时间计满,把他们的值放到存储单元的指定单元。

3 总结

博主在整理此篇文章时,充满了对学生时代满满的回忆,因为这个电子设计是博主从事工程师生涯的第一个作品,当时得了校级电子设计大赛一等奖,怀念当时一起组队的小伙伴。这个作品现在看来可能很简单,但在当时刚刚入门的阶段,完成它也算是经历了千辛万苦的,清晰的记着因为一点硬件问题去电子城买器件的契机请教老师傅,去学校实验室请教高年级学长,到网上查资料,到图书馆恶补专业知识,大学时代真的是太美好了。

作于202204281410,已归档

———————————————————————————————————

本文为博主原创文章,未经博主允许不得转载!

若本文对您有帮助,轻抬您发财的小手,关注/评论/点赞/收藏,就是对我最大的支持!

祝君升职加薪,鹏程万里!

附1:作品实拍

当时都是手工焊接的,看起来有些简陋吧。现在有些器件已经丢了,运行不起来了,这么多年过去了,板子一直留在身边:)

附2:汇编语言代码

当时才大二,C语言刚刚学习,汇编语言学的较多,所以当时就勇者无畏的使用了汇编语言编程:)

主程序:
ALB    EQU    20H.0        ;闹铃标志位
K5 EQU P0.0            ;设定P0.0以K5表示    正
K6 EQU P0.1            ;设定P0.1以K6表示    反
K7 EQU P0.2            ;设定P0.2以K7表示    停
K8 EQU P0.3            ;设定P0.3以K8表示    转换
K9 EQU P3.7              ;光敏信号
K10     EQU             P3.6      ;复位调节键K2  EQU     P0.5        ;小时控制位
K1  EQU     P0.4        ;分钟控制位
K3      EQU             P0.6      ;时间确认按键
K4      EQU             P0.7      ;电机正反辨认
SEC EQU     38H      ;存放秒钟变量
MIN EQU     37H      ;存放分钟变量
HOUR    EQU     36H      ;存放时钟变量
TCNT    EQU     39H      ;存放50ms计数HH        EQU                        40H      ;闹钟设置小时变量
MM       EQU                        41H      ;闹钟设置分钟变量
SS        EQU                        42H      ;闹钟设置秒钟变量
;程序开始
ORG     00HSJMP STARTORG        0BHLJMP INT_T0
START:
;初始化
MOV R1,#1             ;用于计电机转数
MOV R3,#0             ;用于计电机转数MOV       HOUR,#0                         MOV     MIN,#0MOV       SEC,#0MOV       TCNT,#0MOV      TMOD,#01H  MOV      TH0,#3CH        ;定时50毫秒MOV      TL0,#0B0HMOV        IE,#82HSETB TR0
;****************************************************
;无穷循环,判断是否有控制键按下,是哪一个键按下
LOOP:   ACALL  CONVACALL  TIME_PRO       ;检查闹铃时间
JB K8,L12           ;开关转换光控制
JNB K5, ZM_2           ;是否按K5,是则正转JNB K6, FM_2           ;是否按K6,是则反转JNB K7, STOP1          ;是否按K7,是则停止JB K10,TJ               ;是否按K10,是则调节反转
JNB K10,$LCALL  F_MTJTJ:    JB        K1,M1ACALL    SET_TIME        ;设置目前时间JMP    LOOP;设置闹铃时间
M1:JB K2,M2            ;未按下K2,则继续扫描ACALL  SET_ATIME  ;设置闹铃时间SETB ALBJMP LOOP            ;跳到LOOP处执行
M2:JB K1,M3            ;未按下K1,则继续扫描JMP LOOP            ;跳到LOOP处执行
M3:JB K3,M4            ;未按下K3,则继续扫描JMP LOOP            ;跳到LOOP处执行
M4:JMP LOOP            ;跳到LOOP处执行L12:  JNB K9,FM_3           JB K9,ZM_3;***********************************************
STOP: MOV P3,#0F0H          ;步进电机停止工作JMP LOOP;开关控制步进电机正反转程序ZM_3:LCALL DELAY1CJNE R3,#40, Z_M       ; 检测正转是否满JMP  LOOP               ;转至LOOP
FM_3:LCALL DELAY1CJNE R3,#0, F_M       ; 检测反转是否满JMP  LOOP               ;转至LOOPFM_2: LCALL DELAY1            ;按K6键消抖JNB K6,$              ;K6是否放开LCALL DELAY1            ;放开消抖CJNE R3,#0, F_M          ;是否反转满JMP  LOOP                ;转至LOOP
ZM_2: LCALL DELAY1            ;按K5键消抖JNB K5,$              ;K5是否放开LCALL DELAY1            ;放开消抖CJNE R3,#40, Z_M       ; 检测正转是否满JMP  LOOP               ;转至LOOP
;***********************************************
STOP1:LCALL DELAY1           ;按K7键消抖JNB K7,$              ;K7是否放开LCALL DELAY1            ;放开消抖JMP STOP               ;电机停止
;执行闹铃处理
TIME_OUT:
JB  K4,Z
JMP    F
Z: ACALL  ZM_3 CLR ALBLJMP LOOPF:ACALL   FM_3
CLR ALB
LJMP LOOPRET
Z_M: MOV R0,#00H            ;正转到TABLE取码指针初值
Z_M1: MOV P3,#00HMOV A,R0                MOV DPTR,#TABLE1         ;存表MOVC A,@A+DPTR           ;取表代码JZ Z_M                  ;是否取到结束码MOV P3,A               ;输出
JNB K7,STOP1           ;若按K7键,停止转动JNB K6,FM_2            ;若按K6键,反转动LCALL CONVINC R0                  ;取下一码INC R1                  ;计数   CJNE R1,#255, Z_M1       ;循环MOV R1,#00HINC R3                  ;计数 CJNE R3,#40, Z_M1       ;循环MOV P3,#0F0H            ;计数满停止工作LJMP LOOPRET
;反转子程序
F_M : MOV R0,#09H            ;反转到TABLE取码指针初值
F_M1: MOV P3,#00HMOV A,R0                MOV DPTR,#TABLE1         ;存表MOVC A,@A+DPTR           ;取表代码JZ F_M                  ;是否取到结束码MOV P3,A               ;输出
JNB K7,STOP1           ;若按K7键,停止转动JNB K5,ZM_2            ;若按K6键,反转动LCALL CONVINC R0                  ;取下一码DJNZ R1,F_M1           ;循环MOV R1,#255DJNZ R3,F_M1           ;循环MOV P3,#0F0H            ;计数满停止工作LJMP LOOPRET
;***********************************************
;定时器中断服务程序,对秒,分钟和小时的计数
INT_T0: MOV     TH0,#3CH  ;重加载初始值MOV        TL0,#0B0H       INC     TCNT      ;加1MOV        A,TCNT     CJNE A,#20,RETUNE    ;是否到了1s INC     SECMOV      TCNT,#0    ;计数值清零MOV        A,SEC      CJNE A,#60,RETUNE      ;是否到了1minINC      MINMOV      SEC,#0MOV       A,MINCJNE   A,#60,RETUNE      ;是否到了1hINC        HOURMOV     MIN,#0MOV       A,HOURCJNE  A,#24,RETUNE      ;是否到了24hMOV       HOUR,#0MOV      MIN,#0MOV       SEC,#0MOV       TCNT,#0
RETUNE: RETI
;实现显示功能的子程序
CONV:MOV  DPTR ,#TABLE
MOV     A,SEC   ;显示秒MOV     B,#10DIV        ABCLR       P2.6MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.6MOV     A,BCLR      P2.7MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.7CLR     P2.5MOV     P1,#40H     ;显示分隔符LCALL DELAYSETB   P2.5MOV     A,MIN   ;显示分钟MOV        B,#10DIV        ABCLR       P2.3MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.3MOV     A,BCLR      P2.4MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.4CLR     P2.2MOV     P1,#40H     ;显示分隔符LCALL DELAYSETB   P2.2MOV     A,HOUR      ;显示小时MOV        B,#10DIV        ABCLR       P2.0MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.0MOV     A,BCLR      P2.1MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.1RETTABLE:   DB  3FH,06H,5BH,4FH,66HDB   6DH,7DH,07H,7FH,6FH;***********************************************
;实现调整时间子程序;设置目前时间
SET_TIME:CLR TR0                      ;定时器暂时停止工作MOV SEC,#0                    ;秒钟清零 L00:     ACALL  CONV               ;扫描显示JNB  K1,L00L0:    ACALL  CONV               ;扫描显示JMP L1L3:         JB K2,L2                      ;未按下K2,则继续扫描JNB K2,$                      ;按下,则等待放开; K2小时调整INC     HOUR        ;小时值加1MOV       A,HOURCJNE  A,#24,L11   ;判断是否加到24小时MOV      HOUR,#0L11:    ACALL CONV               ;转换显示数据JMP L0                      ;继续程序执行
L1:        JB K1,L3                   ;未按下K1,则继续扫描JNB K1,$                      ;按下,则等待放开; K1分钟调整INC        MIN     ; 分钟值加1MOV      A,MINCJNE   A,#60,L21   ;判断是否加到60minMOV     MIN,#0L21:    ACALL CONV               ;转换显示数据JMP L0                      ;继续程序执行
L2:       JB K3,L0                    ;未按下K3,则继续扫描JNB K3,$                      ;按下,则等待放开SETB TR0                        ;启动定时器RET
;***********************************************
;设置闹铃时间
SET_ATIME:N00:   ACALL CONVA                ; 加载闹铃时间数据
JNB  K2,N00                      ;按下,则等待放开; K2小时调整N0:        ACALL CONVA                ; 加载闹铃时间数据 JB   K2,N1 JNB K2,$ INC      HH  ;小时值加1MOV       A,HHCJNE    A,#24,N11   ;判断是否加到24小时MOV      HH,#0N11:    ACALL CONVA               ;加载闹铃时间数据JMP N0                      ;跳转到N0执行
N1:        JB   K1,N2                     ; 未按下K1,则继续扫描JNB  K1,$                      ;按下,则等待放开; K1分钟调整INC      MM  ; 分钟值加1MOV      A,MMCJNE    A,#60,N21   ;判断是否加到60minMOV     MM,#0N21:    ACALL CONVA               ;加载闹铃时间数据JMP N0                      ;跳转到N0执行
N2:       JB K3,N0                    ;未按下K3,则继续扫描JNB K3,$                      ;按下,则等待放开ACALL CONV                  ;加载现在时间数据RET
;***********************************************
; 加载闹铃时间数据
CONVA:MOV      DPTR,#TABLE
MOV     A,SS    ;显示秒MOV     B,#10DIV        ABCLR       P2.6MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.6MOV     A,BCLR      P2.7MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.7CLR     P2.5MOV     P1,#40H     ;显示分隔符LCALL DELAYSETB   P2.5MOV     A,MM    ;显示分钟MOV        B,#10DIV        ABCLR       P2.3MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.3MOV     A,BCLR      P2.4MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.4CLR     P2.2MOV     P1,#40H     ;显示分隔符LCALL DELAYSETB   P2.2MOV     A,HH        ;显示小时MOV        B,#10DIV        ABCLR       P2.0MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.0MOV     A,BCLR      P2.1MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.1RET
;***********************************************
;检查闹钟时间处理
TIME_PRO:JB ALB ,TI3RET
;检查闹铃是否到
TI3:MOV      A,HOURMOV      B,HHCJNE      A,B,BX      ;检查闹铃小时时间MOV      A,MINMOV      B,MMCJNE      A,B,BX          ;检查闹铃分钟时间MOV      A,SECMOV      B,SSCJNE      A,B,BX          ;检查闹铃分钟时间ACALL     TIME_OUT     ;时间到,进行处理BX: RET
DELAY:  MOV     R6,#10
D1:     MOV     R7,#50DJNZ  R7,$DJNZ    R6,D1RET
DELAY1 :MOV R6,#20            ;延时20msD2   :MOV R7,#248DJNZ R7,$DJNZ R6,D2RET
TABLE1: ALB    EQU    20H.0        ;闹铃标志位
K5 EQU P0.0            ;设定P0.0以K5表示    正
K6 EQU P0.1            ;设定P0.1以K6表示    反
K7 EQU P0.2            ;设定P0.2以K7表示    停
K8 EQU P0.3            ;设定P0.3以K8表示    转换
K9 EQU P3.7              ;光敏信号
K10     EQU             P3.6      ;复位调节键K2  EQU     P0.5        ;小时控制位
K1  EQU     P0.4        ;分钟控制位
K3      EQU             P0.6      ;时间确认按键
K4      EQU             P0.7      ;电机正反辨认
SEC EQU     38H      ;存放秒钟变量
MIN EQU     37H      ;存放分钟变量
HOUR    EQU     36H      ;存放时钟变量
TCNT    EQU     39H      ;存放50ms计数HH        EQU                        40H      ;闹钟设置小时变量
MM       EQU                        41H      ;闹钟设置分钟变量
SS        EQU                        42H      ;闹钟设置秒钟变量
;程序开始
ORG     00HSJMP STARTORG        0BHLJMP INT_T0
START:
;初始化
MOV R1,#1             ;用于计电机转数
MOV R3,#0             ;用于计电机转数MOV       HOUR,#0                         MOV     MIN,#0MOV       SEC,#0MOV       TCNT,#0MOV      TMOD,#01H  MOV      TH0,#3CH        ;定时50毫秒MOV      TL0,#0B0HMOV        IE,#82HSETB TR0
;****************************************************
;无穷循环,判断是否有控制键按下,是哪一个键按下
LOOP:   ACALL  CONVACALL  TIME_PRO       ;检查闹铃时间
JB K8,L12           ;开关转换光控制
JNB K5, ZM_2           ;是否按K5,是则正转JNB K6, FM_2           ;是否按K6,是则反转JNB K7, STOP1          ;是否按K7,是则停止JB K10,TJ               ;是否按K10,是则调节反转
JNB K10,$LCALL  F_MTJTJ:    JB        K1,M1ACALL    SET_TIME        ;设置目前时间JMP    LOOP;设置闹铃时间
M1:JB K2,M2            ;未按下K2,则继续扫描ACALL  SET_ATIME  ;设置闹铃时间SETB ALBJMP LOOP            ;跳到LOOP处执行
M2:JB K1,M3            ;未按下K1,则继续扫描JMP LOOP            ;跳到LOOP处执行
M3:JB K3,M4            ;未按下K3,则继续扫描JMP LOOP            ;跳到LOOP处执行
M4:JMP LOOP            ;跳到LOOP处执行L12:  JNB K9,FM_3           JB K9,ZM_3;***********************************************
STOP: MOV P3,#0F0H          ;步进电机停止工作JMP LOOP;开关控制步进电机正反转程序ZM_3:LCALL DELAY1CJNE R3,#40, Z_M       ; 检测正转是否满JMP  LOOP               ;转至LOOP
FM_3:LCALL DELAY1CJNE R3,#0, F_M       ; 检测反转是否满JMP  LOOP               ;转至LOOPFM_2: LCALL DELAY1            ;按K6键消抖JNB K6,$              ;K6是否放开LCALL DELAY1            ;放开消抖CJNE R3,#0, F_M          ;是否反转满JMP  LOOP                ;转至LOOP
ZM_2: LCALL DELAY1            ;按K5键消抖JNB K5,$              ;K5是否放开LCALL DELAY1            ;放开消抖CJNE R3,#40, Z_M       ; 检测正转是否满JMP  LOOP               ;转至LOOP
;***********************************************
STOP1:LCALL DELAY1           ;按K7键消抖JNB K7,$              ;K7是否放开LCALL DELAY1            ;放开消抖JMP STOP               ;电机停止
;执行闹铃处理
TIME_OUT:
JB  K4,Z
JMP    F
Z: ACALL  ZM_3 CLR ALBLJMP LOOPF:ACALL   FM_3
CLR ALB
LJMP LOOPRET
Z_M: MOV R0,#00H            ;正转到TABLE取码指针初值
Z_M1: MOV P3,#00HMOV A,R0                MOV DPTR,#TABLE1         ;存表MOVC A,@A+DPTR           ;取表代码JZ Z_M                  ;是否取到结束码MOV P3,A               ;输出
JNB K7,STOP1           ;若按K7键,停止转动JNB K6,FM_2            ;若按K6键,反转动LCALL CONVINC R0                  ;取下一码INC R1                  ;计数   CJNE R1,#255, Z_M1       ;循环MOV R1,#00HINC R3                  ;计数 CJNE R3,#40, Z_M1       ;循环MOV P3,#0F0H            ;计数满停止工作LJMP LOOPRET
;反转子程序
F_M : MOV R0,#09H            ;反转到TABLE取码指针初值
F_M1: MOV P3,#00HMOV A,R0                MOV DPTR,#TABLE1         ;存表MOVC A,@A+DPTR           ;取表代码JZ F_M                  ;是否取到结束码MOV P3,A               ;输出
JNB K7,STOP1           ;若按K7键,停止转动JNB K5,ZM_2            ;若按K6键,反转动LCALL CONVINC R0                  ;取下一码DJNZ R1,F_M1           ;循环MOV R1,#255DJNZ R3,F_M1           ;循环MOV P3,#0F0H            ;计数满停止工作LJMP LOOPRET
;***********************************************
;定时器中断服务程序,对秒,分钟和小时的计数
INT_T0: MOV     TH0,#3CH  ;重加载初始值MOV        TL0,#0B0H       INC     TCNT      ;加1MOV        A,TCNT     CJNE A,#20,RETUNE    ;是否到了1s INC     SECMOV      TCNT,#0    ;计数值清零MOV        A,SEC      CJNE A,#60,RETUNE      ;是否到了1minINC      MINMOV      SEC,#0MOV       A,MINCJNE   A,#60,RETUNE      ;是否到了1hINC        HOURMOV     MIN,#0MOV       A,HOURCJNE  A,#24,RETUNE      ;是否到了24hMOV       HOUR,#0MOV      MIN,#0MOV       SEC,#0MOV       TCNT,#0
RETUNE: RETI
;实现显示功能的子程序
CONV:MOV  DPTR ,#TABLE
MOV     A,SEC   ;显示秒MOV     B,#10DIV        ABCLR       P2.6MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.6MOV     A,BCLR      P2.7MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.7CLR     P2.5MOV     P1,#40H     ;显示分隔符LCALL DELAYSETB   P2.5MOV     A,MIN   ;显示分钟MOV        B,#10DIV        ABCLR       P2.3MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.3MOV     A,BCLR      P2.4MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.4CLR     P2.2MOV     P1,#40H     ;显示分隔符LCALL DELAYSETB   P2.2MOV     A,HOUR      ;显示小时MOV        B,#10DIV        ABCLR       P2.0MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.0MOV     A,BCLR      P2.1MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.1RETTABLE:   DB  3FH,06H,5BH,4FH,66HDB   6DH,7DH,07H,7FH,6FH;***********************************************
;实现调整时间子程序;设置目前时间
SET_TIME:CLR TR0                      ;定时器暂时停止工作MOV SEC,#0                    ;秒钟清零 L00:     ACALL  CONV               ;扫描显示JNB  K1,L00L0:    ACALL  CONV               ;扫描显示JMP L1L3:         JB K2,L2                      ;未按下K2,则继续扫描JNB K2,$LCALL DELAY           ;按下,则等待放开; K2小时调整INC     HOUR        ;小时值加1MOV       A,HOURCJNE  A,#24,L11   ;判断是否加到24小时MOV      HOUR,#0L11:    ACALL CONV               ;转换显示数据JMP L0                      ;继续程序执行
L1:        JB K1,L3                   ;未按下K1,则继续扫描JNB K1,$LCALL DELAY                   ;按下,则等待放开; K1分钟调整INC        MIN     ; 分钟值加1MOV      A,MINCJNE   A,#60,L21   ;判断是否加到60minMOV     MIN,#0L21:    ACALL CONV               ;转换显示数据JMP L0                      ;继续程序执行
L2:       JB K3,L0                    ;未按下K3,则继续扫描JNB K3,$                      ;按下,则等待放开SETB TR0                        ;启动定时器RET
;***********************************************
;设置闹铃时间
SET_ATIME:N00:   ACALL CONVA                ; 加载闹铃时间数据
JNB  K2,N00                      ;按下,则等待放开; K2小时调整N0:        ACALL CONVA                ; 加载闹铃时间数据 JB   K2,N1 JNB K2,$LCALL DELAY  INC      HH  ;小时值加1MOV       A,HHCJNE    A,#24,N11   ;判断是否加到24小时MOV      HH,#0N11:    ACALL CONVA               ;加载闹铃时间数据JMP N0                      ;跳转到N0执行
N1:        JB   K1,N2                     ; 未按下K1,则继续扫描JNB K1,$LCALL DELAY                     ;按下,则等待放开; K1分钟调整INC     MM  ; 分钟值加1MOV      A,MMCJNE    A,#60,N21   ;判断是否加到60minMOV     MM,#0N21:    ACALL CONVA               ;加载闹铃时间数据JMP N0                      ;跳转到N0执行
N2:       JB K3,N0                    ;未按下K3,则继续扫描JNB K3,$                      ;按下,则等待放开ACALL CONV                  ;加载现在时间数据RET
;***********************************************
; 加载闹铃时间数据
CONVA:MOV      DPTR,#TABLE
MOV     A,SS    ;显示秒MOV     B,#10DIV        ABCLR       P2.6MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.6MOV     A,BCLR      P2.7MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.7CLR     P2.5MOV     P1,#40H     ;显示分隔符LCALL DELAYSETB   P2.5MOV     A,MM    ;显示分钟MOV        B,#10DIV        ABCLR       P2.3MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.3MOV     A,BCLR      P2.4MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.4CLR     P2.2MOV     P1,#40H     ;显示分隔符LCALL DELAYSETB   P2.2MOV     A,HH        ;显示小时MOV        B,#10DIV        ABCLR       P2.0MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.0MOV     A,BCLR      P2.1MOVC    A,@A+DPTRMOV      P1,ALCALL   DELAYSETB   P2.1RET
;***********************************************
;检查闹钟时间处理
TIME_PRO:JB ALB ,TI3RET
;检查闹铃是否到
TI3:MOV      A,HOURMOV      B,HHCJNE      A,B,BX      ;检查闹铃小时时间MOV      A,MINMOV      B,MMCJNE      A,B,BX          ;检查闹铃分钟时间MOV      A,SECMOV      B,SSCJNE      A,B,BX          ;检查闹铃分钟时间ACALL     TIME_OUT     ;时间到,进行处理BX: RET
DELAY:  MOV     R6,#10
D1:     MOV     R7,#50DJNZ  R7,$DJNZ    R6,D1RET
DELAY1 :MOV R6,#20            ;延时20msD2   :MOV R7,#248DJNZ R7,$DJNZ R6,D2RET
TABLE1:
DB 09H,01H,03H,02H,06H,04H,0CH,08H    ;正转表
DB 00                  ;正转结束
DB 08H,0CH,04H,06H,02H,03H,01H,09H    ;反转表
DB 00                  ;反转结束
;反转子程序
F_MTJ :MOV R1,#1             ;用于计电机转数
MOV R3,#0             ;用于计电机转数
F_MTJ1 :
MOV R0,#09H           ;反转到TABLE取码指针初值
F_M1TJ:MOV P3,#00HMOV A,R0                MOV DPTR,#TABLE1         ;存表MOVC A,@A+DPTR           ;取表代码JZ F_MTJ1                  ;是否取到结束码MOV P3,A               ;输出LCALL CONVINC R0                  ;取下一码
INC R1                  ;计数   CJNE R1,#255, F_M1TJ       ;循环MOV R1,#00HINC R3                  ;计数 CJNE R3,#2, F_M1TJ       ;循环MOV P3,#0F0H            ;计数满停止工作LJMP LOOPRETEND
DB 09H,01H,03H,02H,06H,04H,0CH,08H    ;正转表
DB 00                  ;正转结束
DB 08H,0CH,04H,06H,02H,03H,01H,09H    ;反转表
DB 00                  ;反转结束
;反转子程序
F_MTJ :MOV R1,#1             ;用于计电机转数
MOV R3,#0             ;用于计电机转数
F_MTJ1 :
MOV R0,#09H           ;反转到TABLE取码指针初值
F_M1TJ:MOV P3,#00HMOV A,R0                MOV DPTR,#TABLE1         ;存表MOVC A,@A+DPTR           ;取表代码JZ F_MTJ1                  ;是否取到结束码MOV P3,A               ;输出LCALL CONVINC R0                  ;取下一码
INC R1                  ;计数   CJNE R1,#255, F_M1TJ       ;循环MOV R1,#00HINC R3                  ;计数 CJNE R3,#2, F_M1TJ       ;循环MOV P3,#0F0H            ;计数满停止工作LJMP LOOPRETEND

极客DIY开源方案分享——智能家居你也可以做,何不DIY个自动窗帘升降控制系统?(纪念我的职业生涯处女作、曾获校赛一等奖作品、上古汇编语言编程)相关推荐

  1. 极客技术专题【003期】:java mvc 增删改查 自动生成工具来袭

    日期:2013-4-17  来源:GBin1.com 技术专题介绍 分享专题:java mvc 增删改查 自动生成工具来袭 分享人:激情燃烧的UI 授课时间:2013/04/19  21:00-22: ...

  2. 密码极客波卡生态系列分享会第一期:如何基于波卡开发区块链项目

    2020年10月20日,密码极客发起了第一期[波卡生态系列分享会].我们非常荣幸邀请到了Parity亚洲区技术总监贾瑶琪博士做客密码极客大咖直播间,为大家讲解<如何基于波卡开发区块链项目> ...

  3. 基于Domoticz智能家居系统(十七)DIY一款基于MySensors的ESP8266+NRF24L01的MQTT(WIFI)和RF无线网关(三)一个简单MySensors客户端的验证实验

    DIY一款基于MySensors的ESP8266+NRF24L01的MQTT(WIFI)和RF无线网关(三)一个简单MySensors客户端的验证实验 一个简单MySensors客户端的验证实验 一. ...

  4. 区块链进化论:极客与开源 - 区块链大航海时代

    1976年当做区块链史前时代的元年,正式开启了整个密码学,包括密码学货币的时代. 1982年,Lamport提出拜占廷将军问题,标志着分布式计算的可靠性理论和实践进入到了实质性阶段. 1985年,Ko ...

  5. 无线WiFi通信模组方案,智能家居无线物联网应用,ESP32芯片模组技术

    近年来,技术进步大幅增加了智能家居的可用性.硬件方面,芯片算力的升级.通讯技术的更新以及传感器功能的增强为智能家居发展提供技术基础:软件方面,边缘计算.人工智能催生出新型IoT系统,以实现万物互联. ...

  6. 无线WiFi芯片模块传输方案,智能家居应用,物联网智能化发展

    据Statista统计,全球IoT产品设备将增长17%,从2015年的154亿部增至2025年的754亿部.到2025年,72%的物联网连接将使用WiFi和Zigbee的传输技术. 而在网络通信领域, ...

  7. 微波雷达人体感应器,即时存在感知方案,智能家居人体感应交互

    人体微波感应器在智能家居的人体感应应用中具有明显的优势. 一是人体静止时仍然敏感:二是环境灵活性高,感应效果不受温度.亮度.湿度.光波动等周围环境的影响. 雷达人体微波感应器具有更广泛的角度,可以实现 ...

  8. MindCon极客周 | 第三届全新席卷而来,SIG英雄帖,做硬核玩家,夺万元大奖!

    MindCon极客周是华为昇思MindSpore每半年举办一次的开发者狂欢盛会,修复社区Bugfix,贡献开源社区,更有各领域大咖分享前沿技术,旨在引领兴趣者们走入AI探索的世界. 在大家的浓厚挑战氛 ...

  9. 一位极客美女打造了一款能为她做“口活”的装置

    之前这名美女发布了不少新奇的装置,比如自动早餐机.自动刷牙机.扇脸闹钟以及自动切菜机. 这名美女在发明这款设备被称为"Wake-Up Machine"(扇脸闹钟)的时候,就曾在 Y ...

  10. 航芯方案分享 | 智能网联汽车终端T-BOX应用方案

    随着5G时代的到来,汽车智能化.网联化程度的不断提高,车载终端T-BOX作为车辆与云端的信息交互点,扮演着重要的角色.T-BOX的升级换代也为人们的出行实现了很多便利,同时也带来了极大的信息安全挑战, ...

最新文章

  1. R语言绘制核密度图实战(Kernel Density Plot)
  2. 云端飘 String s=new String(abc)创建了几个对象?
  3. 【组合数学】递推方程 ( 递推方程示例 2 汉诺塔 | 递推方程示例 3 插入排序 )
  4. 中小企业虚拟化解决方案-VMware vSphere 6.5-日常管理入口v0.0.1
  5. Python语法糖——遍历列表时删除元素
  6. 初学者Git和GitHub简介(教程)
  7. MySQL数据库常用的操作命令(二)
  8. spark sql 性能优化
  9. gstreamer向appsrc发送帧画面的代码
  10. js 手机号码正则
  11. SVN如何批量忽略文件和文件夹
  12. 欧空局:SNAP and the Sentinel Toolboxes下载网址
  13. 美团Android开发工程师岗位职能要求,薪资翻倍
  14. WebUploader 上传 php 怎么回去返回的图片路径
  15. 《黑白团团队》第七次作业:团队项目设计完善编码
  16. Monash call:什么是生物识别安全 - 定义,系统以及设备
  17. 记录--WebSocket 原理
  18. java 吸血鬼数字_用java求吸血鬼数字 | 学步园
  19. 电商风控赛事亚军方案分享!
  20. R语言医学实例分析:代码解析

热门文章

  1. K8S-四层负载均衡-Service解读
  2. python 进化树_Biopython之系统发育树(进化树)的绘制
  3. linux系统重装win10系统不用u盘,win10不用u盘怎么重装系统
  4. 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
  5. 单片机C语言LED点阵编程,单片机LED点阵的介绍
  6. 【Excel 操作】二维表转一维表的两种方法
  7. indexOf用法小结
  8. 【SLAM】——编译项目orb-slam2_with_semantic_labelling
  9. 使用uniapp微信公众号和小程序踩坑全过程
  10. python的计算_python计算smoothed PSSM(二)