STM32单片机HAL库开发指南

内部资源的处理

GPIO的处理

//输出
#define LED(a) (a?HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET):HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET)) 
#define BEEP(a) (a?HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_SET):HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET)) 

#define RELAY(a) (a?HAL_GPIO_WritePin(RELAY_GPIO_Port, RELAY_Pin, GPIO_PIN_SET):HAL_GPIO_WritePin(RELAY_GPIO_Port, RELAY_Pin, GPIO_PIN_RESET)) 
//输入
#define IR_IN HAL_GPIO_ReadPin(IR_IN_GPIO_Port,IR_IN_Pin)
#define FRI HAL_GPIO_ReadPin(FRI_GPIO_Port,FRI_Pin)

定时器的使用

uint16_t time_1ms,time_500ms;         //计时变量1ms,500ms

HAL_TIM_Base_Start_IT(&htim1);  //定时器中断开始初始化

//定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == htim1.Instance)		//定时器1触发中断
	{
		time_1ms++;
		if(time_1ms>= 500)
		{
			time_1ms= 0;
			time_500ms = 1;
		}
	}
}


串口的数据获取与发送

//串口的数据获取
uint8_t USART1_TX_BUF[200];
#define u1_printf(...)  HAL_UART_Transmit(&huart1,USART1_TX_BUF,sprintf((char *)USART1_TX_BUF,__VA_ARGS__),0xffff)
                                                                                                                                                                      
uint8_t USART2_TX_BUF[200];
#define u2_printf(...)  HAL_UART_Transmit(&huart2,USART2_TX_BUF,sprintf((char *)USART2_TX_BUF,__VA_ARGS__),0xffff)
  

uint8_t USART3_TX_BUF[200];
#define u3_printf(...)  HAL_UART_Transmit(&huart3,USART3_TX_BUF,sprintf((char *)USART3_TX_BUF,__VA_ARGS__),0xffff)

//串口2的数据获取
uint8_t uart2_value;      //串口传的单个数据
//串口的储存数组,串口的接收时间,串口存值的数量
uint8_t uart2_buf[36],uart2_time,uart2_num;
uint8_t uart2_rx_flag;//串口的获取值的标志位


//定时器中串口处理过程
if(uart2_num != 0) //串口接收到数据传来
		{
			uart2_time++;       //计时开始
			if(uart2_time >= 10)//一帧数据接受完成
			{
        //将标志位清零
				uart2_time = 0;   
				uart2_num = 0;
        //接收标志位置1
				uart2_rx_flag = 1;
			}
		}

//串口回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == huart2.Instance)//串口2触发中断
	{
    //获取串口2的数据,uart2_value
		HAL_UART_Receive_IT(&huart2, &uart2_value, 1);
    //将数据存储到uart2_buf中
		uart2_buf[uart2_num++] = uart2_value;
		uart2_time = 0;
	}

}



adc的数据获取

uint16_t adc_value,light_value;
//单通道数据获取
   HAL_ADC_Start(&hadc1);
		if(HAL_ADC_PollForConversion(&hadc1, 999) == HAL_OK)
			adc_value = HAL_ADC_GetValue(&hadc1);
		HAL_ADC_Stop(&hadc1);
		light_value = (adc_value/4096.0)*100;			//获取值
  
//多通道数据获取
uint8_t adc_ch;   //adc的个数
uint32_t adc_buf[3];//adc数值的存储数组

/*******************
    作者:特纳斯电子
    网站:https://www.mcude.com
    联系方式:46580829(QQ)
    淘宝店铺:特纳斯电子
  * 函数功能: 一次完整的ADC数据传输
  * 输入参数: 无
  * 返 回 值: adc的数值存储区域adc_buf[]
  * 说    明:adc_buf uint32_t;
  *****************************/
uint16_t dong_get_adc(){
    //开启ADC1
  HAL_ADC_Start(&hadc1);
    //等待ADC转换完成,超时为100ms
    HAL_ADC_PollForConversion(&hadc1,100);
    //判断ADC是否转换成功
    if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC)){
         //读取值
       return HAL_ADC_GetValue(&hadc1);
    }
    return 0;
}


