STC8增强型单片机开发day04

2024-05-13 20:52

本文主要是介绍STC8增强型单片机开发day04,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

热敏电阻

NTC(Negative Temperature Coefficient)是指随温度上升电阻减小、具有负温度系数的热敏电阻现象和材料

原理图

在这里插入图片描述

ADC功能引脚
ADC0P1.0
ADC1P1.1
ADC2P5.4
ADC3P1.3
ADC4P1.4
ADC5P1.5
ADC6P1.6
ADC7P1.7
ADC8P0.0
ADC9P0.1
ADC10P0.2
ADC11P0.3
ADC12P0.4
ADC13P0.5
ADC14P0.6

温度计算步骤

1. 通过ADC采样计算出热敏电阻位置的电压

V n t c 2.5 = A D C _ V a l u e 4096 V n t c = 2.5 × A D C _ V a l u e 4096 \begin{aligned} \frac{V_{ntc}}{2.5} &= \frac{ADC\_Value}{4096} \\ \\ V_{ntc} &= 2.5 \times \frac{ADC\_Value}{4096} \end{aligned} 2.5VntcVntc=4096ADC_Value=2.5×4096ADC_Value

○ ADC_Value就是通过ADC采样出来的的数值,范围是0-4096。
○ V_ntc即为对应的电压值

2. 通过欧姆定律计算热敏电阻的阻值

V n t c R n t c = 3.3 V − V n t c R 10 K = 3.3 V R 10 K + R n t c \frac{V_{ntc}}{R_{ntc}} = \frac{3.3V-V_{ntc}}{R_{10K}} = \frac{3.3V}{R_{10K} + R_{ntc}} RntcVntc=R10K3.3VVntc=R10K+Rntc3.3V

串联分压,电流不变。上面是热敏电阻ntc和10k电阻的电流等式,根据公式推导出热敏电阻的阻值计算公式:
R n t c = V n t c ⋅ R 10 k 3.3 V − V n t c R_{ntc} = \frac{V_{ntc} \cdot R_{10k}}{3.3V-V_{ntc}} Rntc=3.3VVntcVntcR10k

3. 通过阻值查表得到温度

在这里插入图片描述
采用表的方式来记录 电阻值和温度的关系。
其中,表中记录的是阻值,下标记录的是温度。可以通过阻值比对,查询出下标,下标就是对应的温度。

u16 code temp_table[]= {58354, // -5555464, // -5452698, // -5350048, // -5247515, // -5145097, // -5042789, // -4940589, // -4838492, // -4736496, // -4634597, // -4532791, // -4431075, // -4329444, // -4227896, // -4126427, // -4025034, // -3923713, // -3822460, // -3721273, // -3620148, // -3519083, // -3418075, // -3317120, // -3216216, // -3115361, // -3014551, // -2913785, // -2813061, // -2712376, // -2611728, // -2511114, // -2410535, // -239986,  // -229468,  // -218977,  // -208513,  // -198075,  // -187660,  // -177267,  // -166896,  // -156545,  // -146212,  // -135898,  // -125601,  // -115319,  // -105053,  // -94801,  // -84562,  // -74336,  // -64122,  // -53920,  // -43728,  // -33546,  // -23374,  // -13211,  // 03057,  // 12910,  // 22771,  // 32639,  // 42515,  // 52396,  // 62284,  // 72177,  // 82076,  // 91978,  // 101889,  // 111802,  // 121720,  // 131642,  // 141568,  // 151497,  // 161430,  // 171366,  // 181306,  // 191248,  // 201193,  // 211141,  // 221092,  // 231044,  // 241000,  // 25957,   // 26916,   // 27877,   // 28840,   // 29805,   // 30771,   // 31739,   // 32709,   // 33679,   // 34652,   // 35625,   // 36600,   // 37576,   // 38552,   // 39530,   // 40509,   // 41489,   // 42470,   // 43452,   // 44434,   // 45417,   // 46401,   // 47386,   // 48371,   // 49358,   // 50344,   // 51331,   // 52318,   // 53306,   // 54295,   // 55284,   // 56274,   // 57264,   // 58254,   // 59245,   // 60236,   // 61228,   // 62220,   // 63212,   // 64205,   // 65198,   // 66191,   // 67184,   // 68178,   // 69172,   // 70166,   // 71160,   // 72155,   // 73150,   // 74145,   // 75140,   // 76135,   // 77131,   // 78126,   // 79122,   // 80118,   // 81115,   // 82111,   // 83107,   // 84104,   // 85101,   // 8697,    // 8794,    // 8891,    // 8989,    // 9086,    // 9183,    // 9281,    // 9378,    // 9476,    // 9574,    // 9671,    // 9769,    // 9867,    // 9965,    // 10063,    // 10161,    // 10260,    // 10358,    // 10456,    // 10555,    // 10653,    // 10752,    // 10850,    // 10949,    // 11047,    // 11146,    // 11245,    // 11343,    // 11442,    // 11541,    // 11640,    // 11739,    // 11838,    // 11937,    // 12036,    // 12135,    // 12234,    // 12333,    // 12432,    // 125
};

