首页 > 其他分享 >基于51单片机的多功能控制终端设计

基于51单片机的多功能控制终端设计

时间:2024-12-25 16:28:55浏览次数:4  
标签:u8 ++ 51 多功能 单片机 flag LCD1602 str time

1.项目背景

  基于51单片机的多功能控制终端设计旨在实现一个集多种控制功能于一体的终端系统。该系统通过51单片机作为控制核心,结合外围电路和程序控制,实现对各种设备的有效控制。本设计以STC89C52RC作为主控MCU,外围接口设备有LCD1602显示屏幕、直流电机、温度传感器DS18B20、RTC电子钟DS1302、无缘蜂鸣器以及按键和LED灯。STC89C52 封装(直插封装)的 51 单片机芯片实物图如下所示:
在这里插入图片描述
  上图可看到芯片表面印有 STC89C52RC 40I-PDIO40 1947H0XN52.X90C 丝印,下面我们了解下芯片表面丝印的含义:
  STC–表示芯片为STC公司生产的产品,其他公司的也有AT、SST等。
  8–表示该芯片为8051内核芯片。
  9–表示内部含有Flash EEPROM存储器,还有如80C51中0表内部含有
  MaskROM(掩模 ROM)存储器;如87C51中7表示内部含有EPROM(紫外线可擦除ROM)存储器。
C–表示该器件为CMOS产品。还有如89LV52和89LE58中的LV和LE都表示该芯片为低电压产品(通常为3.3V电压供电);而89S52中S表示该芯片含有可串行下载功能的Flash存储器,即具有ISP可在线编程功能。
  5–固定不变。
  2–表示该芯片内部程序存储(FLASH)空间大小,1为4KB,2为8KB,3为12KB,即该数乘以 4KB 就是芯片内部的程序存储空间大小。程序空间大小决定了一个芯片所能装入执行代码的多少。一般来说,程序存储空间越大,芯片价格也越高,所以我们再选择芯片的时候要根据自己需求选择合适芯片。
  RC–STC单片机内部 RAM(随机读写存储器)为512B(字节)。还有如 RD+表示内部RAM 为 1280B。还有芯片会省略此部分。
  注意:该512B这在物理和逻辑上都分为两个地址空间:内部RAM(256字节)和内部扩展RAM(256字节),此外,STC89C52RC还可以访问在片外扩展的64KB外部数据存储器。内部512字节的RAM分为三个部分:低128字节(00H-7FH)、高128字节(80H-FFH)以及内部扩展的256字节RAM空间(00H-FFH)。低128字节的空间既可以直接寻址也可以间接寻址,而高128字节的空间和特殊功能寄存器区SFR的地址空间(80H-FFH)貌似共用相同的地址范围,但物理上是独立的,使用时通过不同的寻址方式加以区分。

2.设计要求

  本设计分为软件和硬件两部分组成。

  • 软件部分

     1.驱动DS18B20温度传感器,采集温度数据;
     2.驱动DS1302电子钟,获取实时时间;
     3.驱动红外解码器,解析红外数据;
     4.驱动直流电机
     5.驱动LCD屏幕
     6.按键、蜂鸣器、LED驱动
    
  • 软件部分

     1.设计UI界面1:显示当前温度数据
     2.设计UI界面2:显示实时时间+日期+星期
     3.设计UI界面3:显示个人信息(姓名+学号)
     4.支持红外遥控和按键切换显示界面
     5.设计直流电机风扇档位(低、中、高),可通过按键和红外遥控实现档位切换以及风扇开关
     6.根据实时温度,自动切换风扇档位(温度范围自行设定)
     7.支持红外遥控或者按键设置温度范围,当温度超过设定的最大值,则蜂鸣器长响;
     8.支持串口校准时间
     9.支持串口控制LED和蜂鸣器开关
     10.整体功能调试,UI界面功能优化
    
  • 整体设计框图

在这里插入图片描述

  • 系统概述
      以STC89C52RC作为主控MCU,驱动LCD1602并口屏幕,设计4个UI界面,分别用于显示个人信息、实时时间、实时温度以及当前电机运行状态。驱动DS1302,设置基准时间;驱动串口,制定串口协议,实现串口时间校准;驱动DS18B20数字温度传感器、采集实时环境温度并在LCD上实时显示;驱动红外解码模块,解析NEC协议,通过红外遥控器实现UI界面切换和温度阈值设定;驱动ULN2003电机驱动模块,可通过遥控器调节电机风扇档位,或根据设定的温度阈值自动实现风扇档位调节;驱动按键和LED,通过按键实现界面切换,LED作为程序运行状态指示灯。
  • 运行效果

  界面1:个人信息显示
