基于stm32的智能风扇设计

 

相关程序下载:https://download.csdn.net/download/ManJuSa/19775016

1 任务要求

题目:基于STM32智能风扇设计

基本要求:通过按键开、关风扇;

通过设定时间,定时关闭风扇;

风扇有普通模式,可以设置为快档,中档,慢档,跟普通风扇一样。

拓展功能:温度控制。OLED显示。

2 系统总体设计

 

DHT11温湿度传感器

STM32F103C8T6

TOUCH触摸键盘

TIM3定时器

OLED15864显示屏

PWM直流电机

此次采用STM32F103C8T6芯片进行设计风扇,该风扇有三种模式,分别是手动模式,温控模式,定时模式。模式切换用触摸键盘KEY_B控制。KEY_A控制手动模式开关和慢、中、快档,温控模式下的阈值选择,定时模式下的阈值选择。KEY_C控制温控和定时模式下的阈值加值。KEY_D控制温控模式下的减值以及定时模式下的定时开启开关。

将以上所有结果显示到OLED显示屏上,每个模式都有一个新的页面,方便、简洁。TIM3定时器用来产生1s中断给倒计时计时。另外,所有档位都有输出PWM脉冲,将PWM脉冲连接到直流电机即可转动不同速度。本次课设将利用继电器模拟电机的启停。

3 单元电路设计

3.1 STM32F103主芯片

STM32F103C8T6是一款基于ARM Cortex-M3内核(ARM公司在ARM11以后改用Cortex命名,并分成A、R和M三类,M系列有M0、M0+、M3、M4、M7)的32位的微控制器,采用LQFP48封装,由意法半导体公司(ST)推出,属于STM32系列(ST公司还有SPC5X系列微控制器)。其程序存储器FLASH容量是64KB (64K x 8bit),RAM容量是20KB(20K x 8bit),2个12bit ADC合计12路通道(外部通道只有PA0到PA7、PB0到PB1,并不是18通道),37个通用I/O口(PA0-PA15、PB0-PB15、PC13-PC15、PD0-PD1),4个16bit通用定时器(TIM1(带死区插入,常用于产生PWM控制电机)、TIM2、TIM3、TIM4),2个看门狗定时器(独立看门狗、窗口看门狗)1个24bit向下计数的滴答定时器(很重要,一般delay都使用这个定时器实现),2*IIC,2*SPI,3*USART,1*CAN,工作电压2V~3.6V,工作温度为-40°C ~ 85°C,系统时钟最高可到72MHz(一般是由8MHz的外部时钟经锁相环9倍频到72MHz)。

3.2 DHT11温湿度传感器

DHT11 采用单总线协议与单片机通信,单片机发送一次复位信号后,DHT11 从低功耗模式转换到高速模式,等待主机复位结束后,DHT11 发送响应信号,并拉高总线准备传输数据。一次完整的数据为 40bit,按照高位在前,低位在后的顺序传输。

数据格式为:8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数数据+8bit 温度小数数据+8bit 校验和,一共 5 字节(40bit)数据。由于 DHT11 分辨率只能精确到个位,所以小数部分是数据全为 0。校验和为前 4 个字节数据相加,校验的目的是为了保证数据传输的准确性。

DHT11 只有在接收到开始信号后才触发一次温湿度采集,如果没有接收到主机发送复位信号,DHT11 不主动进行温湿度采集。当数据采集完毕且无开始信号后,DHT11 自动切换到低速模式。

3.3 TOUCH触摸键盘

触摸按键与传统的机械按键相比,不仅美观而且耐用、寿命长,它颠覆了传统意义上的机械按键控制,只要轻轻触摸,就可以实现按键开关的控制、量化调节甚至方向控制。触摸按键已广泛应用于手机、DVD、洗衣机等消费类电子产品中。本文我们就介绍一种简单的触摸按键:电容式触摸按键。开发板上的电容触摸按键其实就是一小块覆铜区域, 也称之为触摸感应区,通常我们会将四周的铜片与电路板地信号连通,触摸感应区设计成方便手指触摸大小,并将其连接在输入捕获通道上。触摸感应区与四周的铜片区域就形成了一个电容,通过检测电容充放电时间即可判断是否有触摸。

此次设计功能如下:

KEY_A控制手动模式下关闭、满档、中档和快挡;控制温控模式下的两个阈值选择;控制定时模式下的三个时间阈值选择。

KEY_B控制界面的选择。默认界面为手动模式,下一页为温控模式,再下一页为定时模式。

KEY_C控制温控模式下的阈值加法以及定时模式下的阈值加法。

KEY_D控制温控模式下的阈值减法以及定时模式下的阈值减法,另外双击它还可以控制定时模式倒计时开关。

3.4 OLED12864显示屏

OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。OLED显示技术具有自发光的特性,采用非常薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光,而且OLED显示屏幕可视角度大,并且能够节省电能。OLED显示技术具有自发光的特性,采用非常薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光,而且OLED显示屏幕可视角度大,并且能够节省电能,从2003年开始这种显示设备在MP3播放器上得到了应用。

三种模式下都显示“模式”、“风速”,而且不同风速会显示“关”、“慢”、“中”、“快”;在温控模式下还显示了“温湿度”、阈值,定时模式显示倒计时。

3.5 PWM直流电机

脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。

直流无刷电机调速的原理就是在驱动电机转动的基础上,将驱动电流由PWM信号来控制,改变PWM信号的脉冲宽度,即通过调节MOSFET通断的时间来调节提供给电机三相的电流大小,从而对电机进行调速控制。STM32部的普通的定时器TIM3和TIM4,每个可以产生四路PWM发生器。

本次设计满档500,中档1000,快挡1500。

说明电路工作原理

此次采用STM32F103C8T6芯片进行设计风扇,该风扇有三种模式,分别是手动模式,温控模式,定时模式。模式切换用触摸键盘KEY_B控制。KEY_A控制手动模式开关和慢、中、快档,温控模式下的阈值选择,定时模式下的阈值选择。KEY_C控制温控和定时模式下的阈值加值。KEY_D控制温控模式下的减值以及定时模式下的定时开启开关。将以上所有结果显示到OLED显示屏上,每个模式都有一个新的页面,方便、简洁。TIM3定时器用来产生1s中断给倒计时计时。另外,所有档位都有输出PWM脉冲,将PWM脉冲连接到直流电机即可转动不同速度。