代码参考

创建NTC.h,写入如下内容

#ifndef __NTC_H__
#define __NTC_H__#include "Config.h"// 求绝对值
#define abs(x)	((x > 0) ? (x) : (-(x)))#define NTC_GPIO			GPIO_P0#define NTC_GPIO_PIN	GPIO_Pin_4#define NTC_ACD_CH		ADC_CH12// 初始化NTC
void NTC_init();// 获取温度值
int NTC_get_temperature();#endif

创建一个NTC.c文件,写入如下内容,请自行将temp_table拷贝进来

#include "NTC.h"
#include "GPIO.h"
#include "ADC.h"
#include "NVIC.h"
#include <stdio.h>static void GPIO_config(void) {GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义GPIO_InitStructure.Pin  = NTC_GPIO_PIN;		//指定要初始化的IO,GPIO_InitStructure.Mode = GPIO_HighZ;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_Inilize(NTC_GPIO, &GPIO_InitStructure);//初始化
}/******************* AD配置函数 *******************/
void	ADC_config(void)
{ADC_InitTypeDef		ADC_InitStructure;		//结构定义ADC_InitStructure.ADC_SMPduty   = 31;		//ADC 模拟信号采样时间控制, 0~31(注意: SMPDUTY 一定不能设置小于 10)ADC_InitStructure.ADC_CsSetup   = 0;		//ADC 通道选择时间控制 0(默认),1ADC_InitStructure.ADC_CsHold    = 1;		//ADC 通道选择保持时间控制 0,1(默认),2,3ADC_InitStructure.ADC_Speed     = ADC_SPEED_2X1T;		//设置 ADC 工作时钟频率	ADC_SPEED_2X1T~ADC_SPEED_2X16TADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED;	//ADC结果调整,	ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIEDADC_Inilize(&ADC_InitStructure);		//初始化ADC_PowerControl(ENABLE);				//ADC电源开关, ENABLE或DISABLENVIC_ADC_Init(DISABLE,Priority_0);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}// 初始化NTC
void NTC_init() {GPIO_config();ADC_config();
}static int search_temp(float rst_Rx10){int i, min_index = 0;// 计算数组长度int len = sizeof(temp_table) / sizeof(u16);// 记录最小差值 float min_diff = abs(rst_Rx10 - temp_table[0]);for (i = 1; i < len; i++){// 计算数组里每一个阻值和rst_Rx10的差值float diff = abs(rst_Rx10 - temp_table[i]);// 得到差值最小元素对应的索引iif(diff < min_diff){// 如果有更小的差值,赋值min_diff = diff;min_index = i;}}printf("len: %d R: %.2f min_diff: %.2f min_index: %d \n", len, rst_Rx10, min_diff, min_index);return min_index;
}// 获取温度值
int NTC_get_temperature() {u16 adc_value;float rst_V;float rst_R;int rst_T;// 获取对应的ADC值adc_value = Get_ADCResult(NTC_ACD_CH);// adc_value返回的值范围 0 -> 4096// 等同于P05引脚的电压值和Vref的占比  1024// X = ADC_V  * Vref / 4096// 计算电压rst_V = adc_value * 2.5 / 4096;// 计算电阻值rst_R = rst_V * 10 / (3.3 - rst_V);// 9.36KΩ 将阻值兑换成温度rst_T = search_temp(rst_R * 100) - 55;printf("ADC: %d voltage: %.2f R = %.2f T = %d℃ \n", adc_value, rst_V, rst_R, (int)rst_T);return rst_T;
}

main函数中:


int rst_T;
NTC_init();rst_T = NTC_get_temperature();
printf("温度:%d \n", rst_T);

独立按键

原理图

在这里插入图片描述

按键消抖

  1. 软件延时法:在按键按下时,使用软件延时一段时间,例如10毫秒,然后再检测按键是否还处于按下状态,如果是,则认为按键有效。这种方法简单易行,但会浪费一定的处理器时间,同时需要根据实际情况调整延时时间。

  2. 硬件滤波法:在按键输入引脚上添加RC滤波电路,可以有效地去除按键信号上的瞬间噪声。这种方法对于高频噪声的去除效果较好,但需要一定的电路设计能力。

  3. 程序消抖法:在程序中记录按键前后两次的状态,如果两次状态不同,则认为按键有效。这种方法可以根据需要调整检测时间,消抖效果较好,但需要额外的程序设计。

我们采用程序消抖法。

软件设计

要求

当用户按下,或者松开按键时,捕获到这个事件。将事件通过串口发出来。

分析

监控引脚的高低电平变化。记录状态,比对实时状态。
● 监控:死循环去读取电平信息
● 记录与比对:通过变量记录,实时拿到当前状态,与记录的上一次进行比对。

实现单个按钮
#include "Config.h"
#include "Delay.h"
#include "GPIO.h"
#include "UART.h"
#include "NVIC.h"
#include "Switch.h"#define KEY1 P51void GPIO_config(void) {P5_MODE_IO_PU(GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4);
}void UART_config(void) {COMx_InitDefine		COMx_InitStructure;					//结构定义COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLEUART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3UART1_SW(UART1_SW_P30_P31);		// 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}u8 last_key_state = 1; // 抬起void main(){GPIO_config();UART_config();EA = 1;while(1){if(KEY1 == 1 && last_key_state == 0){ // 当前是抬起Up 1, 上一次是按下Down 0printf("KEY1 up\n");last_key_state = 1;}else if(KEY1 == 0 && last_key_state == 1){// 当前是按下Down 0, 上一次是抬起Up 1printf("KEY1 down\n");	last_key_state = 0;}delay_ms(20);}
}
实现多个按钮
#include "Config.h"
#include "Delay.h"
#include "GPIO.h"
#include "UART.h"
#include "NVIC.h"
#include "Switch.h"#define KEY1 P51
#define KEY2 P52
#define KEY3 P53
#define KEY4 P54void GPIO_config(void) {P5_MODE_IO_PU(GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4);
}void UART_config(void) {COMx_InitDefine		COMx_InitStructure;					//结构定义COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLEUART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3UART1_SW(UART1_SW_P30_P31);		// 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}#define	DOWN	0
#define	UP		1u8 last_key_states[] = {UP, UP, UP, UP};		// key的最后一次状态// 判断指定位置【是否是】按下或抬起
#define	IS_KEY_DOWN(i)		last_key_states[i] == DOWN
#define	IS_KEY_UP(i)		last_key_states[i] == UP// 将指定位置值【设置】为按下或抬起
#define SET_KEY_DOWN(i)		last_key_states[i] = DOWN
#define SET_KEY_UP(i)		last_key_states[i] = UPvoid main(){GPIO_config();UART_config();EA = 1;while(1){if(KEY1 && IS_KEY_DOWN(0)){ // 这次是抬起Up 1, 上一次是按下Down 0printf("KEY1 up\n");SET_KEY_UP(0);}else if(!KEY1 && IS_KEY_UP(0)){// 这次是按下Down 0, 上一次是抬起Up 1printf("KEY1 down\n");	SET_KEY_DOWN(0);}if(KEY2 && IS_KEY_DOWN(1)){ // 这次是抬起Up 1, 上一次是按下Down 0printf("KEY2 up\n");SET_KEY_UP(1);}else if(!KEY2 && IS_KEY_UP(1)){// 这次是按下Down 0, 上一次是抬起Up 1printf("KEY2 down\n");	SET_KEY_DOWN(1);}if(KEY3 && IS_KEY_DOWN(2)){ // 这次是抬起Up 1, 上一次是按下Down 0printf("KEY3 up\n");SET_KEY_UP(2);}else if(!KEY3 && IS_KEY_UP(2)){// 这次是按下Down 0, 上一次是抬起Up 1printf("KEY3 down\n");	SET_KEY_DOWN(2);}if(KEY4 && IS_KEY_DOWN(3)){ // 这次是抬起Up 1, 上一次是按下Down 0printf("KEY4 up\n");SET_KEY_UP(3);}else if(!KEY4 && IS_KEY_UP(3)){// 这次是按下Down 0, 上一次是抬起Up 1printf("KEY4 down\n");	SET_KEY_DOWN(3);}delay_ms(20);}
}
使用位操作存储状态
// P51, P52, P53, P54
//u8 last_key_states[] = {UP, UP, UP, UP}; 
// 0b 0 0 0 0 - 1 1 1 1
u8 last_key_states = 0x0F; 	// KEY最后一次状态的8个位(只使用低4位)// 判断指定位置【是否】是按下
//  0b 0 0 0 0 - 0 0 0 0
//& 0b 0 0 0 0 - 0 1 0 0		----- 判断指定位i=2是否是0
//  0b 0 0 0 0 - 0 0 0 0			== 0
#define IS_KEY_DOWN(i)			(last_key_states & (1 << i)) == 0// 判断指定位置【是否】是抬起
//  0b 0 0 0 0 - 1 1 0 0
//& 0b 0 0 0 0 - 1 0 0 0		----- 判断指定位i=3是否是1
//  0b 0 0 0 0 - 1 0 0 0			> 0
#define IS_KEY_UP(i)			(last_key_states & (1 << i)) > 0// 将指定位置值【设置】为按下
//   0b 0 0 0 0 - 1 1 0 0			
//&= 0b 1 1 1 1 - 1 0 1 1		------ 将指定位i=2设置为0,按下
//&=~0b 0 0 0 0 - 0 1 0 0
//	 0b 0 0 0 0 - 1 0 0 0		
#define SET_KEY_DOWN(i)			last_key_states &= ~(1 << i)// 将指定位置值【设置】为抬起
//   0b 0 0 0 0 - 1 1 0 0			
//|= 0b 0 0 0 0 - 0 0 1 0		------ 将指定位i=1设置为1,抬起
//   0b 0 0 0 0 - 1 1 1 0
#define SET_KEY_UP(i)			last_key_states |= (1 << i)