在这里插入图片描述
  界面2:实时时间显示
在这里插入图片描述
  界面3:实时温度显示
在这里插入图片描述
  界面4:电机工作状态
在这里插入图片描述

3.软件设计

3.1 直流电机驱动

  直流电机是一种能将直流电能转换成机械能(直流电动机)或将机械能转换成直流电能(直流发电机)的旋转电机。
  直流电机的结构应由定子和转子两大部分组成。直流电机运行时静止不动的部分称为定子,定子的主要作用是产生磁场,由机座、主磁极、 换向极、 端盖、轴承和电刷装置等组成。运行时转动的部分称为转子,其主要作用是产生电磁转矩和感应电动势,是直流电机进行能量转换的枢纽,所以通常又称为电枢,由转轴、电枢铁心、电枢绕组、换向器和风扇等组成。
直流电机没有正负之分,在两端加上直流电就能工作。需要知道直流电机的额定电压和额定功率,不能使之长时间超负荷运作。在交换接线后,可以形成正反转。
  直流电机具有良好的启动和调速性能,常应用于对启动和调速有较高要求的场合,如大型可逆式轧钢机、矿井卷扬机、宾馆高速电梯、龙门刨床、电力机车、内燃机车、城市电车、地铁列车、电动自行车、造纸和印刷机械、船舶机械、大型精密机床和大型起重机等生产机械中。在现代工业生产和生活中发挥着重要作用。随着技术的不断进步,直流电机在高效节能、智能化等方面取得了显著发展。
  本次开发板配置的直流电机为5V直流电机,轴长为8mm,轴径为2mm,工作电压1~ 6V,工作电流0.35~0.4A ,在3V工作电压转速可达17000-18000 转每分钟,外观实物图如下:
在这里插入图片描述

3.1.1 ULN2003电路

  ULN2003是一种高耐压、大电流的复合晶体管阵列,由七个硅NPN复合晶体管(达林顿管)组成。每个达林顿管集电极可输出高达500mA的电流,同时能承受高达50V的电压。兼容TTL/CMOS逻辑信号,在5V的工作电压下,ULN2003能直接与TTL和CMOS电路相连,无需额外的逻辑缓冲器。电路内部设计有续流二极管,可用于驱动继电器、步进电机等电感性负载,有效抑制电感负载操作时产生的电压尖峰。其内部包含七个独立的达林顿管驱动通道,可将多个通道并联以实现更高的输出电流能力。
   ULN2003内部框图如下:
在这里插入图片描述  硬件电路如下:
在这里插入图片描述
  ULN2003的输入口与单片机的P1.0P1.3连接,对应输出OUT1OUT4, J47排针用于外部连接电机接口,可以支持直流电机、五线四相步进电机28BYJ-48连接。本次是直流电机接线方式为一根线连接在VCC上,另一根连接在OUT1上,可通过单片机P1.0口输出高电平来控制电机旋转,输出低电源控制电机停止。注意:单片机 P1.0输出低电平时,ULN2003的OUT1并不会输出高电平导致停止,而是因为集电极开路,导致电机无电流流入致使停止。

3.1.2 程序设计

  设置工作周期约为1ms,通过调节高低电平时间,从而实现直接电机速度调节。

sbit MOTOR=P1^0;//电机驱动接口
void Motor_Ctl(u16 time)
{
  if(time==1000)
  {
    MOTOR=1;
    return ;
  }
  if(time==0)
  {
    MOTOR=0;
    return ;
  }
  MOTOR=1;
  Delay_Us(time);
  MOTOR=0;
  Delay_Us(1000-time);
}

3.2 DS18B20温度传感器驱动

  DS18B20是Dallas半导体公司生产的数字温度传感器,是世界上第一片支持"一线总线"接口的温度传感器。测量温度范围为-55℃ ~ +125℃,精度为±0.5℃。分辨率为9 ~ 12位。支持3V ~ 5.5V输入电压。抗干扰能力强。
  每一个DSl820包括一个唯一的64位长的序号,该序号值存放在 DSl820 内部的 ROM(只读存贮器)中。开始8位是产品类型编码(DSl820 编码均为 10H) ,接着的 48位是每个器件唯一的序号,最后 8 位是前面 56 位的CRC(循环冗余校验)码。
在这里插入图片描述