KEY_A控制手动模式下关闭、满档、中档和快挡;控制温控模式下的两个阈值选择;控制定时模式下的三个时间阈值选择。

KEY_B控制界面的选择。默认界面为手动模式,下一页为温控模式,再下一页为定时模式。

KEY_C控制温控模式下的阈值加法以及定时模式下的阈值加法。

KEY_D控制温控模式下的阈值减法以及定时模式下的阈值减法,另外双击它还可以控制定时模式倒计时开关。

三种模式下显示“模式”、“风速”,而且不同风速会显示“关”、“慢”、“中”、“快”;在温控模式下还显示了“温湿度”、阈值,定时模式显示倒计时。

本次设计满档500,中档1000,快挡1500。

困难问题

我遇到的困难是第一次我选用LM75A温度传感器,在OLED显示出温度值后百分百会卡死,后来改用DHUT11温湿度传感器后没有出现问题。

主程序代码:

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "tim.h"
#include "touch_key.h"
#include "dht11.h"
u8 key=0,mode=0,mode_shoudong=0,speed=0;
u8 time_flag=0,set_time=0;
u8 temp_flag=0,temp_low=25,temp_high=30;
u8 set_hour=0,set_min=0,set_sec=10;
u8 temp_read=0,time_read=0;
int main (void){//主程序
	u8 b[2];
	delay_ms(500);
	RCC_Configuration(); //时钟设置
	RELAY_Init();//继电器初始化
	I2C_Configuration();//I2C初始化
	DHT11_Init();
	OLED0561_Init(); //OLED初始化
	TOUCH_KEY_Init();//按键初始化
	TIM3_NVIC_Init ();//开启TIM3中断向量
	TIM3_Init(9999,7199);//定时器初始化,定时1秒(9999,7199)
	TIM3_PWM_Init(59999,23);//PWM时钟频率=72000000/(59999+1)*(23+1) = 50HZ (20ms)
	DHT11_ReadData(b);
	delay_ms(1000);//DHT11初始化后必要的延时(不得小于1秒)
	while(1){
		switch(key=key_scan())
		{
			case 1:
				if(mode==0)//手动模式
				{
					
					speed++;
					if(speed==4)
						speed=0;
				}
				if(mode==1)//温控
				{
					temp_flag++;//温控阈值更改标志位
					if(temp_flag==2)
						temp_flag=0;
				}
				if(mode==2)//定时
				{
					time_flag++;//定时更改标志位
					if(time_flag==3)
						time_flag=0;
				}
			break;
			case 2:
				mode++;// mode=0:手动  1:温控自动  2:定时
			OLED_DISPLAY_CLEAR();
			if(mode==3)
				mode=0;
			break;
			case 3:
				if(mode==1)
				{
					if(temp_flag==0)
					{
						if(temp_low<40)
							temp_low++;	
					}
						
					if(temp_flag==1)
					{
						if(temp_high<45)
						temp_high++;
					}
				}
				if(mode==2)
				{
					if(time_flag==0)
					{
						if(set_hour<23)
						set_hour++;
					}
					if(time_flag==1)
					{
						if(set_min<59)
						set_min++;
					}
					if(time_flag==2)
					{
						if(set_sec<59)
						set_sec++;
					}
				}
				break;
			case 4:
				if(mode==1)
				{
					if(temp_flag==0)
					{
						if(temp_low>20)
							temp_low--;	
					}
						
					if(temp_flag==1)
					{
						if(temp_high>25)
						temp_high--;
					}
				}
				if(mode==2)
				{
					if(time_flag==0)
					{
						if(set_hour>0)
						set_hour--;
					}
					if(time_flag==1)
					{
						if(set_min>0)
						set_min--;
					}
					if(time_flag==2)
					{
						if(set_sec>0)
						set_sec--;
					}
				}
				break;
			case 5:
				if(mode==2)
				{
					set_time++;//定时模式开关
					if(set_time==2)
						set_time=0;
				}
			}
		if(mode==0)//手动控制
		{	
			OLED_DISPLAY_16x16(0,0*16,0);//模
			OLED_DISPLAY_16x16(0,1*16,1);//式
			OLED_DISPLAY_8x16(0,5*8,58);//:
			OLED_DISPLAY_16x16(0,4*16,2);//手
			OLED_DISPLAY_16x16(0,5*16,3);//动
							if(speed==0)
			{
				RELAY_1(0);//继电器关闭
				TIM_SetCompare1(TIM3,0);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,14);//关
			}
			if(speed==1)
			{
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,500);
					OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,11);//慢
			}
			if(speed==2)
			{
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1000);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,12);//中
			}
			if(speed==3)
			{
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1500);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,13);//快
			}
			
		}
		if(mode==1)//温控
		{		
			DHT11_ReadData(b);
			OLED_DISPLAY_16x16(6,0*16,4);//温
			OLED_DISPLAY_16x16(6,1*16,17);//湿
			OLED_DISPLAY_16x16(6,2*16,6);//度
			OLED_DISPLAY_8x16(6,6*8,':');//
		OLED_DISPLAY_8x16(6,7*8,b[1]/10+0x30);//显示温度值
		OLED_DISPLAY_8x16(6,8*8,b[1]%10+0x30);//
			OLED_DISPLAY_8x16(6,10*8,'C');//
			OLED_DISPLAY_8x16(6,12*8,b[0]%10+0x30);//湿度值
			OLED_DISPLAY_8x16(6,13*8,b[0]%10+0x30);//
			OLED_DISPLAY_8x16(6,15*8,'%');//
			OLED_DISPLAY_16x16(0,0*16,0);//模
			OLED_DISPLAY_16x16(0,1*16,1);//式
			OLED_DISPLAY_8x16(0,5*8,58);//:
			OLED_DISPLAY_16x16(0,4*16,4);//温
			OLED_DISPLAY_16x16(0,5*16,5);//控
			OLED_DISPLAY_16x16(4,0*16,15);//阈
			OLED_DISPLAY_16x16(4,1*16,16);//值
			OLED_DISPLAY_8x16(4,5*8,58);//:
			OLED_DISPLAY_8x16(4,6*8,temp_low/10+0x30);//显示温度低值
			OLED_DISPLAY_8x16(4,7*8,temp_low%10+0x30);
			OLED_DISPLAY_8x16(4,9*8,temp_high/10+0x30);//显示温度高值
			OLED_DISPLAY_8x16(4,10*8,temp_high%10+0x30);			
			if(b[1]<temp_low)
			{
				RELAY_1(0);//继电器关闭
				TIM_SetCompare1(TIM3,0);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,14);//关
			}
			else if(b[1]>=temp_low&b[1]<temp_high)
			{			
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1000);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,12);//中
			}
			else if(b[1]>=temp_high)
			{	
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1500);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,13);//快
			}
		}
		if(mode==2)//定时
		{
			OLED_DISPLAY_16x16(0,0*16,0);//模
			OLED_DISPLAY_16x16(0,1*16,1);//式
			OLED_DISPLAY_8x16(0,5*8,58);//:
			OLED_DISPLAY_16x16(0,4*16,7);//定
			OLED_DISPLAY_16x16(0,5*16,8);//时
			OLED_DISPLAY_16x16(4,0*16,15);//阈
			OLED_DISPLAY_16x16(4,1*16,16);//值
			OLED_DISPLAY_8x16(4,5*8,58);//:
			OLED_DISPLAY_8x16(4,6*8,set_hour/10+0x30);//显示小时阈值
			OLED_DISPLAY_8x16(4,7*8,set_hour%10+0x30);
			OLED_DISPLAY_8x16(4,8*8,58);//:
			OLED_DISPLAY_8x16(4,9*8,set_min/10+0x30);//显示分钟阈值
			OLED_DISPLAY_8x16(4,10*8,set_min%10+0x30);
			OLED_DISPLAY_8x16(4,11*8,58);//:
			OLED_DISPLAY_8x16(4,12*8,set_sec/10+0x30);//显示秒钟阈值
			OLED_DISPLAY_8x16(4,13*8,set_sec%10+0x30);
			if(set_time==1){
				if(set_hour==0&set_min==0&set_sec==0)
				{
					RELAY_1(0);//继电器关闭
				TIM_SetCompare1(TIM3,0);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,14);//关
					set_time=0;
				}
				else
				{
					RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1500);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,13);//快
				}
			}
			
		}
}
}