//将获取的值存储到adc_buf中
		for(adc_ch=0;adc_ch<3;adc_ch++){
    //分别存放通道1、2、3的ADC值
    adc_buf[adc_ch]=dong_get_adc();
		}
  
  
  
  //浊度传感器
      deep=adc_buf[1]/4095.00*5;             //获取电压值
    deep = deep-0.0192*(temp/10.0 - 25.0);   //进行温度补偿
    deep = -865.68*deep+3680;                //计算浊度值 
    

   //PM2.5传感器
   
   #define P_LED(a) (a?HAL_GPIO_WritePin(P_LED_GPIO_Port, P_LED_Pin, GPIO_PIN_SET):HAL_GPIO_WritePin(P_LED_GPIO_Port, P_LED_Pin, GPIO_PIN_RESET)) 

    P_LED(0);        //打开灯光  
    delay_us(280);  //延时280us
    //ADC检测
    delay_us(40);  //延时40us
    P_LED(1);      //关灯
    
    PM2_5 = ((adc_buf[0]*3.3/4096.0)*1000)/12;
  
    
  

外部中断

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == PUSH_Pin)
	{
		push_value++;
	}
}

外设驱动

氧气检测

uint16_t O2_value;     //氧气变量

if(uart1_rx_flag == 1)
  {
    uart1_rx_flag = 0;	
    O2_value = uart1_buf[4]*256 + uart1_buf[5];	//读取氧气值
  }
  
  //氧气初始化配置
  u1_printf("%c%c%c%c%c%c%c%c%c",0xFF,0x01,0x03,0x01,0x00,0x00,0x00,0x00,0x04);

舵机控制

//pwm控制
uint16_t SG90_angle=500;      //舵机角度控制变量(500-2500 0-180°)

HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);       //定时器3pwm初始化

__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,SG90_angle);    //舵机的角度控制

Zigbee 的配置与数据收发(亿百特)

//主机
//配置zigbee
ev_type: 
00 协调器
01 路由器
02 终端(默认)


u2_printf("%c%c%c%c%c", 0xFD, 0x02, 0x01, 0x00, 0xFF);		//设置zigbee为协调器

/*******从机*****/
//ZIGBEE的发送包头,以广播形式发送
uint8_t Zigbee_Head[4] = {0xFC,0X00,0X01,0X02};
//Zigbee的发送数据
uint8_t Zigbee_Data[20];
//发送的位数
uint8_t Zigbee_num;
//Zigbee发送的数据长度
uint8_t Data_Leng = 6;

/*******************
    作者:特纳斯电子
    网站:https://www.mcude.com
    联系方式:46580829(QQ)
    淘宝店铺:特纳斯电子
  * 函数功能: Zigbee发送包头,广播形式发送
  * 输入参数: 发送数据的长度
  * 返 回 值: 无
  * 说    明:无
  **************/
void Zigbee_Send_Head(uint8_t Data_Len)
{
	uint8_t i;
  //改变Zigbee_Head数组中[1]的数,确认发送长度
	Zigbee_Head[1] = Data_Len += 2;
  //for循环依次发出
	for(i=0;i<4;i++)
		u2_printf("%c", Zigbee_Head[i]);  //串口2发送字符
}


//发送字符放入待发送数组中
    Zigbee_Data[0]=0xA1;
		Zigbee_Data[1]=NUM/100%10;
		Zigbee_Data[2]=NUM/10%10;
		Zigbee_Data[3]=NUM/1%10;
		Zigbee_Data[4]=NUM/10%10;
		Zigbee_Data[5]=NUM/1%10;
    //发送报头数据
		Zigbee_Send_Head(Data_Leng);
    //循环发送数组的数据
		for(Zigbee_num=0; Zigbee_num<Data_Leng; Zigbee_num++)
    u2_printf("%c", Zigbee_Data[Zigbee_num]);//以字符发送

ADX345-角度传感器


Init_ADXL345();				//ADXL345初始化

uint16_t BuShu;				//步数变量
uint8_t BuShu_flag;			//步数标志位

ReadData_XYZ();				//读取角度值

/* 步数计算  一般500ms检测一次*/
    if(temp_Y>300 && BuShu_flag==0)
      BuShu_flag = 1;
    
    if(temp_Y<-300 && BuShu_flag==1)
    {
      BuShu_flag = 0;
      BuShu++;
    }

28BYJ-48-步进电机

uint8_t Motor_Status;											//步进电机状态变量
uint16_t Motor_Num;												//步进电机计数变量
uint16_t Motor_Time;											//步进电机计时变量
uint8_t const Motor_Buf[8] = {0x01, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08, 0x09};//步进电机步数数组