3.2.1 DS18B20特点
  • 全数字温度转换及输出。
  • 先进的单总线数据通信。
  • 最高12位分辨率,精度可达土 0.5 摄氏度。
  • 12位分辨率时的最大工作周期为750毫秒。
  • 可选择寄生工作方式。
  • 检测温度范围为–55° C ~+125° C (–67° F ~+257° F)
  • 内置 EEPROM,限温报警功能。
  • 64 位光刻 ROM,内置产品序列号,方便多机挂接。
  • 多样封装形式,适应不同硬件系统。
3.2.2 操作时序
  • 复位脉冲和存在信号
    在这里插入图片描述
      每一次通信之前必须进行复位,复位的时间、等待时间、回应时间应严格按时序编程。
      复位脉冲:由控制器(单片机)给DS18B20单总线至少480uS的低电平信号。当18B20接到此复位信号后则会在15~60uS后回发一个芯片的存在脉冲。
      存在脉冲:在复位电平结束之后,控制器应该将数据单总线拉高,以便于在15~ 60uS后接收存在脉冲,存在脉冲为一个60~240uS的低电平信号。至此,通信双方已经达成了基本的协议,接下来控制器与18B20即可实现数据通信。
      代码实现如下:
/*发送复位信号,检测存在脉冲*/
u8 DS18B20_GetAck(void)
{
  u8 cnt=0;
  DS18B20_PORT=0;
  delay_10us(75);	//拉低750us
  DS18B20_PORT=1;	
delay_10us(2);	//20US
  while(DS18B20_PORT)
  {
    cnt++;
    if(cnt>=200)return 1;
  }
  //等待拉高
  cnt=0;
  while(DS18B20_PORT==0)
  {
    cnt++;
    delay_10us(1);
    if(cnt>=20)return 2;
  }
  return 0;
}
  • 写数据时序
    在这里插入图片描述
      主机要生成一个写时间隙(至少1us),必须把数据线拉到低电平然后释放,在写时间隙开始后的15us内允许数据线拉到高电平。主机要生成一个写0时间隙,必须把数据线拉到低电平并保持60 us。
      代码实现如下:
/*发送一字节数据*/
void DS18B20_WriteByte(u8 dat)
{
  u8 i=0;
  for(i=0;i<8;i++)
  {
    DS18B20_PORT=0;
    Delay1us();
    if(dat&0x01)DS18B20_PORT=1;
    else DS18B20_PORT=0;
    delay_10us(6);
    dat>>=1;//发送下一位数据
    DS18B20_PORT=1;
    Delay1us();
  }
}
  • 读数据时序
    在这里插入图片描述
      当从DS1820读取数据时,主机生成读时间隙。当主机把数据线从高电平拉到低电平时,写时间隙开始。数据线必须保持至少1 u s;从DS1820输出的数据在读时间隙的下降沿出现后15us内有效。因此,主机在读时间隙开始后必须停止把I/0脚驱动为低电平15us,以读取I/0脚状,在读时间隙的结尾,I/0引脚将被外部上拉电阻拉到高电平。所有读时间隙必须最少60u s,包括两个读周期间至少1us的恢复时间。
      代码实现如下:
u8 DS18B20_ReadByte(void)
{
  u8 dat=0;
  u8 i=0;
  for(i=0;i<8;i++)
  {
    DS18B20_PORT=0;
    Delay1us();
    DS18B20_PORT=1;
    Delay1us();
    Delay1us();
    dat>>=1;
    if(DS18B20_PORT)dat|=0x80;
    delay_10us(5);
  }
  return dat;
}
3.2.3 读取温度步骤

在这里插入图片描述
  发送复位信号–>检测回应信号—>发送0xCC–>发送0x44->发送复位信号—>检测回应信号—>写 0xcc—>写0xbe —>循环8次读取温度低字节—>循环8次读取温度高字节---->显示温度数据。
  数据的读或写是从低位开始的。

3.3 红外解码驱动

  在光谱中波长自760nm至400um的电磁波称为红外线,它是一种不可见光。目前几乎所有的视频和音频设备都可以通过红外遥控的方式进行遥控,比如电视机、空调、影碟机等,都可以见到红外遥控的影子。这种技术应用广泛,相应的应用器件都十分廉价,因此红外遥控是我们日常设备控制的理想方式。
  红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中。由于红外线遥控不具有像无线电遥控那样穿过障碍物去控制被控对象的能力,所以,在设计红外线遥控器时,不必要像无线电遥控器那样,每套(发射器和接收器)要有不同的遥控频率或编码(否则,就会隔墙控制或干扰邻居的家用电器),所以同类产品的红外线遥控器,可以有相同的遥控频率或编码,而不会出现遥控信号“串门”的情况。这对于大批量生产以及在家用电器上普及红外线遥控提供了极大的方便。由于红外线为不可见光,因此对环境影响很小,再由红外
  光波动波长远小于无线电波的波长,所以红外线遥控不会影响其他家用电器,也不会影响临近的无线电设备。红外遥控通信系统一般由红外发射装置和红外接收设备两大部分组成。
