Skip to content

Latest commit

 

History

History
556 lines (529 loc) · 16.5 KB

暑假考核进度三.md

File metadata and controls

556 lines (529 loc) · 16.5 KB

当前作品进度:

基本功能各部分代码已完成,待整体进行调试

矩阵按键:

用于控制密码锁

u8 Array_KEY_Scan(u8 mode)
{	

	
	u8 KeyValue;
 

	if(!GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_3))
	{

	
		LED0 = 0;
		GPIO_ResetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
		if((GPIOF->IDR&0x00f0)!=0x0000 )
		{	
			delay_ms(2);
			if((GPIOF->IDR&0x00f0)!=0x0000)
			{
		
		
				switch(GPIOF->IDR&0x00f0)
				{
				
					case 0x0010:
					KeyValue = '0';break;
					case 0x0020:
					KeyValue = 'o';break;
					case 0x0040:
					KeyValue = 'r';break;
					case 0x0080:
					KeyValue = '*';break;
				}
				LED1= 0;
				while((GPIOF->IDR&0x00f0)!=0x0000);
				LED0 =1;
				LED1 = 1;
				return KeyValue;
			}
		}
	}
	else if(!GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_2))
	{ 
		

		GPIO_ResetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
		if((GPIOF->IDR&0x00f0)!=0x0000  )
		{	
			delay_ms(2);
			if((GPIOF->IDR&0x00f0)!=0x0000)
			{

				LED0 = 0;
				switch(GPIOF->IDR&0x00f0)
				{
				
					case 0x0010:
					KeyValue = '1';break;
					case 0x0020:
					KeyValue = '2';break;
					case 0x0040:
					KeyValue = '3';break;
					case 0x0080:
					KeyValue = 's';break;
				}
				while((GPIOF->IDR&0x00f0)!=0x0000);
				LED0 = 1;
				return KeyValue;
				}
			}
	}
	else if(!GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_1))
	{
	

		GPIO_ResetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
		if((GPIOF->IDR&0x00f0)!=0x0000  )
		{	
			delay_ms(2);
			if((GPIOF->IDR&0x00f0)!=0x0000)
			{

				LED1= 0;
				switch(GPIOF->IDR&0x00f0)
				{
				
					case 0x0010:
					KeyValue = '4';break;
					case 0x0020:
					KeyValue = '5';break;
					case 0x0040:
					KeyValue = '6';break;
					case 0x0080:
					KeyValue = '#';break;
				}
				while((GPIOF->IDR&0x00f0)!=0x0000);
				LED1 = 1;
				return KeyValue;
			}
		}
	}
	else if(!GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_0))
	{


		GPIO_ResetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
		if((GPIOF->IDR&0x00f0)!=0x0000  )
		{	
			delay_ms(2);
			if((GPIOF->IDR&0x00f0)!=0x0000)
			{
			  LED1 = 0;
				LED0 = 0;
				switch(GPIOF->IDR&0x00f0)
				{
				
					case 0x0010:
					KeyValue = '7';break;
					case 0x0020:
					KeyValue = '8';break;
					case 0x0040:
					KeyValue = '9';break;
					case 0x0080:
					KeyValue = '*';;break;
				}
				while((GPIOF->IDR&0x00f0)!=0x0000);
				LED0 = 1;
				LED1 = 1; 
				return KeyValue;
			}
		}
  }
	
	return 0;
}

电机:

用于控制窗帘和门锁

#include "motor.h"
#include "delay.h"
#include "stm32f10x.h"
#include "sys.h"
#include "stdlib.h"
#include "LED.h"
void MOTOR_Init()
{
		GPIO_InitTypeDef  GPIO_IN;
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);//ʹÄÜʱÖÓ£»
		GPIO_IN.GPIO_Mode = GPIO_Mode_Out_PP;//ÍÆÍìÊä³ö£»
		GPIO_IN.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_IN.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_4|GPIO_Pin_6|GPIO_Pin_8;
		GPIO_Init(GPIOG,&GPIO_IN);
}