//1ms定时器中
if(Motor_Status & 0x80)						//步进电机转动
		{
			if(Motor_Status & 0x01)
				Motor_Num++;
			else
				Motor_Num--;
			if(Motor_Num >= 256*8)
			{
				Motor_Status &= ~0x80;
				Motor_Time = 0;
				if(Motor_Status&0x01)					//开门后,延时关门
					Motor_Status |= 0x40;
			}
   //第一种写法
			GPIOB->ODR &= 0xff0f;           //引脚状态
			GPIOB->ODR |= Motor_Buf[Motor_Num%8] << 4;
   //第二种写法
                        GPIOB->ODR &= 0xffc7;
			GPIOA->ODR &= 0x7fff;
			
			if(Motor_Buf[Motor_Num%8] & 0x01)
				GPIOB->ODR |= 1<<5;
			if(Motor_Buf[Motor_Num%8] & 0x02)
				GPIOB->ODR |= 1<<4;
			if(Motor_Buf[Motor_Num%8] & 0x04)
				GPIOB->ODR |= 1<<3;
			if(Motor_Buf[Motor_Num%8] & 0x08)
				GPIOA->ODR |= 1<<15;
		}
  
  if((Motor_Status & 0x01) == 0x00 )	//若门为关闭状态,步进电机开门
				{		
					Motor_Status |= 0x81;

				}

if(Motor_Status & 0x40 )
				{

					Motor_Status &= ~0x41;
					Motor_Status |= 0x80;
				}
    
    
    if(Motor_Status & 0x80)						//步进电机转动
		{
			if(Motor_Status & 0x01)
				Motor_Num++;
			else
			{
				if(IR)
				{

					Motor_Status |= 0x01;
					Motor_Status |= 0x40;
				}
				Motor_Num--;
			}
				
			if(Motor_Num >= 256*8)
			{
				Motor_Status &= ~0x80;
				Motor_Time = 0;
				if(Motor_Status&0x01)					//开门后,延时关门
					Motor_Status |= 0x40;
			}
			GPIOB->ODR &= 0xff0f;
			GPIOB->ODR |= Motor_Buf[Motor_Num%8] << 4;
		}
		
		if((Motor_Status & 0x40))//延时关门(红外触发后通过该程序延时关门)
		{
			Motor_Time++;
			if(Motor_Time >= 3000)
			{
				Motor_Time = 0;
				Motor_Status |= 0x80;
				Motor_Status &= ~0x41;
			}
		}
  

GSM-SIM900A(SIM800C)

uint8_t GSM_Send_bz;    //发送标志位
uint16_t GSM_time;			//每隔500ms发送一条
uint8_t Phone_Number[11]="18016242114";//接收手机号
uint8_t Message[50];     //发送数据存储
uint8_t GSM_flag;       //发送标志

void GSM_Send(uint8_t *Message)
{
		if(GSM_Send_bz==1)
		{
      if(GSM_flag==0)
      {
        GSM_flag=1;
        u3_printf("AT+CMGF=1\r\n");					//设置短息格式为文本模式
      }
		}
		else if(GSM_Send_bz==2)
		{
      if(GSM_flag==0)
      {
        GSM_flag=1;
        u3_printf("AT+CSMP=17,167,2,25\r\n");					//设置短消息文本模式
      }
		}
		else if(GSM_Send_bz == 3)
		{
      if(GSM_flag==0)
      {
        GSM_flag=1;
        u3_printf("AT+CSCS=\"UCS2\"\r\n");		//选择TE字符集
      }
		}
		else if(GSM_Send_bz == 4)
		{
      if(GSM_flag==0)
      {
        GSM_flag=1;
        u3_printf("AT+CMGS=\"003%c003%c003%c003%c003%c003%c003%c003%c003%c003%c003%c\"\r\n", \
                    Phone_Number[0],Phone_Number[1],Phone_Number[2],\
                    Phone_Number[3],Phone_Number[4],Phone_Number[5],\
                    Phone_Number[6],Phone_Number[7],Phone_Number[8],\
                    Phone_Number[9],Phone_Number[10]);//此处修改为对方的电话号
      }
		}
		else if(GSM_Send_bz == 5)
		{
      if(GSM_flag==0)
      {
        GSM_flag=1;
        u3_printf("%s",Message);	//发送文本
        u3_printf("%c",0x1A);     //结束符
      }
		}
}

GSM_Send(Message);