定时器tim中断代码

void TIM3_IRQHandler(void){ //TIM3中断处理函数
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){	//判断是否是TIM3中断
			if(mode==2)//定时模式
			{	
					if(set_time)
					{
						set_time_count++;
						if(set_time_count>=50)
						{
							set_time_count=0;										
				if(set_sec>0)
				set_sec--;
				else if(set_min>0)
					{
						set_min--;
						set_sec=59;
					}
				else if(set_hour>0)
						{
							set_hour--;
							set_min=59;
							set_sec=59;
						}
				}
			}
    }
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
	}
}

键盘处理程序代码

u8 key_scan(void){
u8 keya=0,keyb=0,keyc=0,keyd=0,keye=0,keyf=0,key_count=0;
	if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_A)){ //读触摸按键的电平
		delay_ms(10);
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_A))
			keya=1;
		while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_A));
	}
	if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_B)){ //读触摸按键的电平
		delay_ms(10);
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_B))
			keyb=1;
		while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_B));
	}
	if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_C)){ //读触摸按键的电平
		delay_ms(10);
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_C))
			keyc=1;
		while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_C));
	}
	if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D)){ //读触摸按键的电平
			delay_ms(10); //延时去抖动
			if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D)){//判断长短键
				while((!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D))&&c<KEYD_SPEED1){ //循环判断长按,到时跳转
					c++;delay_ms(10); //长按判断的计时
				}
				if(c>=KEYD_SPEED1){ //长键处理
					//长按后执行的程序放到此处
					keye=1;
					while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D));
				}else{ //单击处理
					for(b=0;b<KEYD_SPEED2;b++){//检测双击
						delay_ms(10);
						if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D)){
							a=1;
							//双击后执行的程序放到此处
							keyf=1;
							while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D));
						}
					}
					if(a==0){ //判断单击
						//单击后执行的程序放到此处
						keyd=1;
						
					}
				}
				a=0;c=0; //参数清0
			}
	}
	if(keya==1)//key_a单击
		key_count=1;
	else if(keyb==1)//key_b单击
		key_count=2;
	else if(keyc==1)//key_c单击
		key_count=3;
	else if(keyd==1)//key_d单击
		key_count=4;
	else if(keye==1)//key_d长按
		key_count=6;
	else if(keyf==1)//key_d双击
		key_count=5;
	return key_count;
}

OLED汉字代码:


#ifndef __CHS_16x16_H
#define __CHS_16x16_H	 