在这里插入图片描述
在这里插入图片描述

3.3.1 NEC协议介绍

  本案例使用红外遥控协议为NEC协议格式,下面将对NEC协议格式进行介绍。
  NEC协议采用PPM(Pulse Position Modulation,脉冲位置调制)的形式进行编码,数据的每一位(Bit)脉冲长度为560us,由38KHz的载波脉冲 (carrier burst) 进行调制,推荐的载波占空比为 1/3至 1/4。有载波脉冲的地方,其宽度都为 560us,而载波脉冲的间隔时间是不同的。发送时序图如下:
在这里插入图片描述
  协议规定低位首先发送。一串信息首先发送9ms的AGC(自动增益控制)的高脉冲,接着发送4.5ms的起始低电平,接下来是发送四个字节的地址码和命令码,这四个字节分别为:地址码;地址码反码;命令码;命令码反码。
  如果你一直按那个按键,一串信息也只能发送一次,一直按着,发送的则是以110ms为周期的重复码。
  注意:上图是发送时序格式,接收到的信号是跟发送信号正好反向的。
  接收协议格式如下:
在这里插入图片描述

  • 引导码:9ms低电平+4.5ms高电平
    在这里插入图片描述
      32位数据:8位用户码+8位用户反码+8位数据码+8位数据反码;(按低位先发);

  • 逻辑0:560us低+565us高
    在这里插入图片描述

  • 逻辑1:560us低+1690us高
    在这里插入图片描述

3.3.2 解码流程图

在这里插入图片描述

3.3.3 外部中断

  STC89C5X 系列单片机提供了4个外部中断:外部中断0(INTO)、外部中断1(INT1)、外部中断2(INT2)、外部中断3(INT3)。(注意:51系列单片机一定有基本的2个外部中断,但不全有4个中断,需要查看芯片手册,通常我们都是使用基本的2个外部中断:INT0 和 INT1)。
  INT0对应的是P3.2口的附加功能,可由 IT0(TCON.0)选择其为低电平有效还是下降沿有效。当CPU检测到P3.2引脚上出现有效的中断信号时,中断标志 IE0(TCON.1)置 1,向CPU申请中断。
  INT1对应的是P3.3口的附加功能,可由IT1(TCON.2)选择其为低电平有效还是下降沿有效。当CPU检测到P3.3引脚上出现有效的中断信号时,中断标志IE1(TCON.3)置1,向CPU申请中断。

  • 中断允许控制寄存
    在这里插入图片描述
位号说明
EX0(IE.0)外部中断 0 允许位;
ET0(IE.1)定时/计数器 T0 中断允许位;
EX1(IE.2)外部中断 0 允许位;
ET1(IE.3)定时/计数器 T1 中断允许位;
ES(IE.4)串行口中断允许位;
EA (IE.7)CPU 中断允许(总允许)位。
  • 中断请求标志TCON
    在这里插入图片描述
    在这里插入图片描述
  • 配置步骤:

  ①设置触发外部中断触发方式(低电平触发或者下降沿触发IT0/IT1);
  ②使能外部中断(EX0/EXT1=1);
  ③CPU开中断(EA=1);

/*
红外解码初始化
硬件接口IR --P3^2 外部中断0
*/
sbit IR_DECODE=P3^2;
void Infrared_Decode_Init(void)
{
  IT0=1;//外部中断0,下降沿触发
  EX0=1;//使能外部中断
  EA=1;//总中断
  IR_DECODE=1;//上拉
}
3.3.4 红外NEC协议解析
//10us延时函数
void delay_10us(u16 ten_us)
{
	while(ten_us--);	
}
u8 infrared_dat[4]={0};
u8 infrared_flag=0;
//外部中断0处理函数
void decode_handler() interrupt 0
{
  u8 i=0,j;
  u16 time=0;
  //9ms低电平
  time=1000;
  while((IR_DECODE==0) && time)
  {
    delay_10us(1);
    time--;
    if(time==0)return ;
  }
  //4.5ms高电平
  time=600;
  while(IR_DECODE && time)
  {
    delay_10us(1);
    time--;
    if(time==0)return ;
  }
  for(i=0;i<4;i++)
  {
    for(j=0;j<8;j++)
    {
      //560us间隔时间
      time=70;
      while((IR_DECODE==0) && time)
      {
        delay_10us(1);
        time--;
        if(time==0)return ;
      }
      //数据0和数据1
      time=0;
      while(IR_DECODE)
      {
        delay_10us(10);
        time++;
        if(time>=20)return ;
      }
      infrared_dat[i]>>=1;
      if(time>=8)infrared_dat[i]|=0x80;//数据1;1.69ms高
    }
  }
  infrared_flag=1;
}