void SteperFrontTurn(u16 speed)
{
	GPIO_SetBits(GPIOG,GPIO_Pin_2|GPIO_Pin_4);
	GPIO_ResetBits (GPIOG, GPIO_Pin_6|GPIO_Pin_8);
	delay_ms(speed);
	
	GPIO_SetBits(GPIOG,GPIO_Pin_6|GPIO_Pin_4);
	GPIO_ResetBits (GPIOG, GPIO_Pin_2|GPIO_Pin_8);
	delay_ms(speed);
	
	GPIO_SetBits(GPIOG,GPIO_Pin_6|GPIO_Pin_8);
	GPIO_ResetBits (GPIOG, GPIO_Pin_2|GPIO_Pin_4);
	delay_ms(speed);
	
	GPIO_SetBits(GPIOG,GPIO_Pin_2|GPIO_Pin_8);
	GPIO_ResetBits (GPIOG, GPIO_Pin_4|GPIO_Pin_6);
	delay_ms(speed);
	LED0 = 0;	
}

void SteperBackTurn(u16 speed)
{
	GPIO_SetBits(GPIOG,GPIO_Pin_2|GPIO_Pin_4);
	GPIO_ResetBits (GPIOG, GPIO_Pin_6|GPIO_Pin_8);
	delay_ms(speed);
	
	GPIO_SetBits(GPIOG,GPIO_Pin_2|GPIO_Pin_8);
	GPIO_ResetBits (GPIOG, GPIO_Pin_4|GPIO_Pin_6);
	delay_ms(speed);
	
	GPIO_SetBits(GPIOG,GPIO_Pin_6|GPIO_Pin_8);
	GPIO_ResetBits (GPIOG, GPIO_Pin_2|GPIO_Pin_4);
	delay_ms(speed);
	
	GPIO_SetBits(GPIOG,GPIO_Pin_6|GPIO_Pin_4);
	GPIO_ResetBits (GPIOG, GPIO_Pin_2|GPIO_Pin_8);
	delay_ms(speed);
}

void SteperStop()
{
	GPIO_ResetBits(GPIOG,GPIO_Pin_2|GPIO_Pin_4|GPIO_Pin_6|GPIO_Pin_8);
}

void SteperRun(u16 speed,int angle)
{
  float val,per_round,round =512;
	int i;
	per_round = round/360;
	val = per_round*abs(angle);
	if(angle>0)
	{
		
		for(i=0;i<val;i++)
		{
			SteperFrontTurn(speed);
			SteperStop();
		}
		
	}
	else
	{
			for(i=0;i<val;i++)
		{
			SteperBackTurn(speed);
			SteperStop();
		}
	}	
}

温湿度传感器

//原子哥的库
//DHT11是单总线传输数据,从mcu发出信号,DHT11响应
//RST:根据数据手册mcu先拉低,延时18ms,再拉高,延时20~40us,发出信号让DHT11发送数据
void DHT11_Rst(void) 
{                 
	  DHT11_IO_OUT(); 	//设置为输出
    DHT11_DQ_OUT=0; 	//输出0,拉低
    delay_ms(20);    	
    DHT11_DQ_OUT=1; 	
	delay_us(30);     	
}
//根据开发手册,DHT11在接收正常的时序是拉低信号,之后延时20~40us后拉高,保持40us~50us后发送数据,check()函数是用于检验dht11是否响应
u8 DHT11_Check(void) 	   
{   
	u8 retry=0;
	DHT11_IO_IN(); //进入输入模式,读取dht11信号
   while (DHT11_DQ_IN&&retry<100)//读取dht11信号,返回低电平则响应,否则retry++至超时
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
    while (!DHT11_DQ_IN&&retry<100)//等待高电平信号,超时未响应
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}
//读数据,一位一位读
//根据高电平持续时间不同,判断是0还是1
u8 DHT11_Read_Bit(void) 			 
{
 	u8 retry=0;
	while(DHT11_DQ_IN&&retry<100)//读取数据时dht11会先拉低信号
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_DQ_IN&&retry<100)//之后拉高,根据高电平时间判断数据
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);
	if(DHT11_DQ_IN)return 1;//如果40us后还是高电平,则读取为1
	else return 0;		   
}

u8 DHT11_Read_Byte(void)  //整合数据
{        
    u8 i,dat;
    dat=0;
	for (i=0;i<8;i++)//将数据一位一位存入dat
	{
   		dat<<=1; //左移一位添0
	    dat|=DHT11_Read_Bit();//读取数据,|按位与,只有都为0才为0
    }						    
    return dat;//返回读取的数据
}
//温湿度数据
//数据由5个字节组成,每个字节8bit,高位先出,依次是湿度的整数、小数,温度的整数、小数。最后一位为校验位,等于温湿度的整数小数之和
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
 	u8 buf[5];//用于存储五个字节
	u8 i;
	DHT11_Rst();//初始化
	if(DHT11_Check()==0)//接收响应
	{
		for(i=0;i<5;i++)
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])//校验
		{
			*humi=buf[0];//最先出的是湿度
			*temp=buf[2];//温度
		}
	}else return 1;//返回1无响应
	return 0;	    
}