//1ms定时器中
if(GSM_Send_bz > 0) {GSM_time++;}
		if(GSM_time >= 500)
		{
			/* GSM向手机发送报警 */
			GSM_flag=0;
			GSM_time=0;
			GSM_Send_bz++;
			if(GSM_Send_bz >= 6)                   //中文
				GSM_Send_bz = 0;
		}
  
  sprintf((char *)Message,"%s","4E2D56FD60A8597D");
       GSM_Send_bz=1;

GPS

char *Start,*End;
char latitude_buf[20];
char longitude_buf[20];


/****
*******GPS
*****/
void GPS_function(void)
{
	char i;
	memset(latitude_buf,'-',7);
	memset(longitude_buf,'-',7);
	Start = strstr((char *)uart2_buf, "GLL");
	if(Start != NULL)
	{
		Start = strstr(Start, ",") + 1;        //获取纬度数据首地址
		if(*(Start) != ',')                                                //判断是否获取到经纬度数据
		{
			Start++;                                                                                        //纬度数据首地址
			End = strstr(Start, ",");                        //获取纬度数据尾地址
			for(i=0; i<End - Start; i++)
			{
				latitude_buf[i+1] = *(Start + i-1);        //将纬度数据存放在数组中
				if(*(Start + i-1) == '.')
				{
					latitude_buf[i+1] = latitude_buf[i];
					latitude_buf[i] = latitude_buf[i-1];
					latitude_buf[i-1] = '.';
				}
			}
			Start = strstr(Start, ",") + 1;        //获取南纬或北纬数据
			if(*Start=='N' || *Start=='S')
				latitude_buf[0] = *Start;                        //将数据存放在纬度数组

			Start = strstr(Start, ",") + 1;        //获取经度数据首地址
			End = strstr(Start, ",");                                //获取经度数据尾地址
			for(i=0; i<End - Start; i++)
			{
				longitude_buf[i+1] = *(Start + i);        //将经度数据存放在数组中
				if(*(Start + i) == '.')
				{
					longitude_buf[i+1] = longitude_buf[i];
					longitude_buf[i] = longitude_buf[i-1];
					longitude_buf[i-1] = '.';
				}
			}
			Start = strstr(Start, ",") + 1;        //获取东经或西经数据
			if(*Start=='E' || *Start=='W')
			longitude_buf[0] = *Start;                //将数据存放在经度数组中

			latitude_buf[7] = '\0';                        //只让经度和纬度显示十个字符
			longitude_buf[7] = '\0';

//			lat = atof((char *)latitude_buf+1);                //字符串转换为浮点型变量
//			lon = atof((char *)longitude_buf+1);                //字符串转换为浮点型变量
		}
	}
}

心率

uint16_t timeCount;						//发送间隔变量
uint8_t sec_5;								//5S标志位
uint32_t ADC_ConvertedValue,xinlv;
uint16_t BPM_BUF[100];								//心率特征点缓存数组
uint16_t IBI, BPM;										//两次脉搏间隔时间以及心率
uint16_t BPM_New, BPM_Old, BPM_Cha;
uint16_t IBI_Time;										//两次脉搏间隔时间计时
uint8_t IBI_Flag;
uint16_t BPM_Max, BPM_Min, BPM_Mid;		//最大最小值以及中间值
uint16_t filter;											//有效阈值
uint8_t flag_50ms,IBI_Finish,BPM_Num,BPM_Err;

int FindArrayMax( uint16_t *a, int n )			//求最大值
{
	int i, max;
	
	max = a[0];
	for(i=0; i<n; i++ )
	{
		if(a[i]>max)
			max = a[i];
	}

	return max;
}


int FindArrayMin( uint16_t *a, int n )			//求最小值
{
	int i, min;
	
	min = a[0];
	for(i=0; i<n; i++ )
	{
		if(a[i]<min)
			min = a[i];
	}
    
    return min;
}