3.4 LCD屏幕显示驱动

  1602液晶也叫1602字符型液晶,它能显示2行字符信息,每行又能显示16个字符。它是一种专门用来显示字母、数字、符号的点阵型液晶模块。它是由若干5x7或者5x10的点阵字符位组成,每个点阵字符位都可以用显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此,所以它不能很好的显示图片。其实物图如下所示:
在这里插入图片描述

3.4.1 LCD软件设计
  • 硬件接口

在这里插入图片描述
  从上图中可知,LCD1602的8位数据口DB0DB7与单片机的P0.0P0.7 管脚连接,LCD1602 的RS、RW、E脚与单片机的P2.6、P2.5、P2.7管脚连接。RJ1是一个电位器,用来调节LCD1602 对比度即显示亮度。

  • LCD初始化
void LCD1602_Init(void)
{
	LCD1602_W_Reg(0x38);//数据总线8位,显示2行,5*7点阵/字符
	LCD1602_W_Reg(0x0c);//显示功能开,无光标,光标闪烁
	LCD1602_W_Reg(0x06);//写入新数据后光标右移,显示屏不移动
	LCD1602_W_Reg(0x01);//清屏	
}
  • 字符串显示函数实现
/*
字符串显示
形参:x--0~15
      y --0~1
*/
void LCD1602_ShowStr(u8 x,u8 y,u8 *str)
{
  while(*str)
  {
    if(x>15)
    {
      x=0;
      y++;
    }
    if(y==0)
    {
      LCD1602_W_Reg(0x80+x);
    }
    else 
    {
      LCD1602_W_Reg(0xC0+x);
    }
     LCD1602_W_Dat(*str++);
    x++;
  }
}

4.整体功能实现

  初始化各个硬件,系统上电自动显示实时时间。可通过串口软件进行时间校准。获取按键值和解码NEC红外遥控器,通过按键或红外遥控切换界面,设置温度阈值,当采集的实时温度数据超过阈值范围,则自动启动电机风扇,根据超出的温度值调节风扇档位,超过最大临界温度后蜂鸣器发出高温报警提示音。支持手动控制风扇档位。