uc8 GB_16[] = {         // 数据表
//"模", 0
			0x10,0x10,0xD0,0xFF,0x94,0x14,0xE4,0xBF,
      0xA4,0xA4,0xA4,0xBF,0xF4,0x26,0x04,0x00,
      0x04,0x03,0x00,0xFF,0x08,0x89,0x8B,0x4A,
      0x2A,0x1E,0x2A,0x2A,0x4B,0xC8,0x48,0x00,

//"式", 1
			0x10,0x10,0x90,0x90,0x90,0x90,0x90,0x10,
      0xFF,0x10,0x12,0x14,0x10,0x18,0x10,0x00,
      0x00,0x20,0x60,0x20,0x1F,0x10,0x10,0x08,
      0x01,0x06,0x18,0x20,0x40,0x80,0x70,0x00,

//"手", 2
			0x00,0x04,0x24,0x24,0x24,0x24,0x24,0xFC,
      0x22,0x22,0x22,0x33,0x22,0x00,0x00,0x00,
      0x02,0x02,0x02,0x02,0x02,0x42,0x82,0x7F,
      0x02,0x02,0x02,0x02,0x02,0x03,0x02,0x00,

//"动", 3
			0x20,0x24,0x24,0xE4,0x26,0x34,0x20,0x10,
      0x10,0xFF,0x10,0x10,0x10,0xF8,0x10,0x00,
      0x08,0x1C,0x0B,0x08,0x08,0x8A,0x4C,0x30,
      0x0C,0x03,0x40,0x80,0x40,0x3F,0x00,0x00,

//"温", 4
			0x10,0x22,0x64,0x0C,0x80,0x00,0xFE,0x92,
      0x92,0x92,0x92,0x92,0xFF,0x02,0x00,0x00,
      0x04,0x04,0xFE,0x01,0x40,0x7E,0x42,0x42,
      0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00,

//"控", 5
			0x10,0x10,0x10,0xFF,0x90,0x50,0x0C,0x44,
      0x24,0x15,0x06,0x14,0x24,0x54,0x0C,0x00,
      0x02,0x42,0x81,0x7F,0x00,0x40,0x42,0x42,
      0x42,0x42,0x7E,0x42,0x43,0x62,0x40,0x00,

//"度", 6
			0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0xA5,
      0xA6,0xA4,0xFC,0x24,0x34,0x26,0x04,0x00,
      0x40,0x20,0x9F,0x80,0x42,0x42,0x26,0x2A,
      0x12,0x2A,0x26,0x42,0x40,0xC0,0x40,0x00,

//"定", 7
			0x10,0x0C,0x04,0x24,0x24,0x24,0x25,0xE6,
      0x24,0x24,0x34,0x24,0x04,0x14,0x0C,0x00,
      0x80,0x40,0x20,0x1F,0x20,0x40,0x40,0x7F,
      0x42,0x42,0x43,0x42,0x40,0x60,0x20,0x00,

//"时", 8
			0x00,0xFC,0x84,0x84,0x84,0xFE,0x14,0x10,
      0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x00,
      0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,
      0x00,0x23,0x40,0x80,0x7F,0x00,0x00,0x00,
			
//"风", 9
			0x00,0x00,0xFE,0x02,0x0A,0x12,0x62,0x82,
      0x62,0x1A,0x02,0xFF,0x02,0x00,0x00,0x00,
      0x80,0x40,0x3F,0x20,0x10,0x08,0x06,0x01,
      0x06,0x18,0x00,0x3F,0x40,0x80,0xE0,0x00,

//"速", 10
			0x40,0x42,0x44,0xCC,0x00,0xF4,0x94,0x94,
      0x94,0xFF,0x94,0x94,0x94,0xF6,0x04,0x00,
      0x00,0x40,0x20,0x1F,0x20,0x51,0x48,0x44,
      0x42,0x7F,0x42,0x44,0x4C,0x61,0x20,0x00,

//"慢", 11
			0x40,0x38,0x00,0xFF,0x08,0xD0,0x5F,0x55,
      0xD5,0x55,0xD5,0x55,0x5F,0xE0,0x40,0x00,
      0x00,0x00,0x00,0xFF,0x00,0x83,0x8A,0x5A,
      0x2B,0x2A,0x2B,0x5A,0x4A,0x83,0x80,0x00,

//"中", 12
			0x00,0xF8,0x08,0x08,0x08,0x08,0x08,0xFF,
      0x08,0x08,0x08,0x08,0x08,0xFC,0x08,0x00,
      0x00,0x03,0x01,0x01,0x01,0x01,0x01,0xFF,
      0x01,0x01,0x01,0x01,0x01,0x03,0x00,0x00,

//"快", 13
			0x80,0x70,0x00,0xFF,0x10,0x20,0x10,0x10,
      0xFF,0x10,0x10,0x10,0xF8,0x10,0x00,0x00,
      0x00,0x00,0x00,0xFF,0x82,0x42,0x22,0x1A,
      0x07,0x0A,0x12,0x22,0x43,0xC2,0x42,0x00,
			
//"关", 14
			0x00,0x10,0x10,0x11,0x12,0x1C,0x10,0xF0,
      0x10,0x18,0x14,0x13,0x1A,0x90,0x00,0x00,
      0x81,0x81,0x41,0x41,0x21,0x11,0x0D,0x03,
      0x0D,0x11,0x21,0x21,0x41,0xC1,0x41,0x00,
			
//"阈", 15
			0x00,0xFC,0x11,0xD2,0x50,0x52,0xD2,0x12,
      0xFE,0x12,0x16,0x9A,0x12,0xFF,0x02,0x00,
      0x00,0xFF,0x10,0x17,0x14,0x14,0x57,0x20,
      0x10,0x0F,0x12,0x39,0x80,0xFF,0x00,0x00,

//"值", 16
			0x80,0x40,0x20,0xF8,0x07,0x04,0xE4,0xA4,
      0xA4,0xBF,0xA4,0xA4,0xF6,0x24,0x00,0x00,
      0x00,0x00,0x00,0xFF,0x40,0x40,0x7F,0x4A,
      0x4A,0x4A,0x4A,0x4A,0x7F,0x40,0x40,0x00,
			
//"湿", 17
			0x10,0x22,0x64,0x0C,0x80,0xFE,0x92,0x92,
      0x92,0x92,0x92,0x92,0xFF,0x02,0x00,0x00,
      0x04,0x04,0xFE,0x41,0x44,0x48,0x50,0x7F,
      0x40,0x40,0x7F,0x50,0x48,0x64,0x40,0x00,
};

 

版权声明:本文为CSDN博主「醉痴璧」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ManJuSa/article/details/118105079

 

相关程序下载:https://download.csdn.net/download/ManJuSa/19775016

1 任务要求

题目:基于STM32智能风扇设计

基本要求:通过按键开、关风扇;

通过设定时间,定时关闭风扇;

风扇有普通模式,可以设置为快档,中档,慢档,跟普通风扇一样。

拓展功能:温度控制。OLED显示。

2 系统总体设计

 

DHT11温湿度传感器

STM32F103C8T6

TOUCH触摸键盘

TIM3定时器

OLED15864显示屏

PWM直流电机