void Get_BPM_function()
{	
	
	if(flag_50ms)
	{
		HAL_ADC_Start(&hadc1);
		if(HAL_ADC_PollForConversion(&hadc1, 999) == HAL_OK)
			ADC_ConvertedValue = HAL_ADC_GetValue(&hadc1);
		HAL_ADC_Stop(&hadc1);
		flag_50ms =0;
		BPM_Max = FindArrayMax(BPM_BUF, 100);
		BPM_Min = FindArrayMin(BPM_BUF, 100);
		BPM_Mid = (BPM_Max + BPM_Min)/2;
		filter = (BPM_Max + BPM_Mid)/2;
		
		if(IBI_Finish == 1)
		{
			IBI_Finish = 0;
			BPM_Old = BPM_New;
			BPM_New = 60000 / IBI;
			if(BPM_New < 200)				//心率大于200算错误信号
			{
				if(BPM_New >= BPM_Old)
					BPM_Cha = BPM_New - BPM_Old;
				else
					BPM_Cha = BPM_Old - BPM_New;
				
				if(BPM_Cha < 5)				//连续3次误差在5之内才进行输出
				{
					BPM_Err = 0;
					BPM_Num++;
					if(BPM_Num >= 2)
					{
						BPM_Num = 0;
						BPM = BPM_New;
					}
				}
				else{									//中途错误一次,重新计算
					BPM_Num = 0;
					BPM_Err++;
					if(BPM_Err >= 5)
						BPM = 0;
				}
			}
			else{
				BPM_Num = 0;
				BPM_Err++;
				if(BPM_Err >= 5)
					BPM = 0;
			}
		}
	}
}

//1ms定时器中
if(timeCount%30==0)
		{
			flag_50ms=1;
			BPM_BUF[i++] = ADC_ConvertedValue;				//以15ms的周期将350个特征点存入心率数组,用于心率计算
			if(i >= 100)
				i = 0;
		}
		
		if((BPM_Max-BPM_Min) > 100)				//提高误差
		{
			if(IBI_Flag==1 && ADC_ConvertedValue>=filter)		//大于有效阈值的时间记录一次时间
			{
				IBI_Flag = 0;
				IBI = IBI_Time;
				IBI_Time = 0;
				IBI_Finish = 1;
			}
			else if(IBI_Flag==0 && ADC_ConvertedValue<filter)
				IBI_Flag = 1;
			IBI_Time++;
		}
		else{
			IBI = 0;
			IBI_Time = 0;
			BPM = 0;
		}
		
		timeCount++;
		if(timeCount >= 5000)							//产生5S周期信号
		{
			timeCount = 0;
			sec_5 = 1;
		}

WIFI -腾讯云


//1、放在main函数while(1);
ESP8266_App();

//2、放在1ms定时器中
time_flag_1ms++;
		if(time_flag_1ms>3000)   //定时三秒,每三秒上传一次数据
		{
			time_flag_1ms=0;
			sec_3 = 1;
		}
  
//3、串口中断回调函数
if(huart->Instance == huart2.Instance)//串口2触发
	{
		HAL_UART_Receive_IT(&huart2, &uart2_value, 1);
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆
		esp8266_buf[esp8266_cnt++] = uart2_value;	
	}
 
//4、配网标志位等于1
SmartConfig=1;

 

WIFI-ONENET

//网络设备驱动
#include "esp8266.h"
//网络设备
#include "onenet.h"

uint8_t time_1ms,time_500ms;
uint8_t uart1_value;          //串口1数据接收变量
uint8_t uart2_value;          //串口2数据接收变量
uint16_t timeCount;						//发送间隔变量
uint8_t sec_5;								//5S标志位
uint8_t flag_wifi;            //WIFI状态变量
unsigned char *dataPtr = NULL;//接收指针

HAL_TIM_Base_Start_IT(&htim1);
	HAL_UART_Receive_IT(&huart1, &uart1_value, 1);
	HAL_UART_Receive_IT(&huart2, &uart2_value, 1);

if(sec_5 == 1)
		{
			sec_5 = 0;
			
			if(ESP8266_Status()==0)
			{
				if(flag_wifi == 0)
				{
					flag_wifi = 1;
					ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT");
					OneNet_DevLink();
				}
				UsartPrintf("OneNet_SendData\r\n");
				OneNet_SendData();									//发送数据
				ESP8266_Clear();
			}
			else{
				if(flag_wifi == 1)
					flag_wifi = 0;
			}
		}
		dataPtr = ESP8266_GetIPD(0);
		if(dataPtr != NULL)
			OneNet_RevPro(dataPtr);	


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == htim1.Instance)		//定时器1触发中断
	{
		time_1ms++;
		if(time_1ms>= 500)
		{
			time_1ms= 0;
			time_500ms = 1;
		}
		
		timeCount++;
		if(timeCount >= 5000)							//产生5S周期信号
		{
			timeCount = 0;
			sec_5 = 1;
		}


	}

}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

	if(huart->Instance == huart1.Instance)//串口1触发
	{
		HAL_UART_Receive_IT(&huart1, &uart1_value, 1);
	}
	else if(huart->Instance == huart2.Instance)//串口2触发
	{
		HAL_UART_Receive_IT(&huart2, &uart2_value, 1);
		
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆
		esp8266_buf[esp8266_cnt++] = uart2_value;
	}

}

