微型家庭中控STM32+C#上位机_(STM32部分)

今日尝试开发一款简单好学的 C8T6+C#_Winform上位机 的微型家庭中控设备的 小试验品:

这个设备将成为我毕设系统的一个小部分......

主要开发环境与工具介绍:

单片机 STM32F103C8T6 使用标准库函数编程

Visual Studio 2022软件 C# Winform 开发 上位机控制软件
本文主要描述一下STM32部分的实现......

STM32部分主要实现:

监控温度湿度,查看时间日期,开灯,开门,报警,串口回传信息给上位机等功能

文章提供完整代码解释、设计点解释、测试效果图、完整工程下载

目录

STM32F103C8T6单片机部分:

使用模块与接线:

硬件实物连接图:

代码编程主要逻辑:

STM32部分功能单独展示:

STM32串口发送部分:

STM32部分整体工程下载:


STM32F103C8T6单片机部分:

这部分就用简单的while(1)主循环加定时器中断的前后台逻辑裸机程序就能很好胜任了,

不需要什么都上操作系统(耗电)......

使用模块与接线:

使用以下传感器与显示器(包含接线):

AHT10 温湿度传感器 :

SCL: PB3

SDA: PB4

OLED显示器:

SCL: PB6

SDA: PB7

Beep蜂鸣器 : PA0

LED 灯 : PA1

舵机 : PA6

按键KEY1 : PA2

按键KEY2 : PB15

**按键KEY3 :**PB14

按键KEY4 : PB13

最后还有个稳压降压模块

硬件实物连接图:

直接飞线连连得了......

代码编程主要逻辑:

灯、蜂鸣器、按键的引脚初始化都只需要初始化为输入输出引脚即可

cpp 复制代码
#include "headfire.h"

//蜂鸣器、灯、按键 初始化
void Beep_LED_KEY_init(void)
{
		/*定义一个GPIO_InitTypeDef类型的结构体*/
		GPIO_InitTypeDef GPIO_InitStructure;		
		/*开启LED相关的GPIO外设时钟*/
		RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,ENABLE);
		/*开启LED相关的GPIO外设时钟*/
		RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,ENABLE);		
		
		/*选择要控制的GPIO引脚*/
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;	
		/*设置引脚模式为通用推挽输出*/
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
		/*设置引脚速率为50MHz */   
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
		/*调用库函数,初始化GPIO*/
		GPIO_Init(GPIOA	, &GPIO_InitStructure);
	
		/*选择要控制的GPIO引脚*/
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	
		/*设置引脚模式为通用推挽输出*/
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
		/*设置引脚速率为50MHz */   
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
		/*调用库函数,初始化GPIO*/
		GPIO_Init(GPIOA	, &GPIO_InitStructure);

    // 配置PA2为输入模式,无上拉/下拉  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入,你也可以选择GPIO_Mode_IPU(内部上拉)或GPIO_Mode_IPD(内部下拉)  
    GPIO_Init(GPIOA, &GPIO_InitStructure);  
  
    // 配置GPIOB13为输入模式,这里以内部上拉为例  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 内部上拉输入  
    GPIO_Init(GPIOB, &GPIO_InitStructure);  
  
    // 类似地配置GPIOB14和GPIOB15  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;  
    GPIO_Init(GPIOB, &GPIO_InitStructure); // 保持之前的模式设置(内部上拉)  
  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;  
    GPIO_Init(GPIOB, &GPIO_InitStructure); // 保持之前的模式设置(内部上拉)  
	
}




//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下

//4,KEY3按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY3!!
u8 KEY_Scan(u8 mode)
{	 
	static u8 key_up=1;//按键按松开标志
	if(mode)key_up=1;  //支持连按		  
	if(key_up&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))
	{
		delay_ms(10);//去抖动 
		key_up=0;
		if(KEY1==0)return KEY1_PRES;
		else if(KEY2==0)return KEY2_PRES;
		else if(KEY3==0)return KEY3_PRES;
		else if(KEY4==0)return KEY4_PRES;
	}else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)key_up=1; 	    
 	return 0;// 无按键按下
}
cpp 复制代码
void Beep_LED_KEY_init(void);