此次采用STM32F103C8T6芯片进行设计风扇,该风扇有三种模式,分别是手动模式,温控模式,定时模式。模式切换用触摸键盘KEY_B控制。KEY_A控制手动模式开关和慢、中、快档,温控模式下的阈值选择,定时模式下的阈值选择。KEY_C控制温控和定时模式下的阈值加值。KEY_D控制温控模式下的减值以及定时模式下的定时开启开关。

将以上所有结果显示到OLED显示屏上,每个模式都有一个新的页面,方便、简洁。TIM3定时器用来产生1s中断给倒计时计时。另外,所有档位都有输出PWM脉冲,将PWM脉冲连接到直流电机即可转动不同速度。本次课设将利用继电器模拟电机的启停。

3 单元电路设计

3.1 STM32F103主芯片

STM32F103C8T6是一款基于ARM Cortex-M3内核(ARM公司在ARM11以后改用Cortex命名,并分成A、R和M三类,M系列有M0、M0+、M3、M4、M7)的32位的微控制器,采用LQFP48封装,由意法半导体公司(ST)推出,属于STM32系列(ST公司还有SPC5X系列微控制器)。其程序存储器FLASH容量是64KB (64K x 8bit),RAM容量是20KB(20K x 8bit),2个12bit ADC合计12路通道(外部通道只有PA0到PA7、PB0到PB1,并不是18通道),37个通用I/O口(PA0-PA15、PB0-PB15、PC13-PC15、PD0-PD1),4个16bit通用定时器(TIM1(带死区插入,常用于产生PWM控制电机)、TIM2、TIM3、TIM4),2个看门狗定时器(独立看门狗、窗口看门狗)1个24bit向下计数的滴答定时器(很重要,一般delay都使用这个定时器实现),2*IIC,2*SPI,3*USART,1*CAN,工作电压2V~3.6V,工作温度为-40°C ~ 85°C,系统时钟最高可到72MHz(一般是由8MHz的外部时钟经锁相环9倍频到72MHz)。

3.2 DHT11温湿度传感器

DHT11 采用单总线协议与单片机通信,单片机发送一次复位信号后,DHT11 从低功耗模式转换到高速模式,等待主机复位结束后,DHT11 发送响应信号,并拉高总线准备传输数据。一次完整的数据为 40bit,按照高位在前,低位在后的顺序传输。

数据格式为:8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数数据+8bit 温度小数数据+8bit 校验和,一共 5 字节(40bit)数据。由于 DHT11 分辨率只能精确到个位,所以小数部分是数据全为 0。校验和为前 4 个字节数据相加,校验的目的是为了保证数据传输的准确性。

DHT11 只有在接收到开始信号后才触发一次温湿度采集,如果没有接收到主机发送复位信号,DHT11 不主动进行温湿度采集。当数据采集完毕且无开始信号后,DHT11 自动切换到低速模式。

3.3 TOUCH触摸键盘

触摸按键与传统的机械按键相比,不仅美观而且耐用、寿命长,它颠覆了传统意义上的机械按键控制,只要轻轻触摸,就可以实现按键开关的控制、量化调节甚至方向控制。触摸按键已广泛应用于手机、DVD、洗衣机等消费类电子产品中。本文我们就介绍一种简单的触摸按键:电容式触摸按键。开发板上的电容触摸按键其实就是一小块覆铜区域, 也称之为触摸感应区,通常我们会将四周的铜片与电路板地信号连通,触摸感应区设计成方便手指触摸大小,并将其连接在输入捕获通道上。触摸感应区与四周的铜片区域就形成了一个电容,通过检测电容充放电时间即可判断是否有触摸。

此次设计功能如下:

KEY_A控制手动模式下关闭、满档、中档和快挡;控制温控模式下的两个阈值选择;控制定时模式下的三个时间阈值选择。

KEY_B控制界面的选择。默认界面为手动模式,下一页为温控模式,再下一页为定时模式。

KEY_C控制温控模式下的阈值加法以及定时模式下的阈值加法。

KEY_D控制温控模式下的阈值减法以及定时模式下的阈值减法,另外双击它还可以控制定时模式倒计时开关。

3.4 OLED12864显示屏

OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。OLED显示技术具有自发光的特性,采用非常薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光,而且OLED显示屏幕可视角度大,并且能够节省电能。OLED显示技术具有自发光的特性,采用非常薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光,而且OLED显示屏幕可视角度大,并且能够节省电能,从2003年开始这种显示设备在MP3播放器上得到了应用。

三种模式下都显示“模式”、“风速”,而且不同风速会显示“关”、“慢”、“中”、“快”;在温控模式下还显示了“温湿度”、阈值,定时模式显示倒计时。

3.5 PWM直流电机

脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。

直流无刷电机调速的原理就是在驱动电机转动的基础上,将驱动电流由PWM信号来控制,改变PWM信号的脉冲宽度,即通过调节MOSFET通断的时间来调节提供给电机三相的电流大小,从而对电机进行调速控制。STM32部的普通的定时器TIM3和TIM4,每个可以产生四路PWM发生器。

本次设计满档500,中档1000,快挡1500。

说明电路工作原理

此次采用STM32F103C8T6芯片进行设计风扇,该风扇有三种模式,分别是手动模式,温控模式,定时模式。模式切换用触摸键盘KEY_B控制。KEY_A控制手动模式开关和慢、中、快档,温控模式下的阈值选择,定时模式下的阈值选择。KEY_C控制温控和定时模式下的阈值加值。KEY_D控制温控模式下的减值以及定时模式下的定时开启开关。将以上所有结果显示到OLED显示屏上,每个模式都有一个新的页面,方便、简洁。TIM3定时器用来产生1s中断给倒计时计时。另外,所有档位都有输出PWM脉冲,将PWM脉冲连接到直流电机即可转动不同速度。

KEY_A控制手动模式下关闭、满档、中档和快挡;控制温控模式下的两个阈值选择;控制定时模式下的三个时间阈值选择。

KEY_B控制界面的选择。默认界面为手动模式,下一页为温控模式,再下一页为定时模式。

KEY_C控制温控模式下的阈值加法以及定时模式下的阈值加法。