//
u8 DHT11_Init(void)
{	 
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);//使能PG端时钟
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				 
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOG, &GPIO_InitStructure);				 
 	GPIO_SetBits(GPIOG,GPIO_Pin_11);						
			    
	DHT11_Rst();  //初始化,即muc发送激活信号
	return DHT11_Check();
} 

红外遥控

// 原子哥库
//红外遥控是通过接收脉宽不同的信号识别数据,需要开启输入捕获,用于计算高电平时间,并开启溢出中断,用于判断按键是否松开,以及连发码
void Remote_Init(void)    			  
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_ICInitTypeDef  TIM_ICInitStructure;  
 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;				
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 		
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
 	GPIO_SetBits(GPIOB,GPIO_Pin_9);	
	
						  
 	TIM_TimeBaseStructure.TIM_Period = 10000; 
	TIM_TimeBaseStructure.TIM_Prescaler =(72-1); 		   
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  

	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;  
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	
  TIM_ICInitStructure.TIM_ICFilter = 0x03;
  TIM_ICInit(TIM4, &TIM_ICInitStructure);

  TIM_Cmd(TIM4,ENABLE ); 	
 
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure); 

	TIM_ITConfig( TIM4,TIM_IT_Update|TIM_IT_CC4,ENABLE);,ÔÊÐíCC4IE²¶»ñÖÐÏ								 
}
//RmtSta用于存储遥控器状态
//[7]:最高位,接收到引导码(同步码)标志,接收到同步码,开启数据接收
//[6]: 数据接受完后标记
//[5]:保留
//[4]:上升沿捕获接收标志
//[3:0]:溢出计时器
u8 	RmtSta=0;	  	  
u16 Dval;	//存入计数器的值	
u32 RmtRec=0;//红外接收到的数据  		    
u8  RmtCnt=0;//按键按下的次数		  
//定时器4中断服务程序
void TIM4_IRQHandler(void)
{ 		    	 
 
	if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET)
	{
		if(RmtSta&0x80)	//数据接收标志位,即引导码是否接收到						
		{	
			RmtSta&=~0X10;		//取消上升沿捕获标记					
			if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;	//标记已完成依次按键的键值信息采集(即数据采集已完成)
			if((RmtSta&0X0F)<14)RmtSta++;//溢出标记,(使用溢出计算连发码时长)连发码多出99.5ms,小于等于130ms代表按键处于连发状态,小于14则计数器增加10ms,rmtsta低四位为计数器溢出存储。
			else//由于超过140ms,说明此时已停止按下按键(高电平持续时间)
			{
				RmtSta&=~(1<<7);	//清空引导标识				
				RmtSta&=0XF0;		//清空计数器				
			}								 	   	
		}							    
	}
    //捕获到上升沿后开始计数,通过上升沿和下降沿的计数差判断高电平时长
	if(TIM_GetITStatus(TIM4,TIM_IT_CC4)!=RESET)
	{	  
		if(RDATA)//捕获上升沿
		{
  			TIM_OC4PolarityConfig(TIM4,TIM_ICPolarity_Falling);//cc4P=1,设置为下降沿捕获						
			TIM_SetCounter(TIM4,0);	//清空定时器的值,重新计数						
			RmtSta|=0X10;//标记上升沿被捕获							
		}else 
		{
			Dval=TIM_GetCapture4(TIM4);	//读取CCR4清CC4IF标记位(即把计数器的值存入Dval)				
  			TIM_OC4PolarityConfig(TIM4,TIM_ICPolarity_Rising);//设置为上升沿捕获				
			if(RmtSta&0X10)	//标记高电平捕获完成标志						
			{
 				if(RmtSta&0X80)//判断是否接受了引导码,没有则要接收,有了则开始接收数据
				{
					//根据高电平时长判断信号
					if(Dval>300&&Dval<800)	//接收到0		
					{
						RmtRec<<=1;					
						RmtRec|=0;						   
					}else if(Dval>1400&&Dval<1800)	//接收到1
					{
						RmtRec<<=1;					.
						RmtRec|=1;					
					}else if(Dval>2200&&Dval<2600)	//接收到连发码
					{
						RmtCnt++; 					
						RmtSta&=0XF0;					
					}
 				}else if(Dval>4200&&Dval<4700)//没有接收到引导码,接收引导码		
				{
					RmtSta|=1<<7;				
					RmtCnt=0;						
				}						 
			}
			RmtSta&=~(1<<4);//清除上升沿捕获标志
		}				 		     	    					   
	}
	TIM_ClearITPendingBit(TIM4,TIM_IT_Update|TIM_IT_CC4);//清除定时器标记	 	    
}