DS1302-时钟模块

/****
*******按键设置函数
*****/
void Key_function(void)
{
	key_num = Chiclet_Keyboard_Scan();	//按键扫描
	if(key_num != 0)										//有按键按下
	{
		switch(key_num)
		{
			case 1:													//按键1
				flag_display == 7 ? flag_display = 0 : flag_display++; //一共7个模式
				OLED_Clear2();							//清屏
			break;
			case 2:													//按键2
				switch(flag_display)
				{
					case 0:		                  //模式0
						
					break;
					case 1:											//设置界面为1时,修改年 +1
						TIME[6]++;
						if(TIME[6]%0x10 > 9)
						{
							TIME[6] = TIME[6] + 0x06;
						}
						Ds1302Init();
					break;
					
					case 2:											//设置界面为2时,修改月 +1
						TIME[4]++;
						if(TIME[4]%0x10 > 9)
						{
							TIME[4] = TIME[4] + 0x06;
						}
						if(TIME[4] > 0x12)
						{
							TIME[4] = 0x01;
						}
						Ds1302Init();
					break;
					
					case 3:											//设置界面为3时,修改日 +1
						TIME[3]++;
						if(TIME[3]%0x10 > 9)
						{
							TIME[3] = TIME[3] + 0x06;
						}
						if(TIME[3] > 0x31)
						{
							TIME[3] = 0x01;
						}
						Ds1302Init();
					break;
					
					case 4:											//设置界面为4时,修改时 +1
						TIME[2]++;
						if(TIME[2]%0x10 > 9)
						{
							TIME[2] = TIME[2] + 0x06;
						}
						if(TIME[2] > 0x23)
						{
							TIME[2] = 0x00;
						}
						Ds1302Init();
					break;
					
					case 5:											//设置界面为5时,修改分 +1
						TIME[1]++;
						if(TIME[1]%0x10 > 9)
						{
							TIME[1] = TIME[1] + 0x06;
						}
						if(TIME[1] > 0x59)
						{
							TIME[1] = 0x00;
						}
						Ds1302Init();
					break;
					
					case 6:											//设置界面为6时,修改秒 +1
						TIME[0]++;
						if(TIME[0]%0x10 > 9)
						{
							TIME[0] = TIME[0] + 0x06;
						}
						if(TIME[0] > 0x59)
						{
							TIME[0] = 0x00;
						}
						Ds1302Init();
					break;
					
					case 7:											//设置界面为7时,修改星期 +1
						TIME[5]++;
						if(TIME[5] > 0x07)
						{
							TIME[5] = 0x01;
						}
						Ds1302Init();
					break;
					
					default:;break;
				}
				break;

			case 3:													//按键3
				switch(flag_display)
				{
					case 0:		                   //模式0关闭窗帘
						
					break;
					case 1:											//设置界面为1时,修改年 -1
						TIME[6]--;
						if(TIME[6]%0x10 == 0x0f)
						{
							TIME[6] = TIME[6] - 0x06;
						}
						Ds1302Init();
					break;
					
					case 2:											//设置界面为2时,修改月 -1
						TIME[4]--;
						if(TIME[4]%0x10 == 0x0f)
						{
							TIME[4] = TIME[4] - 0x06;
						}
						if(TIME[4] < 0x01)
						{
							TIME[4] = 0x12;
						}
						Ds1302Init();
					break;
					
					case 3:											//设置界面为3时,修改日 -1
						TIME[3]--;
						if(TIME[3]%0x10 == 0x0f)
						{
							TIME[3] = TIME[3] - 0x06;
						}
						if(TIME[3] < 0x01)
						{
							TIME[3] = 0x31;
						}
						Ds1302Init();
					break;
					
					case 4:											//设置界面为4时,修改时 -1
						TIME[2]--;
						if(TIME[2]%0x10 == 0x0f)
						{
							TIME[2] = TIME[2] - 0x06;
						}
						if(TIME[2] > 0x23)
						{
							TIME[2] = 0x23;
						}
						Ds1302Init();
					break;
					
					case 5:											//设置界面为5时,修改分 -1
						TIME[1]--;
						if(TIME[1]%0x10 == 0x0f)
						{
							TIME[1] = TIME[1] - 0x06;
						}
						if(TIME[1] > 0x59)
						{
							TIME[1] = 0x59;
						}
											
						Ds1302Init();
					break;
					
					case 6:											//设置界面为6时,修改秒 -1
						TIME[0]--;
						if(TIME[0]%0x10 == 0x0f)
						{
							TIME[0] = TIME[0] - 0x06;
						}
						if(TIME[0] > 0x59)
						{
							TIME[0] = 0x59;
						}
						Ds1302Init();
					break;
					
					case 7:											//设置界面为7时,修改星期 -1
						TIME[5]--;
						if(TIME[5] < 0x01)
						{
							TIME[5] = 0x07;
						}
						Ds1302Init();
					break;
					default:;break;
				}
			break;
			default:;break;
		}
	}
}