KEY_D控制温控模式下的阈值减法以及定时模式下的阈值减法,另外双击它还可以控制定时模式倒计时开关。

三种模式下显示“模式”、“风速”,而且不同风速会显示“关”、“慢”、“中”、“快”;在温控模式下还显示了“温湿度”、阈值,定时模式显示倒计时。

本次设计满档500,中档1000,快挡1500。

困难问题

我遇到的困难是第一次我选用LM75A温度传感器,在OLED显示出温度值后百分百会卡死,后来改用DHUT11温湿度传感器后没有出现问题。

主程序代码:

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "tim.h"
#include "touch_key.h"
#include "dht11.h"
u8 key=0,mode=0,mode_shoudong=0,speed=0;
u8 time_flag=0,set_time=0;
u8 temp_flag=0,temp_low=25,temp_high=30;
u8 set_hour=0,set_min=0,set_sec=10;
u8 temp_read=0,time_read=0;
int main (void){//主程序
	u8 b[2];
	delay_ms(500);
	RCC_Configuration(); //时钟设置
	RELAY_Init();//继电器初始化
	I2C_Configuration();//I2C初始化
	DHT11_Init();
	OLED0561_Init(); //OLED初始化
	TOUCH_KEY_Init();//按键初始化
	TIM3_NVIC_Init ();//开启TIM3中断向量
	TIM3_Init(9999,7199);//定时器初始化,定时1秒(9999,7199)
	TIM3_PWM_Init(59999,23);//PWM时钟频率=72000000/(59999+1)*(23+1) = 50HZ (20ms)
	DHT11_ReadData(b);
	delay_ms(1000);//DHT11初始化后必要的延时(不得小于1秒)
	while(1){
		switch(key=key_scan())
		{
			case 1:
				if(mode==0)//手动模式
				{
					
					speed++;
					if(speed==4)
						speed=0;
				}
				if(mode==1)//温控
				{
					temp_flag++;//温控阈值更改标志位
					if(temp_flag==2)
						temp_flag=0;
				}
				if(mode==2)//定时
				{
					time_flag++;//定时更改标志位
					if(time_flag==3)
						time_flag=0;
				}
			break;
			case 2:
				mode++;// mode=0:手动  1:温控自动  2:定时
			OLED_DISPLAY_CLEAR();
			if(mode==3)
				mode=0;
			break;
			case 3:
				if(mode==1)
				{
					if(temp_flag==0)
					{
						if(temp_low<40)
							temp_low++;	
					}
						
					if(temp_flag==1)
					{
						if(temp_high<45)
						temp_high++;
					}
				}
				if(mode==2)
				{
					if(time_flag==0)
					{
						if(set_hour<23)
						set_hour++;
					}
					if(time_flag==1)
					{
						if(set_min<59)
						set_min++;
					}
					if(time_flag==2)
					{
						if(set_sec<59)
						set_sec++;
					}
				}
				break;
			case 4:
				if(mode==1)
				{
					if(temp_flag==0)
					{
						if(temp_low>20)
							temp_low--;	
					}
						
					if(temp_flag==1)
					{
						if(temp_high>25)
						temp_high--;
					}
				}
				if(mode==2)
				{
					if(time_flag==0)
					{
						if(set_hour>0)
						set_hour--;
					}
					if(time_flag==1)
					{
						if(set_min>0)
						set_min--;
					}
					if(time_flag==2)
					{
						if(set_sec>0)
						set_sec--;
					}
				}
				break;
			case 5:
				if(mode==2)
				{
					set_time++;//定时模式开关
					if(set_time==2)
						set_time=0;
				}
			}
		if(mode==0)//手动控制
		{	
			OLED_DISPLAY_16x16(0,0*16,0);//模
			OLED_DISPLAY_16x16(0,1*16,1);//式
			OLED_DISPLAY_8x16(0,5*8,58);//:
			OLED_DISPLAY_16x16(0,4*16,2);//手
			OLED_DISPLAY_16x16(0,5*16,3);//动
							if(speed==0)
			{
				RELAY_1(0);//继电器关闭
				TIM_SetCompare1(TIM3,0);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,14);//关
			}
			if(speed==1)
			{
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,500);
					OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,11);//慢
			}
			if(speed==2)
			{
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1000);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,12);//中
			}
			if(speed==3)
			{
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1500);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,13);//快
			}
			
		}
		if(mode==1)//温控
		{		
			DHT11_ReadData(b);
			OLED_DISPLAY_16x16(6,0*16,4);//温
			OLED_DISPLAY_16x16(6,1*16,17);//湿
			OLED_DISPLAY_16x16(6,2*16,6);//度
			OLED_DISPLAY_8x16(6,6*8,':');//
		OLED_DISPLAY_8x16(6,7*8,b[1]/10+0x30);//显示温度值
		OLED_DISPLAY_8x16(6,8*8,b[1]%10+0x30);//
			OLED_DISPLAY_8x16(6,10*8,'C');//
			OLED_DISPLAY_8x16(6,12*8,b[0]%10+0x30);//湿度值
			OLED_DISPLAY_8x16(6,13*8,b[0]%10+0x30);//
			OLED_DISPLAY_8x16(6,15*8,'%');//
			OLED_DISPLAY_16x16(0,0*16,0);//模
			OLED_DISPLAY_16x16(0,1*16,1);//式
			OLED_DISPLAY_8x16(0,5*8,58);//:
			OLED_DISPLAY_16x16(0,4*16,4);//温
			OLED_DISPLAY_16x16(0,5*16,5);//控
			OLED_DISPLAY_16x16(4,0*16,15);//阈
			OLED_DISPLAY_16x16(4,1*16,16);//值
			OLED_DISPLAY_8x16(4,5*8,58);//:
			OLED_DISPLAY_8x16(4,6*8,temp_low/10+0x30);//显示温度低值
			OLED_DISPLAY_8x16(4,7*8,temp_low%10+0x30);
			OLED_DISPLAY_8x16(4,9*8,temp_high/10+0x30);//显示温度高值
			OLED_DISPLAY_8x16(4,10*8,temp_high%10+0x30);			
			if(b[1]<temp_low)
			{
				RELAY_1(0);//继电器关闭
				TIM_SetCompare1(TIM3,0);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,14);//关
			}
			else if(b[1]>=temp_low&b[1]<temp_high)
			{			
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1000);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,12);//中
			}
			else if(b[1]>=temp_high)
			{	
				RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1500);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,13);//快
			}
		}
		if(mode==2)//定时
		{
			OLED_DISPLAY_16x16(0,0*16,0);//模
			OLED_DISPLAY_16x16(0,1*16,1);//式
			OLED_DISPLAY_8x16(0,5*8,58);//:
			OLED_DISPLAY_16x16(0,4*16,7);//定
			OLED_DISPLAY_16x16(0,5*16,8);//时
			OLED_DISPLAY_16x16(4,0*16,15);//阈
			OLED_DISPLAY_16x16(4,1*16,16);//值
			OLED_DISPLAY_8x16(4,5*8,58);//:
			OLED_DISPLAY_8x16(4,6*8,set_hour/10+0x30);//显示小时阈值
			OLED_DISPLAY_8x16(4,7*8,set_hour%10+0x30);
			OLED_DISPLAY_8x16(4,8*8,58);//:
			OLED_DISPLAY_8x16(4,9*8,set_min/10+0x30);//显示分钟阈值
			OLED_DISPLAY_8x16(4,10*8,set_min%10+0x30);
			OLED_DISPLAY_8x16(4,11*8,58);//:
			OLED_DISPLAY_8x16(4,12*8,set_sec/10+0x30);//显示秒钟阈值
			OLED_DISPLAY_8x16(4,13*8,set_sec%10+0x30);
			if(set_time==1){
				if(set_hour==0&set_min==0&set_sec==0)
				{
					RELAY_1(0);//继电器关闭
				TIM_SetCompare1(TIM3,0);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,14);//关
					set_time=0;
				}
				else
				{
					RELAY_1(1);//继电器打开
				TIM_SetCompare1(TIM3,1500);
				OLED_DISPLAY_16x16(2,0*16,9);//风
				OLED_DISPLAY_16x16(2,1*16,10);//速
				OLED_DISPLAY_8x16(2,5*8,58);//:
				OLED_DISPLAY_16x16(2,5*16,13);//快
				}
			}
			
		}
}
}