● u16存储状态: 16个 1 << i 只能存 16 位
● u32存储状态: 32个, 1 << i 要改成 1L << i 能存32位

这篇关于STC8增强型单片机开发day04的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/986801

相关文章

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并

基于Python开发PDF转PNG的可视化工具

《基于Python开发PDF转PNG的可视化工具》在数字文档处理领域,PDF到图像格式的转换是常见需求,本文介绍如何利用Python的PyMuPDF库和Tkinter框架开发一个带图形界面的PDF转P... 目录一、引言二、功能特性三、技术架构1. 技术栈组成2. 系统架构javascript设计3.效果图

基于Python开发PDF转Doc格式小程序

《基于Python开发PDF转Doc格式小程序》这篇文章主要为大家详细介绍了如何基于Python开发PDF转Doc格式小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用python实现PDF转Doc格式小程序以下是一个使用Python实现PDF转DOC格式的GUI程序,采用T

使用Python开发一个图像标注与OCR识别工具

《使用Python开发一个图像标注与OCR识别工具》:本文主要介绍一个使用Python开发的工具,允许用户在图像上进行矩形标注,使用OCR对标注区域进行文本识别,并将结果保存为Excel文件,感兴... 目录项目简介1. 图像加载与显示2. 矩形标注3. OCR识别4. 标注的保存与加载5. 裁剪与重置图像

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

使用Go语言开发一个命令行文件管理工具

《使用Go语言开发一个命令行文件管理工具》这篇文章主要为大家详细介绍了如何使用Go语言开发一款命令行文件管理工具,支持批量重命名,删除,创建,移动文件,需要的小伙伴可以了解下... 目录一、工具功能一览二、核心代码解析1. 主程序结构2. 批量重命名3. 批量删除4. 创建文件/目录5. 批量移动三、如何安