#include <reg52.h> //包含头文件
#include "main.h"
#include "key.h" //按键头文件
#include "usart.h"
#include "ds1302.h"//电子钟头文件
#include "ds18b20.h"
#include "lcd1602.h"
#include "hs0038.h"
sbit D1=P2^0;
sbit BEEP=P2^5;//蜂鸣器引脚接口
void IntToStr(u16 dat,u8 *buf);
void TimerToStr(u8 flag,u8 *str);
void TimerStrGet(u8 *str);//时间更新
/*
蜂鸣器控制函数
形参:time --开启蜂鸣器时间
*/
void BEEP_Ctl(u16 time)
{
  if(time<=0)return ;
  while(time--)
  {
    BEEP=!BEEP;
    delay_us(10);//实现2~5KHZ工作频率
  }
}
/*
直流电机驱动函数

引脚:P1^0
形参:arr  --占空比
周期时间:1000us
*/
sbit MOTOR=P1^0;//电机驱动引脚
void Motor_Ctl(u16 arr)
{
  if(arr==0)//停止工作
  {
    MOTOR=0;
    return ;
  }
  if(arr>=1000)//满负荷运行
  {
    MOTOR=1;
    return ;
  }
  MOTOR=1;//开
  delay_us(arr);
  MOTOR=0;//关
  delay_us(1000-arr);
}
u8 buffer[15]={0};
int main()
{
  u16 time=100;
  u8 i=0;
  u8 key;
  u16 temp=0;
  u16 arr=0;
  u8 hs0038_val=0;
  u8 sec=0;
  u8 menu_flag=0;
  u8 beep_flag=0;
  u16 temp_cnt=2600;//设置温度阈值
  u8 motor_flag=0;//用于控制电机手动和自动模式
  Motor_Ctl(0);//关闭电机
  LED=0xff;//关闭所有灯
  Key_Init();//按键初始化
  Usart_Init();//初始化串口(定时器中断和串口中断一起开时,定时器定时时长不宜过短)
  LCD1602_Init();
  //初始化DS18B20
  DS18B20_CheckStat();
  //Timer0_Init();//定时器初始化
  DS1302_SetTime();//设置时间
  LCD1602_ShowStr(3,0," 12:00:00");
  LCD1602_ShowStr(2,1," 2024-12-01");
  //初始化红外线解码
  HS0038_Init();
	while(1)
	{
    if(hs0038_flag)
    {
      hs0038_flag=0;
      hs0038_val=hs0038_buffer[2];
      //打印红外遥控器值
      i=0;
      buffer[i++]='v';
      buffer[i++]='a';
      buffer[i++]='l';
      buffer[i++]='=';
      buffer[i++]=(hs0038_buffer[2]/10)+'0';
      buffer[i++]=(hs0038_buffer[2]%10)+'0';
      buffer[i++]='\n';
      buffer[i]='\0';
      USART_SendStr(buffer);
    }
    if(hs0038_val==21 && menu_flag==1)//阈值温度--
    {
        BEEP_Ctl(500);
        hs0038_val=0;
        temp_cnt-=50;
        IntToStr(temp_cnt,buffer);
        LCD1602_ShowStr(9,1,buffer);
    }
    else if(hs0038_val==9 && menu_flag==1)//温度阈值++
    {
      BEEP_Ctl(500);
      hs0038_val=0;
      temp_cnt+=50;
      IntToStr(temp_cnt,buffer);
      LCD1602_ShowStr(9,1,buffer);
    }
    key=Key_GetVal();
    if(key==1 || hs0038_val==70)//按键1切换界面
    {
       hs0038_val=0;
       LCD1602_Clear();
       menu_flag++;
       BEEP_Ctl(500);
       if(menu_flag>3)menu_flag=0;
        time=100;
      if(menu_flag==1)//温度阈值
      {
        LCD1602_ShowStr(0,1,"Temp_Th:");
        IntToStr(temp_cnt,buffer);
        LCD1602_ShowStr(9,1,buffer);
      }
      if(menu_flag==2)//显示信息
      {
        LCD1602_ShowStr(4,0,"IT_ashui");
        LCD1602_ShowStr(1,1,"www.wanban.com");
      }
    }
    else if(key==2 || hs0038_val==69)//开关电机
    {
      hs0038_val=0;
      motor_flag=!motor_flag;//手动模式
      BEEP_Ctl(500);
      if(arr!=0)arr=0;//初始档位
      else arr=620;
    }
    else if(key==3 || hs0038_val==67)//电机速度++
    {
      motor_flag=1;//手动模式
      hs0038_val=0;
      BEEP_Ctl(500);
      arr+=190;
      if(arr>=1000)arr=1000;
    }
    else if(key==4 || hs0038_val==64)//电机速度--
    {
      motor_flag=1;//手动模式
      hs0038_val=0;
      BEEP_Ctl(500);
      if(arr<=620)arr=620;
      else arr-=190;
    }
    else if(menu_flag==3)//电机模式查询
    {
      if(motor_flag==0){
        LCD1602_ShowStr(2,0," MOTOR MODE");
        LCD1602_ShowStr(5,1," Auto  ");//自动
      }
      else
      {
        LCD1602_ShowStr(2,0," MOTOR MODE");
        LCD1602_ShowStr(5,1," Manual");//手动
      }
    }
    Motor_Ctl(arr);//电机控制   
    //时间校准
    if(usart_flag)
    {
      USART_SendStr(usart_buf);
      if(usart_buf[0]=='*' && usart_cnt==16)
      {
         BEEP_Ctl(500);
         TimerStrGet(&usart_buf[3]);
      }
      else if(usart_buf[0]=='L' && usart_cnt>=7)//LED1_ON
      {
          if(usart_buf[3]=='1' && usart_buf[6]=='N')LED&=~(1<<0);
          else if(usart_buf[3]=='1' && usart_buf[6]=='F')LED|=(1<<0);
          else if(usart_buf[3]=='2' && usart_buf[6]=='N')LED&=~(1<<1);
          else if(usart_buf[3]=='2' && usart_buf[6]=='F')LED|=(1<<1);
          else if(usart_buf[3]=='3' && usart_buf[6]=='N')LED&=~(1<<2);
          else if(usart_buf[3]=='3' && usart_buf[6]=='F')LED|=(1<<2);
          else if(usart_buf[3]=='4' && usart_buf[6]=='N')LED&=~(1<<3);
          else if(usart_buf[3]=='4' && usart_buf[6]=='F')LED|=(1<<3);
      }
      else if(usart_buf[0]=='B' && usart_cnt>=7)//BEEP_ON
      {
          if(usart_buf[6]=='N')beep_flag=1;
          else if(usart_buf[6]=='F')beep_flag=0;
      }
      usart_flag=0;
      usart_cnt=0;
    }
    if(beep_flag)
    {
      BEEP_Ctl(10);
    }
    else BEEP_Ctl(0);
    if(menu_flag==0)//上电默认显示时间
    {
      //时间显示
      DS1302_GetTime();
      if(sec!=DS1302_Time[0])
      {
        sec=DS1302_Time[0];
        TimerToStr(1,buffer);
        LCD1602_ShowStr(3,1,buffer);
        TimerToStr(2,buffer);
        LCD1602_ShowStr(4,0,buffer);
        i=0;
      }
    }
    time++;
    delay_ms(1);
    if(time>=100)
    {
      time=0;
      temp=DS18B20_ReadTemp();
      temp=temp*0.0625*100;
      if(temp>=temp_cnt && motor_flag==0)//高于阈值温度,设置风扇档位
      {
        if(temp-temp_cnt>1000)arr=1000;//高于设定的温度10°,高速运行
        else if(temp-temp_cnt>500)arr=810;//高于设定的温度5°,中速运行
        else arr=620;//高于设定的温度,低速运行
      }
      else if(temp<temp_cnt && motor_flag==0)arr=0;
      if(menu_flag==1)//显示温度
      {
        IntToStr(temp,buffer);
        LCD1602_ShowStr(4,0,buffer);
      }
    }
	}
}
/*
时间转字符串
形参:
      flag --1表示转年月日、2表示转时分秒
      str  --转换完的时间字符串
*/
void TimerToStr(u8 flag,u8 *str)
{
  u8 i=0;
  if(flag==1)//日期
  {
    str[i++]='2';
    str[i++]='0';
    str[i++]=(DS1302_Time[6]/16)+'0';
    str[i++]=(DS1302_Time[6]%16)+'0';
    str[i++]='-';
    str[i++]=(DS1302_Time[4]/16)+'0';
    str[i++]=(DS1302_Time[4]%16)+'0';
    str[i++]='-';
    str[i++]=(DS1302_Time[3]/16)+'0';
    str[i++]=(DS1302_Time[3]%16)+'0';
  }
  else //时间
  {
    str[i++]=(DS1302_Time[2]/16)+'0';
    str[i++]=(DS1302_Time[2]%16)+'0';
    str[i++]=':';
    str[i++]=(DS1302_Time[1]/16)+'0';
    str[i++]=(DS1302_Time[1]%16)+'0';
    str[i++]=':';
    str[i++]=(DS1302_Time[0]/16)+'0';
    str[i++]=(DS1302_Time[0]%16)+'0';
  }
  str[i]='\0';
}
/*字符串转时间数组*/
void TimerStrGet(u8 *str)
{
  //*20241211204745
  USART_SendStr(str);
   DS1302_Time[6]=(str[0]-'0')*16+(str[1]-'0');//年
   DS1302_Time[4]=(str[2]-'0')*16+(str[3]-'0');//月
   DS1302_Time[3]=(str[4]-'0')*16+(str[5]-'0');//日
   DS1302_Time[2]=(str[6]-'0')*16+(str[7]-'0');//时
   DS1302_Time[1]=(str[8]-'0')*16+(str[9]-'0');//分
   DS1302_Time[0]=(str[10]-'0')*16+(str[11]-'0');//秒
   DS1302_SetTime();  
}

