声明:本项目为作者第一次接触单片机,并对单片机产生了浓厚的兴趣。
本项目采用STC8A8K64D4作为开发芯片与传统51单片机相比,STC8A8K64D4在性能和功能上有显著提升。STC8A8K64D4具有更高的处理速度、更大的存储容量以及更多的外设资源,使其在复杂应用场景中的表现更加出色。此外,STC8A8K64D4还支持多种通信接口,如I2C、SPI和UART,方便与其他设备进行数据交换。这些优势使得STC8A8K64D4在开发嵌入式系统和实现高级算法时具有明显的优势。
在嵌入式项目中要有纵览全局的眼光。对于各个模块心理都要有准确的认识。代码格式也有严格规范,满足模块化要求,使代码可以复用。
重点概要:
1.在对GPIO端口进行配置时,可以采用宏定义的方法,以此节省单片机闪存(Flash Memory)不足。但随着技术的发展,单片机一般不会出现该问题。但是在未来进入公司工作时,为了节约成本,对单片机的成本有限制,造成闪存不足,可以采用此方法。
2.在嵌入式领域中,状态机也是非常重要的,能让按键拥有多种意义。例如1个按键通过状态机可以拥有(短按、长按、双击)。有时间会单独写一篇关于按键状态机的代码。
3. AD转换对我们未来的发展也有重要意义。
4. .............
目录
1 引言
1.1 课题背景
温度计是一种广泛使用的测量仪器,通常用来测量物体的表面或环境温度。在工业、医疗、环境监测等领域中,温度测量至关重要。温度异常可能导致设备故障、生产中断、质量问题甚至安全事故。因此,及时准确地监测和报警温度变化对于保障设备运行、提高生产效率和保障人员安全具有重要意义。
随着科技的发展,芯片制造技术的不断进步,基于单片机的数字温度计已经得到了广泛的应用。STC8A8K64D4是一款单片机芯片,具有高性能、低功耗、集成度高等优点,可用于设计和实现数字温度计。本课题旨在利用STC8A8K64D4芯片,设计一种实用的数字测温仪器,并进行实现、调试和优化,从而满足实际应用需求。
1.2国内外研究现状
1.2.1国外研究现状
在国外,基于微控制器的温度计的设计与实现已经得到了广泛研究和应用。许多研究关注于温度传感器的选择和接口电路的设计。常见的温度传感器包括热敏电阻、热电偶和半导体传感器等。研究者通过选择合适的传感器,并设计相应的接口电路,将模拟信号转换为数字信号,并通过显示屏或通信接口进行数据显示和传输。
1.2.2国内研究现状
在国内,尽管基于微控制器的温度计研究相对较少,但也有一些有价值的成果涌现。国内研究者在温度计设计与实现方面,主要关注于应用领域和功能扩展,为不同领域的温度监测和控制提供了有效的解决方案。
在农业领域,基于微控制器的温度计被广泛用于温室监测和农作物生长环境控制。研究者们通过使用STC8A8K64D4微控制器作为核心处理单元,结合合适的温度传感器和湿度传感器,实现了对温室内温湿度的实时监测和数据记录。通过收集温湿度数据,并结合相应的控制算法,可以实现对温室内环境的智能调控,提高农作物的产量和质量。
在工业领域,基于微控制器的温度计在生产过程中起到重要的作用。研究者们利用STC8A8K64D4微控制器的高精度和实时性能,结合适当的温度传感器,实现对工业生产中关键设备的温度监测和故障预警。通过对温度变化的实时监控,可以及时发现设备故障,并采取相应的措施,以保证生产的稳定性和安全性。
需要指出的是,国内的基于微控制器的温度计研究还相对较少,存在着一些挑战和机遇。在技术方面,如何提高温度计的精度、响应速度和稳定性仍然是亟待解决的问题。同时,如何将温度计与云平台、物联网等技术相结合,实现远程监测和数据共享,也是未来的研究方向。此外,对于不同应用场景的特殊需求,如高温环境、低温环境等,还需要进一步针对性的研究和技术改进。
综上所述,国内的基于微控制器的温度计研究在农业和工业领域已经取得了一定的成果,但仍有很大的发展空间。未来的研究可以进一步探索温度计的精确度和稳定性提升策略,以及与其他传感器和技术的结合,为实际应用提供更加完善和智能的解决方案。
2 总体设计
2.1 系统功能
基于STC8A8K64D4微控制器的温度计设计旨在实现以下主要功能:
温度测量功能:通过连接NTC温度传感器和AD转换器,能够准确测量环境温度。传感器将温度转换为电阻值,并通过AD转换器将模拟电压信号转换为数字信号,以便微控制器进行处理。
温度显示功能:将测量到的温度值以直观的方式显示出来。通过连接LED1602显示模块,可以在液晶显示屏上显示当前的温度值。显示屏可以以数字或字符形式显示温度值,并提供清晰的可视化界面。
报警功能:设置温度阈值,当温度超过预设的阈值时,触发报警。通过控制蜂鸣器或触发外部警报装置,可以提醒用户注意异常温度情况,并需要人工取消报警。
用户交互功能:通过设计合适的用户界面和交互方式,提供友好的操作体验。可以使用按键等方式与系统进行交互,切换功能、调整设置。
系统稳定性和安全性:通过设计合适的防静电措施、温度保护和过热保护功能,提高系统的稳定性和安全性。确保系统在不同环境条件下正常运行,并保护电路和传感器免受损坏。
以上功能是基于STC8A8K64D4微控制器的温度计设计的主要目标和功能。根据具体需求和应用场景,可以进行相应的定制和扩展。通过这些功能的实现,可以提供准确、可靠且用户友好的温度测量和显示解决方案。
2.2 系统环境搭建
2.2.1软件环境搭建(使用Keil 5)
下载和安装Keil 5:访问Keil官方网站,下载适用于您的操作系统的Keil 5集成开发环境(IDE)。
配置Keil 5:打开Keil 5 IDE,并根据提示进行安装和配置。配置包括选择合适的MCU型号(STC8A8K64D4)、设置编译器和调试器等。
创建新工程:在Keil 5 IDE中创建一个新的工程。选择STC8A8K64D4作为目标MCU,并指定工程文件的存储位置。
导入库文件:根据需要,导入STC8系列的库文件。这些库文件包含STC8A8K64D4的相关驱动和函数,可简化开发过程。
编写代码:在Keil 5 IDE中编写代码。根据系统功能的需求,编写初始化代码、温度测量算法、温度显示和更新代码、用户交互代码等。
编译和烧录:使用Keil 5 IDE提供的编译器,编译源代码。然后,将生成的可执行文件通过烧录器或调试器,将程序烧录到STC8A8K64D4微控制器芯片中。
调试和测试:连接电源和相关外设,使用调试工具或编写测试代码,验证温度计系统的功能和准确性。进行实际温度测量和显示测试,并校准温度测量结果。
通过以上的硬件环境搭建和软件环境搭建步骤,您可以建立基于STC8A8K64D4微控制器的温度计系统的开发环境,并进行系统的开发、调试和测试工作。
2.2.2硬件环境搭建
硬件连接:将STC8A8K64D4微控制器与其他硬件模块进行连接。连接NTC温度传感器到合适的引脚,并连接AD转换器和LED1602显示模块。根据硬件设计要求,进行正确的连线和引脚分配。
调试工具准备:准备适用于STC8A8K64D4的调试工具,如USB转串口模块或调试器。这些工具用于与微控制器进行通信、烧录程序和调试代码。
外部组件连接:根据具体需求,连接外部组件,如按键、蜂鸣器或存储器模块。确保这些组件与微控制器正确连接,并按照设计要求进行连线。
硬件调试:在完成硬件连接后,进行硬件调试。通过使用示波器、万用表和逻辑分析仪等工具,检查电路的连通性、电压水平和信号波形。确保所有硬件模块正确工作,并消除任何硬件故障或连接问题。
硬件环境搭建是基于STC8A8K64D4微控制器的温度计设计过程中不可或缺的一步。正确连接和配置硬件模块将为系统功能的实现奠定基础,并确保温度计系统能够准确测量、显示和处理温度数据。
2.3 设计的总体框图
2.4 硬件描述
2.4.1 STC8A8K64D4微控制器
STC8A8K64D4微控制器是基于8051内核的高性能单片机。它具有64KB的Flash存储器和8KB的RAM,可以满足温度计系统的存储和处理需求。该微控制器还提供了丰富的GPIO引脚,用于与其他硬件模块的连接和通信。
2.4.2 A/D 模数转换
A/D 模数转换是将外部的模拟电压转换为 数字信号后,供单片机进行处理,以便单片机能“感知”到外部“消息”。
模拟信号,在电子电路中,通常根据信号值域是否随时域连续变化的特征箱关得号区分为模拟信号和数字信号。如图 1-1 所示,模拟信号是一种数值在时域上值域连续变化的信号。从电学角度去看,这种信号的幅度和相位是连续变化的,所以很多文献上也将其称为“连续信号”。熟悉的正弦波信号、声音信号、压力信号、手机天线部分的电磁信号等都属于模拟信号,很多传感器输出的 4~20mA 电流信号、0~5V 电压信号、0~10V 电压信号,图 1-1 模拟信号数值变化曲线也都是模拟信号。
图1-1 模拟信号数值变化曲线
通常把这种物理量称为“模拟量”,表示模拟量的电信号称为“模拟电信号”,工作运行在这种信号下的电子电路称为“模拟电子电路”。
数字信号,在单片机信号处理中,大多都是数字信号,也就是我们通常所说的高低电平信号。如图 1-2所示,数字信号是一种数值在时域上离散变化的信号,例如数字脉冲信号。
图1-2 数字信号数值分布特征
2.4.3 NTC温度传感器
选择合适的NTC温度传感器,如图 1-3 所示,并将其连接到开发板上的模拟输入通道。确保正确连接传感器的引脚,通常NTC传感器具有两个引脚,一个用于接地,另一个用于连接到模拟输入引脚。
图1-3 NTC温度传感器参数图
2.4.4 LED1602液晶显示模块
LED1602液晶显示模块是一种常用的字符显示模块,由16列2行的字符组成。它采用液晶显示技术,具有低功耗、高可靠性和清晰可见的特点。在基于STC8A8K64D4的温度计设计中,LED1602显示模块被用于将温度数据以可视化的方式显示出来。
LED1602显示模块的硬件连接相对简单,一般包括以下几个主要部分:
LCD控制器:LED1602显示模块内部包含一个LCD控制器,用于控制字符的显示、光线的背光和其他相关功能。在STC8A8K64D4温度计设计中,通过与LCD控制器进行通信,可以向显示模块发送指令和数据,控制显示内容和显示状态。
字符存储区:LED1602显示模块具有16列2行的字符存储区,用于显示字符和符号。每个字符存储区可以显示一个ASCII字符,包括数字、字母、符号和自定义字符。通过与STC8A8K64D4微控制器进行通信,可以将温度数据转换为相应的字符,并将其发送到LED1602显示模块的字符存储区。
背光控制:LED1602显示模块还具有背光控制功能,可以控制显示的背光亮度。一般情况下,通过STC8A8K64D4微控制器的GPIO引脚连接到LED1602显示模块的背光控制引脚,以实现背光的开启和关闭。这样可以根据需要调整背光亮度,提供良好的可视性。
电源供应:LED1602显示模块需要电源供应,一般为5V电源。在设计中,需要将模块的电源引脚与适当的电源连接,以确保模块正常工作。
2.5 软件描述(寄存器配置)
端口配置:
/*-------------------------------------------------------------------
/* (C) Copyright 2021-2022, nbufe. All Rights Reserved
/*-------------------------------------------------------------------
/* File name : STC8Ax_Init.c
/* Description :
/* Author : nbufe
/*-------------------------------------------------------------------
/* Update note:
/* --------- ----------- ----------------------------------------
/* Date Author Note
/* --------- ----------- ----------------------------------------
/*
/*
**/
/* 包含头文件 -------------------------------------------------------*/
#include "STC8Ax_INIT.h"
/* 私有类型定义 -----------------------------------------------------*/
/* None. */
/* 私有宏定义 -------------------------------------------------------*/
/* None. */
/* 私有变量 ---------------------------------------------------------*/
/* None. */
/* 扩展变量 ---------------------------------------------------------*/
/* None. */
/* 私有函数原形 -----------------------------------------------------*/
/* None. */
/* 函数体 -----------------------------------------------------------*/
/* 第一区 初始化单片机 */
/**
* 功能:初始化单片机
* 参数:None
* 返回:None
* 说明:
*/
void System_Init()
{
GPIO_Init(GPIO_P0, Pin_All, GPIO_MODE_OUT_PP);
GPIO_Init(GPIO_P1, Pin_All, GPIO_MODE_IN_FLOATING );
GPIO_Init(GPIO_P1, Pin_2 , GPIO_MODE_OUT_PP);
GPIO_Init(GPIO_P2, Pin_All, GPIO_MODE_WEAK_PULL );
GPIO_Init(GPIO_P3, Pin_All, GPIO_MODE_WEAK_PULL );
GPIO_Init(GPIO_P4, Pin_All, GPIO_MODE_WEAK_PULL );
GPIO_Init(GPIO_P7, Pin_All, GPIO_MODE_WEAK_PULL );
Time0_Config();
ADC_Init();
LCD1602_Init(); // 初始化LCD显示屏
led_dr1 = 1; //LED灭
led_dr2 = 1; //LED灭
led_dr3 = 1; //LED灭
led_dr4 = 1; //LED灭
}
/**
* 功能:初始化外围设备
* 参数:None
* 返回:None
* 说明:
*/
void Time0_Config() //初始化外围
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x30; //设置定时初始值 //1毫秒@24.000MHz初值
TH0 = 0xF8; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
/* 第二区 初始化外围 */
/**
* 功能:初始化外围设备
* 参数:None
* 返回:None
* 说明:
*/
void Peripheral_Init() //初始化外围
{
EA = 1; //开总中断
TR0 = 1; //启动定时中断
ET0 = 1;
}
/*>>>>>>>>>> (C) COPYRIGHT NBUFE <<<<<< >>>>>> END OF FILE <<<<<<<<<<*/
定时器配置:
/*-------------------------------------------------------------------
/* (C) Copyright 2021-2022, nbufe. All Rights Reserved
/*-------------------------------------------------------------------
/* File name : STC8Ax_ISR.c
/* Description :
/* Author : nbufe
/*-------------------------------------------------------------------
/* Update note:
/* --------- ----------- ----------------------------------------
/* Date Author Note
/* --------- ----------- ----------------------------------------
/*
/*
**/
/* 包含头文件 -------------------------------------------------------*/
#include "STC8Ax_ISR.h"
/* 私有类型定义 -----------------------------------------------------*/
/* None. */
/* 私有宏定义 -------------------------------------------------------*/
/* None. */
/* 私有变量 ---------------------------------------------------------*/
/* None. */
/* 扩展变量 ---------------------------------------------------------*/
/* None. */
/* 私有函数原形 -----------------------------------------------------*/
/* None. */
/* 函数体 -----------------------------------------------------------*/
/* 第四区 系统中断处理 */
/**
* 功能:定时中断函数
* 参数:None
* 返回:None
* 说明:
*/
void Time0_ISR() interrupt 1
{
TF0 = 0;
TR0 = 0;
Key_Scan();
TH0 = (65536 - 2000) / 256; //重装初始值(65535-2000)=63535=0xf82f
TL0 = (65536 - 2000) % 256; //1毫秒 @24.000MHz初值
TR0 = 1;
}
/*>>>>>>>>>> (C) COPYRIGHT NBUFE <<<<<< >>>>>> END OF FILE <<<<<<<<<<*/
ADC 特殊功能寄存器:
/*------------------------------------------------------------------*/
/* ADC 特殊功能寄存器*/
/*------------------------------------------------------------------*/
sfr ADC_CONTR = 0xBC; //0000,0000 A/D转换控制寄存器
#define ADC_POWER 0x80 //bit7
#define ADC_START 0x40 //bit6
#define ADC_FLAG 0x20 //bit5
sfr ADC_RES = 0xBD; //0000,0000 A/D转换结果高8位
sfr ADC_RESL = 0xBE; //0000,0000 A/D转换结果低2位
3 详细设计
3.1 主函数设计
3.1.1包含头文件
包含头文件:代码开始处包含了一些自定义的头文件和外部库文件,用于引入所需的函数和定义。这些头文件包括:
"main.h":主头文件,包含了所有其他头文件的引用。
"STC8Ax_INIT.h":STC8系列单片机初始化相关的头文件。
"STC8Ax_DELAY.h":STC8系列单片机延时函数相关的头文件。
".\LCD1602\LCD1602.h":LCD1602液晶显示屏相关的头文件。
".\ADC\ADC.h":ADC模块相关的头文件。
".\LED\LED.h":LED模块相关的头文件。
3.1.2主函数(main)流程
1.执行System_Init()函数:这个函数用于进行系统初始化,例如时钟设置、IO口配置等。
2.延迟500毫秒(Delay_ms(500)):通过Delay_ms()函数实现延时功能。
3.执行Peripheral_Init()函数:这个函数用于进行外设初始化,包括定时器、中断、串口等外设的初始化。
3.在LCD1602上显示字符串 "temperature":使用LCD1602_ShowString()函数在LCD1602显示屏上显示字符串。
4.进入无限循环(while(1)):
5.执行key_service()函数:这个函数处理按键服务的应用程序,按键状态检测。
6.执行ADC_USE()函数:这个函数处理AD的应用程序,包括读取AD值、转换为实际参数等。
7.延迟500毫秒(Delay_ms(500)):通过Delay_ms()函数实现延时功能。
3.1.3主函数(main)详细代码
/*-------------------------------------------------------------------
/* (C) Copyright 2022-2023, nbufe. All Rights Reserved
/*-------------------------------------------------------------------
/* File name : main.c
/* Description :
/* Author : nbufe
/*-------------------------------------------------------------------
/* Update note:
/* --------- ----------- ----------------------------------------
/* Date Author Note
/* --------- ----------- ----------------------------------------
/*
/*
**/
/* 包含头文件 -------------------------------------------------------*/
#include "main.h"
/* 私有类型定义 -----------------------------------------------------*/
/* None. */
/* 私有宏定义 -------------------------------------------------------*/
/* None. */
/* 私有变量 ---------------------------------------------------------*/
/* None. */
/* 扩展变量 ---------------------------------------------------------*/
/* None. */
/* 私有函数原形 -----------------------------------------------------*/
/* None. */
/* 函数体 -----------------------------------------------------------*/
/*
* 功能: 主函数
* 参数: None
* 返回: None
* 说明: None
*/
void main()
{
System_Init();
Delay_ms(500);
Peripheral_Init();
LCD1602_ShowString(1,0,"temperature");
while(1)
{
key_service(); //按键服务的应用程序
ADC_USE();
Delay_ms(500);
}
}
/*>>>>>>>>>> (C) COPYRIGHT NBUFE <<<<<< >>>>>> END OF FILE <<<<<<<<<<*/
3.2 AD转换模块的设计与实现
3.2.1包含头文件及其他参数
头文件:代码开始处包含了自定义的头文件"ADC.h",用于引入所需的函数和定义。
私有类型定义:使用了extern关键字声明了两个unsigned char类型的全局变量upC和downC。
私有变量:定义了三个私有变量:
unsigned char value: 用于保存ADC转换结果的字节值。
unsigned int sum1: 用于保存ADC转换结果的16位值(高8位在ADC_RES,低8位在ADC_RESL)。
unsigned int result: 根据ADC转换结果计算得到的实际结果。
3.2.2 AD数模转换函数体流程
1.ADC_Init()函数:用于进行ADC的初始化。
清零ADC_RES和ADC_RESL寄存器。
配置P_SW2寄存器,选择ADC内部时序。
配置ADCTIM寄存器,设置ADC的内部时序。
清除P_SW2寄存器的相应位,选择系统时钟/2/16作为ADC时钟。
设置ADC_CONTR寄存器的最高位,使能ADC模块。
2.ADC_USE()函数:用于执行ADC的转换和相关操作。
设置ADC_CONTR寄存器的第6位,开始进行ADC转换。
空操作_nop_(),增加一定的延时。
检查ADC_CONTR寄存器的第5位,等待ADC转换完成。
清除ADC_CONTR寄存器的第5位,将ADC_FLAG标志位清零。
设置ADCCFG寄存器为0,选择左对齐方式(通常采用右对齐方式)。
将ADC_RES左移4位,将ADC_RESL右移4位,将两者合并为一个16位的数值sum1。
根据sum1的值进行判断,将结果存储在result变量中。
在LCD1602显示屏上显示result的值。
根据result和upC、downC的比较结果,控制LED灯的状态,并在LCD1602上显示相应的信息。
在LCD1602显示屏上显示upC和downC的值。
在LCD1602显示屏上显示温度单位"'C"。
3.2.3 AD数模转换详细代码
3.3 LED1602模块的设计与实现
3.3.1包含头文件及其他参数
头文件:如"STC8Ax_GPIO.h"、"STC8Ax_REG.h"和"STC8Ax_DELAY.h"
定义LCD1602控制引脚(RS、RW、EN)和数据总线(DB)的硬件端口连接。
3.3.2 LED1602函数体流程
实现函数 `LCD1602_ReadBusy()`,用于检查LCD的忙标志。它会等待忙标志(位7)被清除,表示LCD已准备好接受命令或数据。
实现函数 `LCD1602_Clear()`,向LCD发送清除显示的命令(0x01)。
实现函数 `LCD1602_WriteCmd()`,用于向LCD写入命令。它首先调用 `LCD1602_ReadBusy()` 来确保LCD不忙,将RS(寄存器选择)引脚设置为0(表示命令),将RW(读/写)引脚设置为0(表示写操作),将命令写入数据总线,切换EN(使能)引脚以锁存命令,然后返回。
实现函数 `LCD1602_WriteData()`,用于向LCD写入数据。它的过程与 `LCD1602_WriteCmd()` 类似,但将RS引脚设置为1(表示数据),并将数据写入数据总线。
实现函数 `LCD_run()`,用于控制显示的滚动行为。它接受一个参数 `flag`,用于指定滚动方向:0 表示不滚动,1 表示左移,2 表示右移。该函数向LCD发送相应的命令(0x06、0x18 或 0x1C)。
实现函数 `LCD1602_SetCursor()`,用于在LCD上设置光标位置。它根据给定的x和y坐标计算地址,并向LCD发送相应的命令。
实现函数 `LCD1602_DisplayChar()`,用于在LCD的指定位置(x、y)显示一个字符。它根据坐标计算地址,并向LCD发送命令和数据。
实现函数 `LCD1602_ShowString()`,用于在LCD的指定位置(x、y)显示一个字符串。它调用 `LCD1602_SetCursor()` 来设置光标位置,然后将字符串的每个字符写入LCD。
实现函数 `LCD1602_Init()`,用于初始化LCD。它等待15毫秒的延迟,向LCD发送初始化序列(0x38、0x38、0x38),设置显示模式(0x0C),设置光标移动方向(0x06),并清除显示。
实现函数 `LCD_Pow()`,用于计算一个数的幂。它接受两个参数(X和Y),并返回X的Y次方的值。
实现函数 `LCD_ShowNum()`,用于在LCD的指定位置(行、列)显示一个数字。它计算数字的位数,并使用 `LCD1602_WriteData()` 显示每个位上的数字。
3.3.3 LED1602函数体详细代码
/*-------------------------------------------------------------------
/* (C) Copyright 2021-2022, nbufe. All Rights Reserved
/*-------------------------------------------------------------------
/* File name : LCD1602.c
/* Description :
/* Author : nbufe
/*-------------------------------------------------------------------
/* Update note:
/* --------- ----------- ----------------------------------------
/* Date Author Note
/* --------- ----------- ----------------------------------------
/*
/*
**/
/* 包含头文件 -------------------------------------------------------*/
#include"lcd1602.h"
/* 私有类型定义 -----------------------------------------------------*/
/* None. */
/* 私有宏定义 -------------------------------------------------------*/
/* None. */
/* 私有变量 ---------------------------------------------------------*/
/* None. */
/* 扩展变量 ---------------------------------------------------------*/
/* None. */
/* 私有函数原形 -----------------------------------------------------*/
void LCD1602_ReadBusy();
void LCD1602_WriteCmd(uint8_t cmd);
void LCD1602_WriteData(uint8_t dat);
void LCD1602_SetCursor(uint8_t x, uint8_t y);
/* 函数体 -----------------------------------------------------------*/
/*
/*
* 功能: LCD1602 忙检测函数
* 参数: None
* 返回: None
* 说明: 判断bit7是0,允许执行;1禁止
*/
void LCD1602_ReadBusy()
{
uint8_t sta;
LCD1602_DB = 0xff;
LCD1602_RS = 0;
LCD1602_RW = 1;
do
{
LCD1602_EN = 1;
sta = LCD1602_DB;
LCD1602_EN = 0; //使能,用完就拉低,释放总线
}
while(sta & 0x80);
}
/**
* @brief: LED1602清屏程序
* @param: None
* @return: None
* @note: None
*/
void LCD1602_Clear()
{
LCD1602_WriteCmd(0x01);
}
/*
* 功能: LCD1602 写命令函数
* 参数: None
* 返回: None
* 说明: None
*/
/*void LCD1602_WriteCmd(uint8_t cmd)
{
LCD1602_ReadBusy();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
LCD1602_EN = 1;
LCD1602_EN = 0;
} */
void LCD1602_WriteCmd(uint8_t cmd)
{
LCD1602_ReadBusy();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
Delay_ms(2);
LCD1602_EN = 1;
Delay_ms(2);
LCD1602_EN = 0;
}
/*
* 功能: LCD1602 写数据函数
* 参数: None
* 返回: None
* 说明: None
*/
void LCD1602_WriteData(uint8_t dat)
{
LCD1602_ReadBusy();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_EN = 1;
Delay_ms(2);
LCD1602_DB = dat;
Delay_ms(2);
LCD1602_EN = 0;
}
/**
* @brief: LCD1602滚动显示函数
* @param: flag
* @return: None
* @note: 输入0不滚动屏幕,输入1左移,输入2右移
*/
void LCD_run(uint8 flag)
{
switch (flag)
{
case 0:
LCD1602_WriteCmd(0x06);
break;
case 1:
LCD1602_WriteCmd(0x18);
break;
case 2:
LCD1602_WriteCmd(0x1C);
break;
default:
break;
}
}
/*
* 功能: LCD1602 坐标显示函数
* 参数: None
* 返回: None
* 说明: None
*/
void LCD1602_SetCursor(uint8_t x, uint8_t y)
{
uint8_t addr;
if(y == 0)
addr = 0x00 + x;
else
addr = 0x40 + x;
LCD1602_WriteCmd(addr | 0x80);
}
/*
* 功能: LCD1602 按指定位置显示一个字符函数
* 参数: None
* 返回: None
* 说明: None
*/
void LCD1602_DisplayChar(uint8_t x, uint8_t y, uint8_t dat)
{
y &= 0x1;
x &= 0xF; //限制x不能大于15,y不能大于1
if (y) x |= 0x40; //当要显示第二行时地址码+0x40;
x |= 0x80; //算出指令码
LCD1602_WriteCmd(x); //发命令字
LCD1602_WriteData(dat); //发数据
}
/*
* 功能: LCD1602 显示字符串函数
* 参数: None
* 返回: None
* 说明: None
*/
void LCD1602_ShowString(uint8_t x, uint8_t y, uint8_t *str)
{
LCD1602_SetCursor(x, y); //当前字符的坐标
while(*str != '\0')
{
LCD1602_WriteData(*str++);
}
}
/*
* 功能: LCD1602 初始化函数
* 参数: None
* 返回: None
* 说明: None
*/
void LCD1602_Init()
{
Delay_ms(15);
LCD1602_WriteCmd(0x38);
Delay_ms(5);
LCD1602_WriteCmd(0x38);
Delay_ms(5);
LCD1602_WriteCmd(0x38); // 设置显示模式
LCD1602_WriteCmd(0x0C); // 开显示,显示光标,光标不闪烁
LCD1602_WriteCmd(0x06); // 光标右移,屏幕不移动
LCD1602_Clear(); // 清屏
}
/**
/*
* 功能: 返回值=X的Y次方
* 参数: None
* 返回: None
* 说明: None
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
/*
* 功能: LCD1602 显示数字
* 参数: None
* 返回: None
* 说明: None
*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD1602_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD1602_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}
}
/*>>>>>>>>>> (C) COPYRIGHT NBUFE <<<<<< >>>>>> END OF FILE <<<<<<<<<<*/
3.4 按键服务模块的设计与实现
在嵌入式领域中,状态机也是非常重要的,有时间会单独写一篇关于按键状态机的代码。
3.4.1包含头文件及其他参数
包含头文件 "LED.h"。
声明一个全局变量 `KeySec`,表示被触发的按键编号。
声明两个全局变量 `upC` 和 `downC`,分别表示上升计数和下降计数。
3.4.2 独立按键函数体流程
实现函数 `key_service()`,用于处理按键服务。在函数中使用 `switch` 语句根据 `KeySec` 的值进行不同的操作:
当 `KeySec` 为 1 时,表示1号键短按触发,`upC` 值加一,然后将 `KeySec` 清零,发出蜂鸣声,延时500毫秒。
当 `KeySec` 为 11 时,表示1号键长按连续步进触发,与上述操作类似。
当 `KeySec` 为 2 时,表示2号键短按触发,发出蜂鸣声,延时500毫秒。
当 `KeySec` 为 22 时,表示2号键长按触发,将红色和蓝色LED灯关闭,初始化LCD1602显示器,显示"temperature"字样,发出蜂鸣声,延时500毫秒。
当 `KeySec` 为 3 时,表示3号键短按触发,`downC` 值加一,然后将 `KeySec` 清零,发出蜂鸣声,延时500毫秒。
当 `KeySec` 为 33 时,表示3号键长按连续步进触发,与上述操作类似。
当 `KeySec` 为 4 时,表示4号键短按触发,`upC` 值减一,然后将 `KeySec` 清零,发出蜂鸣声,延时500毫秒。
当 `KeySec` 为 44 时,表示4号键长按触发,`downC` 值减一,然后将 `KeySec` 清零,发出蜂鸣声,延时500毫秒。
这段代码的主要思路是通过检测按键的触发,根据不同的按键编号执行相应的操作。通过修改 `upC` 和 `downC` 的值,可以实现计数的上升和下降。同时,通过控制LED灯和LCD显示器来提供可视化反馈。在每次处理完按键操作后,通过蜂鸣器发出短暂的声音来提供音频反馈。
3.4.3 独立按键函数体详细代码
/*-------------------------------------------------------------------
/* (C) Copyright 2021-2022, nbufe. All Rights Reserved
/*-------------------------------------------------------------------
/* File name : LED.c
/* Description :
/* Author : nbufe
/*-------------------------------------------------------------------
/* Update note:
/* --------- ----------- ----------------------------------------
/* Date Author Note
/* --------- ----------- ----------------------------------------
/*
**
/* 包含头文件 -------------------------------------------------------*/
#include "LED.h"
/* 私有类型定义 -----------------------------------------------------*/
/* None. */
extern unsigned char KeySec; //被触发的按键编号
/* 私有宏定义 -------------------------------------------------------*/
/* None. */
/* 私有变量 ---------------------------------------------------------*/
/* None. */
unsigned char upC=37;
unsigned char downC=17;
/* 扩展变量 ---------------------------------------------------------*/
/* None. */
/* 私有函数原形 -----------------------------------------------------*/
/* None. */
/* 函数体 -----------------------------------------------------------*/
/**
* 函数功能: 按键服务的应用程序
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
void key_service()
{
switch(KeySec) //按键服务状态切换
{
case 1:// 1号键 短按
upC++;
KeySec = 0; //响应按键服务处理程序后,按键编号清零,避免一致触发
beep_dr=0;
Delay_ms(500);
beep_dr=1;
break;
case 11:// 1号键长按连续步进触发
upC++;
KeySec = 0; //响应按键服务处理程序后,按键编号清零,避免一致触发
beep_dr=0;
Delay_ms(500);
beep_dr=1;
break;
case 2:// 2号键 短按
KeySec = 0; //响应按键服务处理程序后,按键编号清零,避免一致触发
beep_dr=0;
Delay_ms(500);
beep_dr=1;
break;
case 22:// 2号键的长按
led_dr4 = 1; //红LED灭
led_dr3 = 1; //蓝LED灭
LCD1602_Init();
KeySec = 0; //响应按键服务处理程序后,按键编号清零,避免一致触发
LCD1602_ShowString(1,0,"temperature");
beep_dr=0;
Delay_ms(500);
beep_dr=1;
break;
case 3:// 3号键 短按
downC++;
KeySec = 0; //响应按键服务处理程序后,按键编号清零,避免一致触发
beep_dr=0;
Delay_ms(500);
beep_dr=1;
break;
case 33:// 3号键长按连续步进触发
downC++;
KeySec = 0; //响应按键服务处理程序后,按键编号清零,避免一致触发
beep_dr=0;
Delay_ms(500);
beep_dr=1;
break;
case 4:// 4号键 短按
upC--;
KeySec = 0; //响应按键服务处理程序后,按键编号清零,避免一致触发
beep_dr=0;
Delay_ms(500);
beep_dr=1;
break;
case 44:// 4号键长按
downC--;
KeySec = 0; //响应按键服务处理程序后,按键编号清零,避免一致触发
beep_dr=0;
Delay_ms(500);
beep_dr=1;
break;
}
}
/*>>>>>>>>>> (C) COPYRIGHT NBUFE <<<<<< >>>>>> END OF FILE <<<<<<<<<<*/
4 总结与展望
4.1 总结
本报告详细介绍了基于STC8A8K64D4微控制器的温度计的设计与实现。首先,对国内外研究现状进行了综述,概述了温度计的应用背景和相关技术。然后,对系统的总体设计进行了阐述,包括系统功能、硬件环境搭建、硬件描述以及LED1602显示模块的详细介绍。接着,详细介绍了系统环境的搭建过程,包括软件环境和开发工具的选择与配置。随后,对硬件环境进行了扩写,详细描述了各个硬件模块的功能和连接方式。
4.2 展望
基于STC8A8K64D4的温度计设计与实现为温度测量和显示提供了一种简单而有效的解决方案。然而,作为一个基础的温度计系统,还有许多方面可以进一步扩展和改进:
界面优化:可以进一步改进用户界面,增加交互性和易用性。例如,可以添加菜单功能,使用户能够更方便地设置参数和查看历史数据。
数据存储与分析:可以考虑将温度数据存储到外部存储器中,以便进行长期的数据记录和分析。这样可以帮助用户更好地了解温度变化趋势,并进行更深入的数据分析。
多传感器支持:除了NTC温度传感器,还可以添加其他类型的温度传感器,如热敏电阻、热电偶等,以扩展温度范围和精确度。
远程监控与控制:通过添加无线通信模块,可以实现远程监控和控制功能。用户可以通过手机应用或云平台远程访问温度数据,并进行远程控制操作,提高系统的灵活性和便捷性。
故障诊断与报警:可以引入故障诊断和报警机制,当温度超过设定阈值或系统发生异常时,及时提醒用户,并采取相应的措施以保证安全和稳定性。
综上所述,基于STC8A8K64D4的温度计设计与实现在温度测量和显示方面提供了一个可靠的解决方案,并具有进一步拓展和改进的潜力。随着技术的不断发展,温度计系统将在更广泛的领域中发挥重要作用,为人们的生活和工作提供更好的温度监测和控制。
4.3 心得体会
通过对基于STC8A8K64D4的温度计的设计与实现的研究和探索,我深刻体会到了硬件与软件的结合在物联网应用中的重要性。在这个项目中,我不仅学习到了硬件环境搭建的方法和步骤,还深入了解了STC8A8K64D4微控制器的特性和使用方法。同时,我也加深了对温度传感器、AD转换器和液晶显示模块等硬件设备的理解。
在软件方面,我学习了如何编写与STC8A8K64D4微控制器兼容的代码,以实现温度数据的获取、处理和显示。我熟悉了嵌入式系统的开发流程和技巧,学会了使用相应的开发工具和调试方法。通过编程,我能够实现与硬件设备的交互,将抽象的温度数据转化为可视化的结果,提高了系统的可用性和用户体验。
此外,通过这个项目,我也更加了解了温度计在现实生活中的广泛应用。温度是一个重要的环境参数,在工业、农业、医疗和家庭等领域都有着广泛的应用需求。通过设计和实现温度计系统,可以实现对环境温度的实时监测和控制,提高生产效率、保障产品质量、提供舒适的生活环境等。
在整个项目的过程中,我也遇到了一些挑战和困难。例如,对硬件的理解和接线的准确性需要认真学习和仔细操作,否则可能会导致系统不稳定或功能失效。此外,编写嵌入式软件需要具备一定的编程基础和逻辑思维能力,对编程语言和开发工具的熟练度也有一定要求。因此,在项目中需要持续学习和探索,解决问题和优化系统的能力也是必不可少的。
总的来说,基于STC8A8K64D4的温度计的设计与实现是一项具有挑战性和实用性的项目。通过这个项目,我不仅掌握了嵌入式系统的开发方法和技巧,还深入了解了温度测量和显示的原理和应用。这对我的专业知识和技能提升有着积极的影响,并且培养了我解决问题和创新思维的能力。我相信在将来的学习和工作中,这些经验和知识都会发挥重要的作用,并为我进一步深入研究和应用物联网领域打下坚实的基础。
视频:
基于STC8A8K64D4的温度计的设计与实现