/* 使用标准的固件库控制IO*/
#define LED(a)	if (a)	\
					GPIO_SetBits(GPIOA, GPIO_Pin_1);\
					else		\
					GPIO_ResetBits(GPIOA, GPIO_Pin_1)
/* 使用标准的固件库控制IO*/
#define Beep(a)	if (a)	\
					GPIO_SetBits(GPIOA, GPIO_Pin_0);\
					else		\
					GPIO_ResetBits(GPIOA, GPIO_Pin_0)

					
//#define KEY1 PAin(2)  //PA2
//#define KEY2 PBin(15)	//PB15 
//#define KEY3 PBin(14)	//PB14
//#define KEY4 PBin(13)	//PB13  
					
#define KEY1  GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)  //读取按键1
#define KEY2  GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15) //读取按键2
#define KEY3  GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14) //读取按键3 
#define KEY4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13) //读取按键4 

 
#define KEY1_PRES 	1	//KEY1按下
#define KEY2_PRES	  2	//KEY2按下
#define KEY3_PRES	  3	//KEY3按下
#define KEY4_PRES   4	//KEY4按下

u8 KEY_Scan(u8 mode);
					
					
#endif

主函数用各种标志位等刷新OLED、按键操作等,定时器实时刷新一些数据或OLED图片...

cpp 复制代码
#include "main.h"

float temp;
u8 hum;
int humm,temper;
uint16_t AHT10_cnt,AHT10_flag;
char buf[30];
uint16_t AHT10_cnt,AHT10_flag;
char buf[30];
//刷新时间标志
uint16_t TimeDisplay_cnt,TimeDisplay,BMP_Display;
u8 display;                    //切换OLED显示内容用(0:温湿度  1:时间)
u8 KEY_value;
int age=21;
u8 door_state=0;  //门状态
u8 oled_state=0;  //显示状态
u8 led_state=0;   //灯状态
u8 Beep_state=0;  //报警状态
u8 Beep_s=0;       //报警状态
u8 Beep_cnt=0;