定时器tim中断代码

void TIM3_IRQHandler(void){ //TIM3中断处理函数
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){	//判断是否是TIM3中断
			if(mode==2)//定时模式
			{	
					if(set_time)
					{
						set_time_count++;
						if(set_time_count>=50)
						{
							set_time_count=0;										
				if(set_sec>0)
				set_sec--;
				else if(set_min>0)
					{
						set_min--;
						set_sec=59;
					}
				else if(set_hour>0)
						{
							set_hour--;
							set_min=59;
							set_sec=59;
						}
				}
			}
    }
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
	}
}

键盘处理程序代码

u8 key_scan(void){
u8 keya=0,keyb=0,keyc=0,keyd=0,keye=0,keyf=0,key_count=0;
	if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_A)){ //读触摸按键的电平
		delay_ms(10);
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_A))
			keya=1;
		while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_A));
	}
	if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_B)){ //读触摸按键的电平
		delay_ms(10);
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_B))
			keyb=1;
		while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_B));
	}
	if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_C)){ //读触摸按键的电平
		delay_ms(10);
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_C))
			keyc=1;
		while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_C));
	}
	if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D)){ //读触摸按键的电平
			delay_ms(10); //延时去抖动
			if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D)){//判断长短键
				while((!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D))&&c<KEYD_SPEED1){ //循环判断长按,到时跳转
					c++;delay_ms(10); //长按判断的计时
				}
				if(c>=KEYD_SPEED1){ //长键处理
					//长按后执行的程序放到此处
					keye=1;
					while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D));
				}else{ //单击处理
					for(b=0;b<KEYD_SPEED2;b++){//检测双击
						delay_ms(10);
						if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D)){
							a=1;
							//双击后执行的程序放到此处
							keyf=1;
							while(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D));
						}
					}
					if(a==0){ //判断单击
						//单击后执行的程序放到此处
						keyd=1;
						
					}
				}
				a=0;c=0; //参数清0
			}
	}
	if(keya==1)//key_a单击
		key_count=1;
	else if(keyb==1)//key_b单击
		key_count=2;
	else if(keyc==1)//key_c单击
		key_count=3;
	else if(keyd==1)//key_d单击
		key_count=4;
	else if(keye==1)//key_d长按
		key_count=6;
	else if(keyf==1)//key_d双击
		key_count=5;
	return key_count;
}

OLED汉字代码:


#ifndef __CHS_16x16_H
#define __CHS_16x16_H	 