//处理按键数据
//0为没有按下
//数据由同步码、地址码、地址反码、控制码、控制反码组成,一共5字节
u8 Remote_Scan(void)
{        
	u8 sta=0;       
    u8 t1,t2;  //(u8 代表8bit)
	if(RmtSta&(1<<6))//得到一个按键的所有信息了
	{ 
	    t1=RmtRec>>24;//右移24位:得到8bit地址码			
	    t2=(RmtRec>>16)&0xff;	//右移16位地址反码
 	    if((t1==(u8)~t2)&&t1==REMOTE_ID)//校验遥控识别码ID及地址(验证地址与地址反码是否相等)
	    { 
	        t1=RmtRec>>8;//得到控制码
	        t2=RmtRec; 	//控制反码
	        if(t1==(u8)~t2)sta=t1; //验证
		}   
		if((sta==0)||((RmtSta&0X80)==0))//按键数据错误/遥控没有按下
		{
		 	RmtSta&=~(1<<6);//清除数据接收标记位
			RmtCnt=0;	//清除计数器的值	
		}
	}  
    return sta;//返回数据
}

连接wifi,连接tcp服务器

通过AT指令进行连接

#include "common.h"
#include "stdlib.h"
u8 wifi_sta_connect()
{

  atk_8266_send_cmd("AT+CWMODE=1","OK",50);
  atk_8266_send_cmd("AT+RST","OK",20);//ÖØÆô
	delay_ms(1000);
	delay_ms(1000);
	delay_ms(1000);
	printf("AT RST success\r\n");
 
	if(atk_8266_send_cmd("AT+CWJAP=wifista_ssid,wifista_password","WIFI GOT IP",300))
	{
	   printf("wifi is connecting...\r\n");
		 delay_ms(1000);
		 delay_ms(1000);
		  
	} 
  atk_8266_send_cmd("AT+CIPMUX=0","OK",20);
  printf("end...\r\n");

  atk_8266_send_cmd("AT+CIPSTART=\"TCP\",\"192.168.43.1\",8086","OK",200);
	printf("connect success\r\n");

	atk_8266_send_cmd("AT+CIPMODE=1","OK",200);
	atk_8266_quit_trans();

	atk_8266_send_cmd("AT+CIPSEND","OK",20);
  atk_8266_send_cmd("AT+ATKCLDSTA=\"28278526856927122889\",\"12345678\"","OK",300);
	
	printf("end...");
	
 return 0;
}

OLED中文显示:

image-20200906225049399

oled 显示图片还在调试中

目前进度:

各部分代码完成,需要合并成完整系统,

目前存在问题:1.按键按下反应不灵敏,导致密码锁没完成

​ 2.返回的温湿度以16进制显示在服务器上。

有待改进部分;引入光敏电阻做成自动窗帘

未完成:空调显示(正在制作)

感悟:

通过本次暑假考核,我对单片机理解加深了,单片机出了如何使用模块,IO口,最重要的通讯,即与各模块的通讯,与其他单片机的通讯,目前使用到的通讯由:同步异步通信(串口通讯),单总线,spi通讯等。各种通讯方式各有不同,单总线只用一条数据线收发数据,双方要通讯,需要分时间,即一方发送信号告知另一个发送数据。串口通讯由于没有双方没有规定时序,但双方约定波特率,保证通讯。spi通讯由于有了时钟线,双方通讯建立在时钟时序上。再来是数据处理:由于电路只有高电平和低电平两种状态,所以数据本质上二进制数据,一般以字节为单位,即8bit,8bit刚好是无符号char类型数据,8bit也是16进制数。在读取数据一般会使用到位运算。&、|、~,&一般用于判断位,|一般用于存入一位bit,~一用于取反。数据类型、数据存入对于单片机的数据处理是必要技能。单片机的通讯是通过严格数据(既有特定数据用于标记接收和发送、检验等),以及双方规定波特率、时序等完成。最后就算io的操作,通过设置高低电平实现读入写入时序。

PS:目前有些部分不是很清晰