int main(void)
{	
	init_ALL();     //初始化所有函数
  while(1)
	{	
		KEY_value=KEY_Scan(0);
		
		switch(KEY_value)
		{
			case 0:	break;
			case KEY1_PRES:	led_state++;
											if(led_state%2==1)  {	LED(1);}
											if(led_state%2==0)	{	LED(0);}
											if(led_state == 16) {led_state=2;} //防止数据异常
											break;
			case KEY2_PRES: Beep_state++;
											if(Beep_state%2==0) {	Beep_s=1;}
											if(Beep_state%2==1)	{	Beep_s=0;}
											if(Beep_state == 16) {Beep_state=2;} //防止数据异常											
											break;
			case KEY3_PRES: oled_state++;
											if(oled_state%2==0) {	OLED_Clear();Beep(1);display=1;}
											if(oled_state%2==1)	{	OLED_Clear();Beep(1);display=0;}											
											if(oled_state == 16) {oled_state=2;} //防止数据异常
											break;			
			case KEY4_PRES:	door_state++;
											if(door_state%2==0) {Beep(1);TIM_SetCompare1(TIM3,60); }
											if(door_state%2==1)	{Beep(1);TIM_SetCompare1(TIM3,260);}
											if(door_state == 16) {door_state=2;} //防止数据异常
											break;
		}
			if(Beep_s==1)
				{
					Beep(1);
				}
				else if(Beep_s==0)
				{
					Beep(0);			
				}
		if(AHT10_flag==1 && display==0)
		{
			AHT10_flag=0;
			AHT10ReadData(&temp,&hum);
			temper=temp*10;
			humm=hum;
			OLED_ShowCHinese(0,0,0);  //打印中文"温"
			OLED_ShowCHinese(16,0,2);  //打印中文"度"
		  sprintf(buf,": %d.%d",temper/10,temper%10);		
 		  OLED_ShowString(32,0,(u8 *)buf,16);	   
			
			OLED_ShowCHinese(0,2,1);  //打印中文"湿"
			OLED_ShowCHinese(16,2,2);  //打印中文"度"
		  sprintf(buf,": %d ",humm);		
 		  OLED_ShowString(32,2,(u8 *)buf,16);	     

			//打印班级姓名
			sprintf(buf,"%d ", age);	
 		  OLED_ShowString(0,5,(u8 *)buf,16);
			OLED_ShowCHinese(16,5,6);   //打印中文"通"			
			OLED_ShowCHinese(32,5,7);   //打印中文"信"		
			OLED_ShowCHinese(48,5,8);   //打印中文"杨"					
			OLED_ShowCHinese(64,5,9);   //打印中文"志"		
			OLED_ShowCHinese(80,5,10);  //打印中文"豪"		
		}
		
		else if(TimeDisplay==1 && display==1)
		{
			Time_Display(RTC_GetCounter(),&time1);
			TimeDisplay=0;
			
		}
		
		if(BMP_Display==1 && display==1)
		{
			switch(BMP_FLAG)
			{
			case 1:OLED_DrawBMP(0,0,64,8,BMP1);  break;
			case 2:OLED_DrawBMP(0,0,64,8,BMP2);  break;
			case 3:OLED_DrawBMP(0,0,64,8,BMP3);  break;
			case 4:OLED_DrawBMP(0,0,64,8,BMP4);  break;
			case 5:OLED_DrawBMP(0,0,64,8,BMP5);  break;
			case 6:OLED_DrawBMP(0,0,64,8,BMP6);  break;
			case 7:OLED_DrawBMP(0,0,64,8,BMP7);  break;
			case 8:OLED_DrawBMP(0,0,64,8,BMP8);  break;
			case 9:OLED_DrawBMP(0,0,64,8,BMP9);  break;
			case 10:OLED_DrawBMP(0,0,64,8,BMP10);  break;
			
			case 11:OLED_DrawBMP(0,0,64,8,BMP11);  break;
			case 12:OLED_DrawBMP(0,0,64,8,BMP12);  break;
			case 13:OLED_DrawBMP(0,0,64,8,BMP13);  break;
			case 14:OLED_DrawBMP(0,0,64,8,BMP14);  break;
			case 15:OLED_DrawBMP(0,0,64,8,BMP15);  break;
				
//flash不够了,只能注释掉这些内存
//			case 16:OLED_DrawBMP(0,0,64,8,BMP16);  break;
//			case 17:OLED_DrawBMP(0,0,64,8,BMP17);  break;
//			case 18:OLED_DrawBMP(0,0,64,8,BMP18);  break;
//			case 19:OLED_DrawBMP(0,0,64,8,BMP19);  break;
//			case 20:OLED_DrawBMP(0,0,64,8,BMP20);  break;		

//			case 21:OLED_DrawBMP(0,0,64,8,BMP21);  break;
//			case 22:OLED_DrawBMP(0,0,64,8,BMP22);  break;
//			case 23:OLED_DrawBMP(0,0,64,8,BMP23);  break;
//			case 24:OLED_DrawBMP(0,0,64,8,BMP24);  break;
//			case 25:OLED_DrawBMP(0,0,64,8,BMP25);  break;
//			case 26:OLED_DrawBMP(0,0,64,8,BMP26);  break;
//			case 27:OLED_DrawBMP(0,0,64,8,BMP27);  break;
//			case 28:OLED_DrawBMP(0,0,64,8,BMP28);  break;
		}
		BMP_Display=0;
		}
		
		
	}
}


