您的位置:首页 > 新闻 > 热点要闻 > 微型家庭中控STM32+C#上位机_(STM32部分)

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

2025/5/24 11:49:32 来源:https://blog.csdn.net/qq_64257614/article/details/140999496  浏览:    关键词:微型家庭中控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

最后还有个稳压降压模块

硬件实物连接图:

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

代码编程主要逻辑:

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

#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;// 无按键按下
}
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图片...

#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();						//初始化定时器2i2c_GPIO_Config();	      //IIC初始化OLED_Init();              //初始化OLED屏幕OLED_Clear();             //清空屏幕数据AHT10Init();              //初始化温湿度传感器Timer3_PWM_init(2000,719);//初始化定时器3Beep_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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com