/****
*******显示函数
*****/
void Display_function(void)
{		
	OLED_Show_Time((uint8_t *)TIME);
	switch(flag_display)												//根据不同的显示标志位,显示不同的界面
	{
		case 0:																		//界面0
			
			Oled_ShowCHinese(1,4,(uint8_t *)"温度");
			Oled_ShowString(32,4,(uint8_t *)":");
			OLED_Show_Temp(40,4,temp);
			Oled_ShowCHinese(1,6,(uint8_t *)"湿度");
			Oled_ShowString(32,6,(uint8_t *)":");
			OLED_Show_Humi(40,6,humi);
			
		break;
		case 1:																		//界面1
			Oled_ShowString(32,4,(uint8_t *)"Set Time");
			Oled_ShowString(96,4,(uint8_t *)"...");
			Oled_ShowCHinese(1,6,(uint8_t *)"设置");
			Oled_ShowString(32,6,(uint8_t *)":");
			Oled_ShowString(40,6,(uint8_t *)"   nian");
		break;
		case 2:																		//界面2
			Oled_ShowString(32,4,(uint8_t *)"Set Time");
			Oled_ShowString(96,4,(uint8_t *)"...");
			Oled_ShowCHinese(1,6,(uint8_t *)"设置");
			Oled_ShowString(32,6,(uint8_t *)":");
			Oled_ShowString(40,6,(uint8_t *)"   yue ");
		break;
		case 3:																		//界面3
			Oled_ShowString(32,4,(uint8_t *)"Set Time");
			Oled_ShowString(96,4,(uint8_t *)"...");
			Oled_ShowCHinese(1,6,(uint8_t *)"设置");
			Oled_ShowString(32,6,(uint8_t *)":");
			Oled_ShowString(40,6,(uint8_t *)"   ri  ");
		break;
		case 4:																		//界面4
			Oled_ShowString(32,4,(uint8_t *)"Set Time");
			Oled_ShowString(96,4,(uint8_t *)"...");
			Oled_ShowCHinese(1,6,(uint8_t *)"设置");
			Oled_ShowString(32,6,(uint8_t *)":");
			Oled_ShowString(40,6,(uint8_t *)"   shi ");
		break;
		case 5:                                   //界面5
			Oled_ShowString(32,4,(uint8_t *)"Set Time");
			Oled_ShowString(96,4,(uint8_t *)"...");
			Oled_ShowCHinese(1,6,(uint8_t *)"设置");
			Oled_ShowString(32,6,(uint8_t *)":");
			Oled_ShowString(40,6,(uint8_t *)"   fen ");
		break;
		case 6:	                                  //界面6
			Oled_ShowString(32,4,(uint8_t *)"Set Time");
			Oled_ShowString(96,4,(uint8_t *)"...");
			Oled_ShowCHinese(1,6,(uint8_t *)"设置");
			Oled_ShowString(32,6,(uint8_t *)":");
			Oled_ShowString(40,6,(uint8_t *)"   miao");
		break;
		case 7:                                   //界面7
			Oled_ShowString(32,4,(uint8_t *)"Set Time");
			Oled_ShowString(96,4,(uint8_t *)"...");
			Oled_ShowCHinese(1,6,(uint8_t *)"设置");
			Oled_ShowString(32,6,(uint8_t *)":");
			Oled_ShowString(40,6,(uint8_t *)"   zhou");
		break;
		
		default:;break;
	}
}

RC522-RFID