//初始化所有函数:
void init_ALL(void)
{
	SysTick_Init(72);         //初始化滴答计时器
	Timer2_Init();						//初始化定时器2
	i2c_GPIO_Config();	      //IIC初始化
	OLED_Init();              //初始化OLED屏幕
	OLED_Clear();             //清空屏幕数据
	AHT10Init();              //初始化温湿度传感器
	Timer3_PWM_init(2000,719);//初始化定时器3
	Beep_LED_KEY_init();      //蜂鸣器、灯、按键 初始化
	RTC_init();
	
	LED(1);
	Beep(1);
	delay_ms(50);
	LED(0);
	Beep(0);
	TIM_SetCompare1(TIM3,60);//150是90度
	
	display=1;
}


//定时器2中断服务函数
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{		
		if(++AHT10_cnt==30)         //每300ms刷新一次温湿度数据
		{AHT10_cnt=0;AHT10_flag=1;}
				if(++TimeDisplay_cnt==10)  //每100ms定时器刷新时间
		{
			TimeDisplay_cnt=0;TimeDisplay=1;
		}
		
		if(++BMP_cnt==5)		        //定时器50ms刷新太空人图片
		{
			BMP_cnt=0;
			BMP_FLAG++;
			BMP_Display=1;
			if(BMP_FLAG==15){BMP_FLAG=1;}
		}
		
		if(++Beep_cnt==12)
		{		
				Beep(0);	
				Beep_cnt=0;
		}
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清出中断寄存器标志位,用于退出中断
	}
}


//RTC每秒进的中断服务函数
void RTC_IRQHandler(void)
{
	  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
	  {
	    /* Clear the RTC Second interrupt */
	    RTC_ClearITPendingBit(RTC_IT_SEC);
	
//	    /* Enable time update */
//	    TimeDisplay = 1;
//	
	    /* Wait until last write operation on RTC registers has finished */
	    RTC_WaitForLastTask();
	  }
}

STM32部分功能单独展示:

KEY1 开关灯

KEY2 报警

KEY3 切换界面显示(时间界面、温湿度界面)

KEY4 驱动舵机模拟开关门

微型家庭中控设备STM32部分功能单独展示

STM32串口发送部分:

这部分的发送逻辑不是简单的发送数据就行了,这是与上位机相配合的数据包格式的发送,目前暂时不添加这个功能,等上位机写好后再编写串口回传数据的功能

STM32部分整体工程下载:

https://download.csdn.net/download/qq_64257614/89628888

相关推荐
iCxhust30 分钟前
Keil µVision 调试指南---UART#1 模拟/调试窗口 完全使用教程
stm32·单片机·嵌入式硬件
iCxhust31 分钟前
51单片机引脚 ALE EA PSEN的用途
单片机·嵌入式硬件·51单片机
碎像36 分钟前
51单片机创建项目
单片机·嵌入式硬件·51单片机
木白CPP41 分钟前
MCU 进程内存布局详解(.text, .rodata, .data, .bss, 堆, 栈)
单片机·嵌入式硬件
Lugas Luo1 小时前
车载录像存储性能模拟测试工具设计
linux·嵌入式硬件·测试工具
v132665623681 小时前
BK7258 wifi6音视频soc芯片应用分析
嵌入式硬件·物联网·音视频·iot·wifi6
風清掦1 小时前
【江科大STM32学习笔记-10】I2C通信协议 - 10.2 硬件 I2C 读写MPU6050
笔记·stm32·单片机·嵌入式硬件·学习
ALINX技术博客2 小时前
【黑金云课堂】FPGA技术教程Vitis开发:RTC中断讲解
单片机·嵌入式硬件·fpga开发
进击的小头2 小时前
第10篇:嵌入式芯片中断系统详解:NVIC与硬实时性优化设计
单片机·嵌入式硬件
天狼IoT2 小时前
STM32-keil+CubeMX快速开发【外设配置篇】:NVIC与中断通用处理方法
stm32·单片机·嵌入式硬件