uc8 GB_16[] = {         // 数据表
//"模", 0
			0x10,0x10,0xD0,0xFF,0x94,0x14,0xE4,0xBF,
      0xA4,0xA4,0xA4,0xBF,0xF4,0x26,0x04,0x00,
      0x04,0x03,0x00,0xFF,0x08,0x89,0x8B,0x4A,
      0x2A,0x1E,0x2A,0x2A,0x4B,0xC8,0x48,0x00,

//"式", 1
			0x10,0x10,0x90,0x90,0x90,0x90,0x90,0x10,
      0xFF,0x10,0x12,0x14,0x10,0x18,0x10,0x00,
      0x00,0x20,0x60,0x20,0x1F,0x10,0x10,0x08,
      0x01,0x06,0x18,0x20,0x40,0x80,0x70,0x00,

//"手", 2
			0x00,0x04,0x24,0x24,0x24,0x24,0x24,0xFC,
      0x22,0x22,0x22,0x33,0x22,0x00,0x00,0x00,
      0x02,0x02,0x02,0x02,0x02,0x42,0x82,0x7F,
      0x02,0x02,0x02,0x02,0x02,0x03,0x02,0x00,

//"动", 3
			0x20,0x24,0x24,0xE4,0x26,0x34,0x20,0x10,
      0x10,0xFF,0x10,0x10,0x10,0xF8,0x10,0x00,
      0x08,0x1C,0x0B,0x08,0x08,0x8A,0x4C,0x30,
      0x0C,0x03,0x40,0x80,0x40,0x3F,0x00,0x00,

//"温", 4
			0x10,0x22,0x64,0x0C,0x80,0x00,0xFE,0x92,
      0x92,0x92,0x92,0x92,0xFF,0x02,0x00,0x00,
      0x04,0x04,0xFE,0x01,0x40,0x7E,0x42,0x42,
      0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00,

//"控", 5
			0x10,0x10,0x10,0xFF,0x90,0x50,0x0C,0x44,
      0x24,0x15,0x06,0x14,0x24,0x54,0x0C,0x00,
      0x02,0x42,0x81,0x7F,0x00,0x40,0x42,0x42,
      0x42,0x42,0x7E,0x42,0x43,0x62,0x40,0x00,

//"度", 6
			0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0xA5,
      0xA6,0xA4,0xFC,0x24,0x34,0x26,0x04,0x00,
      0x40,0x20,0x9F,0x80,0x42,0x42,0x26,0x2A,
      0x12,0x2A,0x26,0x42,0x40,0xC0,0x40,0x00,

//"定", 7
			0x10,0x0C,0x04,0x24,0x24,0x24,0x25,0xE6,
      0x24,0x24,0x34,0x24,0x04,0x14,0x0C,0x00,
      0x80,0x40,0x20,0x1F,0x20,0x40,0x40,0x7F,
      0x42,0x42,0x43,0x42,0x40,0x60,0x20,0x00,

//"时", 8
			0x00,0xFC,0x84,0x84,0x84,0xFE,0x14,0x10,
      0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x00,
      0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,
      0x00,0x23,0x40,0x80,0x7F,0x00,0x00,0x00,
			
//"风", 9
			0x00,0x00,0xFE,0x02,0x0A,0x12,0x62,0x82,
      0x62,0x1A,0x02,0xFF,0x02,0x00,0x00,0x00,
      0x80,0x40,0x3F,0x20,0x10,0x08,0x06,0x01,
      0x06,0x18,0x00,0x3F,0x40,0x80,0xE0,0x00,

//"速", 10
			0x40,0x42,0x44,0xCC,0x00,0xF4,0x94,0x94,
      0x94,0xFF,0x94,0x94,0x94,0xF6,0x04,0x00,
      0x00,0x40,0x20,0x1F,0x20,0x51,0x48,0x44,
      0x42,0x7F,0x42,0x44,0x4C,0x61,0x20,0x00,

//"慢", 11
			0x40,0x38,0x00,0xFF,0x08,0xD0,0x5F,0x55,
      0xD5,0x55,0xD5,0x55,0x5F,0xE0,0x40,0x00,
      0x00,0x00,0x00,0xFF,0x00,0x83,0x8A,0x5A,
      0x2B,0x2A,0x2B,0x5A,0x4A,0x83,0x80,0x00,

//"中", 12
			0x00,0xF8,0x08,0x08,0x08,0x08,0x08,0xFF,
      0x08,0x08,0x08,0x08,0x08,0xFC,0x08,0x00,
      0x00,0x03,0x01,0x01,0x01,0x01,0x01,0xFF,
      0x01,0x01,0x01,0x01,0x01,0x03,0x00,0x00,

//"快", 13
			0x80,0x70,0x00,0xFF,0x10,0x20,0x10,0x10,
      0xFF,0x10,0x10,0x10,0xF8,0x10,0x00,0x00,
      0x00,0x00,0x00,0xFF,0x82,0x42,0x22,0x1A,
      0x07,0x0A,0x12,0x22,0x43,0xC2,0x42,0x00,
			
//"关", 14
			0x00,0x10,0x10,0x11,0x12,0x1C,0x10,0xF0,
      0x10,0x18,0x14,0x13,0x1A,0x90,0x00,0x00,
      0x81,0x81,0x41,0x41,0x21,0x11,0x0D,0x03,
      0x0D,0x11,0x21,0x21,0x41,0xC1,0x41,0x00,
			
//"阈", 15
			0x00,0xFC,0x11,0xD2,0x50,0x52,0xD2,0x12,
      0xFE,0x12,0x16,0x9A,0x12,0xFF,0x02,0x00,
      0x00,0xFF,0x10,0x17,0x14,0x14,0x57,0x20,
      0x10,0x0F,0x12,0x39,0x80,0xFF,0x00,0x00,

//"值", 16
			0x80,0x40,0x20,0xF8,0x07,0x04,0xE4,0xA4,
      0xA4,0xBF,0xA4,0xA4,0xF6,0x24,0x00,0x00,
      0x00,0x00,0x00,0xFF,0x40,0x40,0x7F,0x4A,
      0x4A,0x4A,0x4A,0x4A,0x7F,0x40,0x40,0x00,
			
//"湿", 17
			0x10,0x22,0x64,0x0C,0x80,0xFE,0x92,0x92,
      0x92,0x92,0x92,0x92,0xFF,0x02,0x00,0x00,
      0x04,0x04,0xFE,0x41,0x44,0x48,0x50,0x7F,
      0x40,0x40,0x7F,0x50,0x48,0x64,0x40,0x00,
};

 

版权声明:本文为CSDN博主「醉痴璧」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ManJuSa/article/details/118105079

生成海报
点赞 0

醉痴璧

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

nodemcu 模块用mciropython 使用SD卡

使用sd卡可以扩大8266的存储器,使用时候很重要的是接线。 其他很容易。下面程序就是初始化、挂载sd卡、读sd卡里面main.cpp里面的代码行。 import machine, sdcard, os from machine

stm32f103rct6串口接收字符控制LED闪烁

最近在学单片机的串口,首先从串口发送接收开始吧,串口发送比较简单,下面讲讲串口接收字符串的情况。 单片机型号用的是 stm32f103rct6,IDE版本是keil 5。本代码是操作寄存器

MDK 分散加载文件剖析(一)

1、何为分散加载? 1.1 简介 分散加载就是我们开发者能指定你的 代码 或者 数据变量 到指定的内存空间中运行。通知链接器把程序的某一部分连接在存储器的某个地址空间,我们可以通过编写一个分散加载文件来指定 ARM