/* RFID相关变量 */
uint8_t Temp[4],UID[4];
uint8_t const DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};	//校验密码
uint8_t RC522_Buf[16];										//RC522接收数据存储数组
uint8_t User_Name[6];											//用户数组
uint8_t User_Num;
uint8_t Card_flag;												//卡标志位
uint16_t RC522_time;
uint8_t flag_err_card;
uint8_t cnt=1;
uint16_t flag_card;


if(PcdRequest(0x52,Temp)==MI_OK)	//寻卡,成功后Temp数组为卡类型
    {
      if(PcdAnticoll(UID)==MI_OK)			//防冲突,UID数组数据为卡序列号
      {
        if(PcdSelect(UID) == MI_OK)//选择该序列号卡
        {	
          if(PcdAuthState(0x60, 2,  (unsigned char *)DefaultKey,UID) == MI_OK)//校验卡密码
          {		
            if(PcdRead(2, RC522_Buf) == MI_OK)	//读取块2中当前数据
            {	
              if(flag_card==1)
              {
                if(RC522_Buf[8] == 1)
                {
                  if(flag_led==0)
                  {
                    flag_led=2;
                    BEEP(1);
                    HAL_Delay(150);
                    BEEP(0);
                    flag_display=0;
                    flag_card=0;
                  }
                  
                }
                else
                {
                  //未授权卡
                  if(flag_err_card==0)
                  {
                    if(flag_led==0)
                    {
                      flag_led=1;
                      BEEP(1);
                      HAL_Delay(1000);
                      BEEP(0);
                    }
                  }
                  
                }
              }
              //添加或者注销卡
              else
              {											
                if(flag_card == 3)			//添加卡
                {
                  RC522_Buf[8] = 1;
                  memcpy(RC522_Buf + 9, &cnt, 6);
                  User_Num = 0;
                  PcdWrite(2, RC522_Buf);
                  OLED_Clear();
                  Oled_ShowCHinese(32,3,"已增加");
                  BEEP(1);
                  HAL_Delay(1000);
                  BEEP(0);
                  flag_card=0;
                  flag_display=0;
                  OLED_Clear();
                }
                else if(flag_card == 4)	//注销卡
                {
                  memset(RC522_Buf + 8, 0, 7);
                  PcdWrite(2, RC522_Buf);
                  OLED_Clear();
                  Oled_ShowCHinese(32,3,"已删除");
                  BEEP(1);
                  HAL_Delay(1000);
                  BEEP(0);
                  flag_card=0;
                  flag_display=0;
                  OLED_Clear();
                }
              }
            }
          }
        }
      }
    }
    
    
    /* RFID相关初始化 */
	RC522_GPIO_Init();
	PcdReset();
	PcdAntennaOff(); 
	HAL_Delay(5);
	PcdAntennaOn();  
	M500PcdConfigISOType('A');

红外遥控

uint8_t IR_Buf[4];			//红外信号存储数组


/*
45 46 47
44 40 43
07 15 09
16 19 0D
0C 18 5E
08 1C 5A
42 52 4A
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//外部中断回调函数
{
	uint8_t j,k;
	if(GPIO_Pin == IR_IN_Pin)//判断是否是红外引脚触发中断
	{
		if(IR_IN == 0)										//确认是否真的接收到正确的信号
		{
			while(IR_IN == 0);							//等待9ms低电平
			if(IR_IN == 1)									//如果正确等到9ms低电平
			{
				TIM2->CNT=0;
				HAL_TIM_Base_Start(&htim2);
				while(IR_IN == 1)						 	//等待4.5ms的起始高电平过去
				{
					if(TIM2->CNT >= 5000) return ;
				}
				HAL_TIM_Base_Stop(&htim2);
				for(j=0;j<4;j++)							//共有4组数据
				{
					for(k=0;k<8;k++)						//接收一组数据
					{
						while(IR_IN == 0);				//等待信号前面的560us低电平过去
						TIM2->CNT=0;
						HAL_TIM_Base_Start(&htim2);
						while(IR_IN == 1)					//计算高电平的时间长度
						{
							if(TIM2->CNT >= 2000) return ;
						}
						HAL_TIM_Base_Stop(&htim2);
						IR_Buf[j] >>= 1;
						if(TIM2->CNT >= 800) IR_Buf[j] |= 0x80;	//如果高电平出现大于800us,那么是1
					}
				}
			}
			if(IR_Buf[2] == 0x0C) 
      {
      
      }
			else if(IR_Buf[2] == 0x18)
      {
        
      }
		}
	}
}

 

发表回复

登录... 后才能评论