/*
整数转字符串
形参:dat --要转换的整数
      buf  --保存转换完成的字符串
*/
void IntToStr(u16 dat,u8 *buf)
{
  u8 i=0;
  u8 j=0;
  u8 temp=0;
  if(dat==0)
  {
     buf[i++]='0';
     buf[i]='\0';//字符串结束标志符
     return ;
  }
  //dat=2456
  while(dat)
  {
     buf[i++]=(dat%10+'0');//6 5 4 2
     if(i==2)
     {
        buf[i++]='.';//添加小数点
     }
     dat/=10;
  }
  buf[i]='\0';//字符串结束标志符 -->65.42
  //将字符串倒置
  for(j=0;j<i/2;j++)
  {
    temp=buf[j];
    buf[j]=buf[i-j-1];
    buf[i-j-1]=temp;
  }
  //buf[i++]='\n';//换行符
  buf[i]='\0';
}


标签:u8,++,51,多功能,单片机,flag,LCD1602,str,time
From: https://blog.csdn.net/weixin_44453694/article/details/144694094

相关文章

  • Springboot旧教材交易系统a6151(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,书籍类型,书籍信息开题报告内容一、研究背景随着高等教育的普及和校园生活的丰富多彩,学生们在学习和生活中积累了大量的旧教材。这些旧教材对于个人而言,可......
  • STM32单片机定时器定时方法计算
    定时器是STM32单片机非常常见的外设,使用定时器来设置定时时间需要配置预分频系数(Prescaler)和自动重装载值(CounterPeriod)。 假设设置一个500ms的定时器,时钟频率72MHz,把预分频系数设置为7200(即写入预分频寄存器的值为7200-1),72MHz/7200=10KHz,这样就得到计数器的计数频......
  • 【总结(三)】单片机重点知识总结记录(串口重定向+按键消抖+延时)
    一.串口重定向串口重定向代码如下注意:要添加头文件include"stdio.h"要勾选微库,即UseMicroLIB/**********重定向************///串口1intfputc(intch,FILE*f){HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,0xffff);returnch;}intfgetc(FILE*f){......
  • 【无标题】51系列单片机学习:矩阵按键
    文章目录前言一、矩阵按键的硬件连接二、工作原理三、代码编写总结前言矩阵按键是一种通过行列交叉连接的按键阵列,可以节省单片机的IO口资源,用于实现多个按键的输入检测。以下是本文的简要介绍。一、矩阵按键的硬件连接1.将矩阵按键按照图1方式进行连接。图1.矩阵按......
  • 单片机实物成品-007 汽车防盗系统(代码+硬件+论文)
    汽车尾气监测系统(温度+震动传感器+红外热释电+GPS+三个指示灯+蜂鸣器+正常模式+防盗模式+wifi传输控制+送APP源码 )把该系统划分为两个不同设计主体,一方面为硬件控制主体,通过C语言来编码实现,以STM32开发板为核心控制器,利用多传感融合技术,通过感应车辆是否发生震动行为、是否......
  • 410、基于51单片机的温控电机仿真设计(正反转,加减速,LCD1602,独立按键)
    毕设帮助、开题指导、技术解答(有偿)见文末。目录一、设计功能二、proteus仿真三、原理图四、程序源码五、资料包括一、设计功能单片机读取温度传感器数据,获得温度,根据温度值对电机进行控制:1、设置4个温度值:T1、T2、T3、T4;通过按键修改设定温度2、温度低于T1,电机全......
  • 405、基于51单片机的洗衣机仿真设计(数码管,强洗,弱洗,漂洗;丝质,棉质,化纤)
    毕设帮助、开题指导、技术解答(有偿)见文末。目录一、设计功能二、proteus仿真三、原理图四、程序源码五、资料包括一、设计功能洗衣机控制面板设计。1、用直流电机的转速表征三种不同洗衣方式,弱洗、强洗、漂洗; 2、实现最长10分钟定时; 3、用三个独立按键设置......
  • 404、基于51单片机的大棚控制仿真设计(温湿度CO2,DHT11,LCD1602)
    毕设帮助、开题指导、技术解答(有偿)见文末。目录一、设计功能二、proteus仿真三、原理图四、程序源码五、资料包括一、设计功能大棚温湿度、二氧化碳含量控制系统:1、检测温湿度(DHT11)2、检测二氧化碳浓度(电位器代替)3、设置上下限,如果参数过限,启动控制自动调控大......
  • 402、基于51单片机的洗衣机仿真设计(数码管,2模式,中断)
    毕设帮助、开题指导、技术解答(有偿)见文末。目录一、设计功能二、proteus仿真三、原理图四、程序源码五、资料包括一、设计功能二、proteus仿真三、原理图四、程序源码五、资料包括需要完整的资料可以点击下面的名片,找我要资源压缩包的百度网......
  • 409、基于51单片机的温度控制,简易空调仿真设计(单阀值,LCD,独立按键)
    毕设帮助、开题指导、技术解答(有偿)见文末。目录一、设计功能二、proteus仿真三、原理图四、程序源码五、资料包括一、设计功能简易空调,温度控制系统1、系统启停由按键设置2、系统处于启动状态时,检测到室内有人,那么温度低于阀值启动制热,高于阀值启动制冷3、LCD1602......