地铁站人流检测硬件部分

news/2024/4/27 12:37:09/文章来源:https://blog.csdn.net/qq_52479948/article/details/130350562

目录

一、概述

二、驱动程序

2.1debug串口

2.2体重传感器HX711

2.3滴答定时器

2.4ESP8266

2.5人体检测

2.6 IIC的GPIO

2.7 OLED的IIC

2.8 LED

三、应用

四、中断


一、概述

使用STM32C8T6作为主控

A9		--->	tx(调试串口)
A10		--->    rx
A6		--->	SCK(体重)
A7		--->	DOUT(体重)
A2		--->	tx
A3		--->    rx
B3      --->    wifi reset
C14     --->    人体感应
A5		--->	SCL	(OLED)
A4		--->	SDA
C13		--->	LED1
B0		--->	key1(进站)
B1		--->	key2(出站)

 

用串口一进行打印调试

串口二和ESP01s进行通信连接服务器。

A6和A7用模拟IIC的方式和HX711通信,采集压力传感器,看看是否有人在上面,配合C14管脚的HC-SR501,当两个条件都满足证明有人经过地铁站的检测门。

A4A5是软件IIC和OLED进行通信。

二、驱动程序

2.1debug串口

#include "bsp/usart/bsp_debug_usart.h"/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*//*** 函数功能: 板载调试串口参数配置.* 输入参数: 无* 返 回 值: 无* 说    明:使用宏定义方法代替具体引脚号,方便程序移植,只要简单修改bsp_led.h*           文件相关宏定义就可以方便修改引脚。*/
void DEBUG_USART_Init(void)
{/* 定义IO硬件初始化结构体变量 */GPIO_InitTypeDef GPIO_InitStructure;/* 定义USART初始化结构体变量 */USART_InitTypeDef USART_InitStructure;/* 使能USART时钟 */DEBUG_USARTx_ClockCmd(DEBUG_USARTx_CLK,ENABLE);/* 使能USART功能GPIO时钟 */DEBUG_USARTx_GPIO_ClockCmd(DEBUG_USARTx_TX_CLK | DEBUG_USARTx_RX_CLK | RCC_APB2Periph_AFIO,ENABLE);/* 调试USART功能GPIO初始化 *//* 设定USART发送对应IO编号 */GPIO_InitStructure.GPIO_Pin =  DEBUG_USARTx_TX_PIN;/* 设定USART发送对应IO模式:复用推挽输出 */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;/* 设定USART发送对应IO最大操作速度 :GPIO_Speed_50MHz */GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/* 初始化USART发送对应IO */GPIO_Init(DEBUG_USARTx_TX_PORT, &GPIO_InitStructure);    /* 设定USART接收对应IO编号 */GPIO_InitStructure.GPIO_Pin = DEBUG_USARTx_RX_PIN;/* 设定USART发送对应IO模式:浮空输入 */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;/* 其他没有重新赋值的成员使用与串口发送相同配置 *//* 初始化USART接收对应IO */GPIO_Init(DEBUG_USARTx_RX_PORT, &GPIO_InitStructure);	/* USART工作环境配置 *//* USART波特率:115200 */USART_InitStructure.USART_BaudRate = DEBUG_USARTx_BAUDRATE;/* USART字长(有效位):8位 */USART_InitStructure.USART_WordLength = USART_WordLength_8b;/* USART停止位:1位 */USART_InitStructure.USART_StopBits = USART_StopBits_1;/* USART校验位:无 */USART_InitStructure.USART_Parity = USART_Parity_No ;/* USART硬件数据流控制(硬件信号控制传输停止):无 */USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;/* USART工作模式使能:允许接收和发送 */USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;/* 初始化USART */USART_Init(DEBUG_USARTx, &USART_InitStructure);/* 使能USART */USART_Cmd(DEBUG_USARTx, ENABLE);}/*** 函数功能: 重定向c库函数printf到USARTx* 输入参数: 无* 返 回 值: 无* 说    明:无*/
int fputc(int ch, FILE *f)
{/* 发送一个字节数据到调试串口 */USART_SendData(DEBUG_USARTx, (uint8_t) ch);/* 等待串口数据发送完毕 */while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);		return (ch);
}/*** 函数功能: 重定向c库函数getchar,scanf到USARTx* 输入参数: 无* 返 回 值: 无* 说    明:无*/
int fgetc(FILE *f)
{/* 等待串口输入数据 */while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(DEBUG_USARTx);
}

就是一个简单的串口

2.2体重传感器HX711

#include "bsp/HX711/HX711.h"
#include "bsp/systick/bsp_SysTick.h"u32 HX711_Buffer;
u32 Weight_Maopi;
s32 Weight_Shiwu;
u8 Flag_Error = 0;//校准参数
//因为不同的传感器特性曲线不是很一致,因此,每一个传感器需要矫正这里这个参数才能使测量值很准确。
//当发现测试出来的重量偏大时,增加该数值。
//如果测试出来的重量偏小时,减小改数值。
//该值可以为小数
#define GapValue 106.5void Init_HX711pin(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PF端口时钟//HX711_SCKGPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;				 // 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB//HX711_DOUTGPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//输入上拉GPIO_Init(GPIOA, &GPIO_InitStructure);  GPIO_SetBits(GPIOA,GPIO_Pin_6);					//初始化设置为0
}//****************************************************
//读取HX711
//****************************************************
u32 HX711_Read(void)	//增益128
{unsigned long count; unsigned char i; GPIO_SetBits(GPIOA,GPIO_Pin_7); Delay_us(1);GPIO_ResetBits(GPIOA,GPIO_Pin_6); count=0; while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)); for(i=0;i<24;i++){ GPIO_SetBits(GPIOA,GPIO_Pin_6);  count=count<<1; Delay_us(1);GPIO_ResetBits(GPIOA,GPIO_Pin_6); if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7))count++; Delay_us(1);} GPIO_SetBits(GPIOA,GPIO_Pin_6); count=count^0x800000;//第25个脉冲下降沿来时,转换数据Delay_us(1);GPIO_ResetBits(GPIOA,GPIO_Pin_6);  return(count);
}//****************************************************
//获取毛皮重量
//****************************************************
void Get_Maopi(void)
{Weight_Maopi = HX711_Read();	
} //****************************************************
//称重
//****************************************************
void Get_Weight(void)
{HX711_Buffer = HX711_Read();if(HX711_Buffer > Weight_Maopi)			{Weight_Shiwu = HX711_Buffer;Weight_Shiwu = Weight_Shiwu - Weight_Maopi;				//获取实物的AD采样数值。Weight_Shiwu = (s32)((float)Weight_Shiwu/GapValue); 	//计算实物的实际重量//因为不同的传感器特性曲线不一样,因此,每一个传感器需要矫正这里的GapValue这个除数。//当发现测试出来的重量偏大时,增加该数值。//如果测试出来的重量偏小时,减小改数值。}}

我手搓的,参考它给的51程序,还好大一学了一年51.

2.3滴答定时器

/* 包含头文件 ----------------------------------------------------------------*/
#include "bsp/systick/bsp_SysTick.h"/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
static __IO u32 TimingDelay;
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/ 
/*** 函数功能: 初始化配置系统滴答定时器 SysTick* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void SysTick_Init(void)
{/* SystemFrequency / 1000    1ms中断一次* SystemFrequency / 100000	 10us中断一次* SystemFrequency / 1000000 1us中断一次*/if (SysTick_Config(SystemCoreClock / 1000000)){ /* Capture error */ while (1);}/* 关闭系统滴答定时器:初始化先不用开启,等需要延时时才开启定时器  */SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}/*** 函数功能: us延时程序* 输入参数: nTime:延时时间* 返 回 值: 无* 说    明:无*/
void Delay_us(__IO u32 nTime)
{ TimingDelay = nTime;	/* 使能滴答定时器 */ SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;while(TimingDelay != 0);/* 关闭系统滴答定时器 */SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}/*** 函数功能: 获取节拍程序* 输入参数: 无* 返 回 值: 无* 说    明:在 SysTick 中断函数 SysTick_Handler()调用*/
void TimingDelay_Decrement(void)
{if (TimingDelay != 0x00){ TimingDelay--;}
}

2.4ESP8266

/* 包含头文件 ----------------------------------------------------------------*/
#include "bsp/ESP8266/bsp_esp8266.h"
#include "bsp/systick/bsp_SysTick.h"
#include <stdio.h>  
#include <string.h>  
#include <stdbool.h>
#include <stdarg.h>/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
struct  STRUCT_USARTx_Fram strEsp8266_Fram_Record = { 0 };/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
static char * itoa( int value, char * string, int radix );/* 函数体 --------------------------------------------------------------------*/
/*** 函数功能: 初始化ESP8266用到的GPIO引脚* 输入参数: 无* 返 回 值: 无* 说    明:无*/
static void ESP8266_GPIO_Config ( void )
{/*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDef GPIO_InitStructure;/* 配置 CH_PD 引脚*/RCC_APB2PeriphClockCmd( ESP8266_RST_CLK, ENABLE ); 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* 配置 RST 引脚*/									   GPIO_InitStructure.GPIO_Pin = ESP8266_RST_PIN;GPIO_Init ( ESP8266_RST_PORT, & GPIO_InitStructure );		/* 拉高WiFi模块的复位重启引脚	*/GPIO_ResetBits( ESP8266_RST_PORT, ESP8266_RST_PIN );}/*** 函数功能: 配置 ESP8266 USART 的 NVIC 中断优先级* 输入参数: 无* 返 回 值: 无* 说    明:无*/
static void ESP8266_USART_NVIC_Configuration ( void )
{NVIC_InitTypeDef NVIC_InitStructure; 	/* Configure the NVIC Preemption Priority Bits */  NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2 );/* Enable the USART2 Interrupt */NVIC_InitStructure.NVIC_IRQChannel = ESP8266_USART_IRQ;	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);}/*** 函数功能: 初始化ESP8266用到的 USART* 输入参数: 无* 返 回 值: 无* 说    明:无*/
static void ESP8266_USART_Config ( void )
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;	/* config USART clock */ESP8266_USART_APBxClock_FUN ( ESP8266_USART_CLK, ENABLE );ESP8266_USART_GPIO_APBxClock_FUN ( ESP8266_USART_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE );/* USART GPIO config *//* Configure USART Tx as alternate function push-pull */GPIO_InitStructure.GPIO_Pin =  ESP8266_USART_TX_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(ESP8266_USART_TX_PORT, &GPIO_InitStructure);  /* Configure USART Rx as input floating */GPIO_InitStructure.GPIO_Pin = ESP8266_USART_RX_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(ESP8266_USART_RX_PORT, &GPIO_InitStructure);/* USART1 mode config */USART_InitStructure.USART_BaudRate = ESP8266_USART_BAUD_RATE;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No ;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(ESP8266_USARTx, &USART_InitStructure);/* 中断配置 */USART_ITConfig ( ESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中断 USART_ITConfig ( ESP8266_USARTx, USART_IT_IDLE, ENABLE ); //使能串口总线空闲中断 	ESP8266_USART_NVIC_Configuration();	USART_Cmd(ESP8266_USARTx, ENABLE);	/* 清除发送完成标志 */USART_ClearFlag(ESP8266_USARTx, USART_FLAG_TC|USART_FLAG_TXE|USART_FLAG_RXNE);
}/*** 函数功能: 格式化输出,类似于C库中的printf,但这里没有用到C库* 输入参数: USARTx 串口通道,这里只用到了串口2,即USART2*		        Data   要发送到串口的内容的指针*			      ...    其他参数* 返 回 值: 无* 说    明:典型应用 USART2_printf( USART2, "\r\n this is a demo \r\n" );*            		     USART2_printf( USART2, "\r\n %d \r\n", i );*            		     USART2_printf( USART2, "\r\n %s \r\n", j );*/
void USART_printf(USART_TypeDef * USARTx, char * Data, ... )
{const char *s;int d;   char buf[16];va_list ap;va_start(ap, Data);while ( * Data != 0 )     // 判断是否到达字符串结束符{				                          if ( * Data == 0x5c )  //'\'{									  switch ( *++Data ){case 'r':							          //回车符USART_SendData(USARTx, 0x0d);Data ++;break;case 'n':							          //换行符USART_SendData(USARTx, 0x0a);	Data ++;break;default:Data ++;break;}			 }else if ( * Data == '%'){									  //switch ( *++Data ){				case 's':										  //字符串s = va_arg(ap, const char *);for ( ; *s; s++) {USART_SendData(USARTx,*s);while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );}				Data++;				break;case 'd':			//十进制d = va_arg(ap, int);					itoa(d, buf, 10);					for (s = buf; *s; s++) {USART_SendData(USARTx,*s);while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );}					Data++;				break;				default:Data++;				break;				}		 }		else USART_SendData(USARTx, *Data++);while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET );}
}/*** 函数功能: 将整形数据转换成字符串* 输入参数: radix =10 表示10进制,其他结果为0*           value 要转换的整形数*           buf 转换后的字符串*           radix = 10* 返 回 值: 无* 说    明:被USART_printf()调用*/
static char * itoa( int value, char *string, int radix )
{int     i, d;int     flag = 0;char    *ptr = string;/* This implementation only works for decimal numbers. */if (radix != 10){*ptr = 0;return string;}if (!value){*ptr++ = 0x30;*ptr = 0;return string;}/* if this is a negative value insert the minus sign. */if (value < 0){*ptr++ = '-';/* Make the value positive. */value *= -1;}for (i = 10000; i > 0; i /= 10){d = value / i;if (d || flag){*ptr++ = (char)(d + 0x30);value -= (d * i);flag = 1;}}/* Null terminate the string. */*ptr = 0;return string;
} /* NCL_Itoa *//*** 函数功能: ESP8266初始化函数* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void ESP8266_Init ( void )
{ESP8266_GPIO_Config ();	ESP8266_USART_Config ();	
}/*** 函数功能: 停止使用ESP8266* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void  ESP8266_stop( void )
{ESP8266_RST_LOW_LEVEL();USART_ITConfig ( ESP8266_USARTx, USART_IT_RXNE, DISABLE ); //使能串口接收中断 USART_ITConfig ( ESP8266_USARTx, USART_IT_IDLE, DISABLE ); //使能串口总线空闲中断 	USART_Cmd(ESP8266_USARTx, DISABLE);ESP8266_USART_APBxClock_FUN ( ESP8266_USART_CLK, DISABLE );
}/*** 函数功能: 重启ESP8266模块* 输入参数: 无* 返 回 值: 无* 说    明:被ESP8266_AT_Test调用*/
void ESP8266_Rst ( void )
{
#if 0ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 );   	
#elseESP8266_RST_LOW_LEVEL();Delay_ms( 500 ); ESP8266_RST_HIGH_LEVEL(); 
#endif
}/*** 函数功能: 对ESP8266模块发送AT指令* 输入参数: cmd,待发送的指令*           reply1,reply2,期待的响应,为NULL表不需响应,两者为或逻辑关系*           waittime,等待响应的时间* 返 回 值: 1,指令发送成功*           0,指令发送失败* 说    明:无*/
bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime )
{    strEsp8266_Fram_Record .InfBit .FramLength = 0;               //从新开始接收新的数据包ESP8266_Usart ( "%s\r\n", cmd );if ( ( reply1 == 0 ) && ( reply2 == 0 ) )                      //不需要接收数据return true;Delay_ms( waittime );                 //延时strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ]  = '\0';PC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF );
//  printf("%s->%s\n",cmd,strEsp8266_Fram_Record .Data_RX_BUF);if ( ( reply1 != 0 ) && ( reply2 != 0 ) )return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) || ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); else if ( reply1 != 0 )return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) );elsereturn ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );}/*** 函数功能: 对ESP8266模块进行AT测试启动* 输入参数: 无* 返 回 值: 1,选择成功*           0,选择失败* 说    明:无*/
bool ESP8266_AT_Test ( void )
{char count=0;ESP8266_RST_HIGH_LEVEL();	Delay_ms ( 1000 );while(count<10){if(ESP8266_Cmd("AT","OK",NULL,1000)) return 1;ESP8266_Rst();Delay_ms ( 1000 );++count;}return 0;
}/*** 函数功能: 选择ESP8266模块的工作模式* 输入参数: enumMode,工作模式* 返 回 值: 1,选择成功*           0,选择失败* 说    明:无*/
bool ESP8266_Net_Mode_Choose ( ENUM_Net_ModeTypeDef enumMode )
{bool result=0;char count=0;while(count<10){switch ( enumMode ){case STA:result=ESP8266_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 ); break;case AP:result=ESP8266_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 ); break;case STA_AP:result=ESP8266_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 ); break;default:result=false;break;}if(result) return result;++count;}return 0;
}/*** 函数功能: ESP8266模块连接外部WiFi* 输入参数: pSSID,WiFi名称字符串*           pPassWord,WiFi密码字符串* 返 回 值: 1,连接成功*           0,连接失败* 说    明:无*/
bool ESP8266_JoinAP ( char * pSSID, char * pPassWord )
{char cCmd [120];char count=0;sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord );while(count<10){if(ESP8266_Cmd(cCmd,"OK",NULL,5000))return 1;++count;}return 0;	
}/*** 函数功能: ESP8266模块创建WiFi热点* 输入参数: pSSID,WiFi名称字符串*           pPassWord,WiFi密码字符串*           enunPsdMode,WiFi加密方式代号字符串* 返 回 值: 1,创建成功*           0,创建失败* 说    明:无*/
bool ESP8266_BuildAP ( char * pSSID, char * pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode )
{char cCmd [120];char count=0;sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", pSSID, pPassWord, enunPsdMode );while(count<10){if(ESP8266_Cmd(cCmd,"OK",0,1000))return 1;++count;}return 0;	
}/*** 函数功能: ESP8266模块启动多连接* 输入参数: enumEnUnvarnishTx,配置是否多连接* 返 回 值: 1,配置成功*           0,配置失败* 说    明:无*/
bool ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx )
{char cStr [20];char count=0;sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) );while(count<10){if(ESP8266_Cmd(cStr,"OK",0,500))return 1;++count;}return 0;		
}/*** 函数功能: ESP8266模块连接外部服务器* 输入参数: enumE,网络协议*           ip,服务器IP字符串*           ComNum,服务器端口字符串*           id,模块连接服务器的ID* 返 回 值: 1,连接成功*           0,连接失败* 说    明:无*/
bool ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id)
{char cStr [100] = { 0 }, cCmd [120];switch (  enumE ){case enumTCP:sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum );break;case enumUDP:sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum );break;default:break;}if ( id < 5 )sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr);elsesprintf ( cCmd, "AT+CIPSTART=%s", cStr );return ESP8266_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );}/*** 函数功能: ESP8266模块开启或关闭服务器模式* 输入参数: enumMode,开启/关闭*           pPortNum,服务器端口号字符串*           pTimeOver,服务器超时时间字符串,单位:秒* 返 回 值: 1,操作成功*           0,操作失败* 说    明:无*/
bool ESP8266_StartOrShutServer ( FunctionalState enumMode, char * pPortNum, char * pTimeOver )
{char cCmd1 [120], cCmd2 [120];if ( enumMode ){sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum );sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver );return ( ESP8266_Cmd ( cCmd1, "OK", 0, 500 ) &&ESP8266_Cmd ( cCmd2, "OK", 0, 500 ) );}else{sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum );return ESP8266_Cmd ( cCmd1, "OK", 0, 500 );}
}/*** 函数功能: 获取ESP8266 的连接状态,较适合单端口时使用* 输入参数: 无* 返 回 值: 2,获得ip*           3,建立连接*           4,失去连接*           0,获取状态失败* 说    明:无*/
uint8_t ESP8266_Get_LinkStatus ( void )
{if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) ){if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) )return 2;else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) )return 3;else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) )return 4;		}return 0;
}/*** 函数功能: 获取ESP8266 的端口(Id)连接状态,较适合多端口时使用* 输入参数: 无* 返 回 值: 端口(Id)的连接状态,低5位为有效位,分别对应Id5~0,某位若置1表该Id建立了连接,若被清0表该Id未建立连接* 说    明:无*/
uint8_t ESP8266_Get_IdLinkStatus ( void )
{uint8_t ucIdLinkStatus = 0x00;if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) ){if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:0," ) )ucIdLinkStatus |= 0x01;else ucIdLinkStatus &= ~ 0x01;if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:1," ) )ucIdLinkStatus |= 0x02;else ucIdLinkStatus &= ~ 0x02;if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:2," ) )ucIdLinkStatus |= 0x04;else ucIdLinkStatus &= ~ 0x04;if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:3," ) )ucIdLinkStatus |= 0x08;else ucIdLinkStatus &= ~ 0x08;if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:4," ) )ucIdLinkStatus |= 0x10;else ucIdLinkStatus &= ~ 0x10;	}return ucIdLinkStatus;
}/*** 函数功能: 获取ESP8266 的 AP IP* 输入参数: pApIp,存放 AP IP 的数组的首地址*           ucArrayLength,存放 AP IP 的数组的长度* 返 回 值: 1,获取成功*           0,获取失败* 说    明:无*/
uint8_t ESP8266_Inquire_ApIp ( char * pApIp, uint8_t ucArrayLength )
{char uc;char * pCh;ESP8266_Cmd ( "AT+CIFSR", "OK", 0, 500 );pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "APIP,\"" );if ( pCh )pCh += 6;elsereturn 0;for ( uc = 0; uc < ucArrayLength; uc ++ ){pApIp [ uc ] = * ( pCh + uc);if ( pApIp [ uc ] == '\"' ){pApIp [ uc ] = '\0';break;}}return 1;
}/*** 函数功能: 配置ESP8266模块进入透传发送* 输入参数: 无* 返 回 值: 1,配置成功*           0,配置失败* 说    明:无*/
bool ESP8266_UnvarnishSend ( void )
{if ( ! ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 1000 ) )return false;return  ESP8266_Cmd ( "AT+CIPSEND", "OK", ">", 1000 );}/*** 函数功能: 配置ESP8266模块退出透传模式* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void ESP8266_ExitUnvarnishSend ( void )
{Delay_ms ( 1000 );ESP8266_Usart ( "+++" );Delay_ms( 500 ); }/*** 函数功能: ESP8266模块发送字符串* 输入参数: enumEnUnvarnishTx,声明是否已使能了透传模式*           pStr,要发送的字符串*           ucId,哪个ID发送的字符串*           ulStrLength,要发送的字符串的字节数* 返 回 值: 1,发送成功*           0,发送失败* 说    明:无*/
bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId )
{char cStr [20];bool bRet = false;if ( enumEnUnvarnishTx ){ESP8266_Usart ( "%s", pStr );bRet = true;}else{if ( ucId < 5 )sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );elsesprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );ESP8266_Cmd ( cStr, "> ", 0, 1000 );bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 1000 );}return bRet;}/*** 函数功能: ESP8266模块接收字符串* 输入参数: enumEnUnvarnishTx,声明是否已使能了透传模式* 返 回 值: 接收到的字符串首地址* 说    明:无*/
char * ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx )
{char * pRecStr = 0;strEsp8266_Fram_Record .InfBit .FramLength = 0;strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag );strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';if ( enumEnUnvarnishTx )pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;else {if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" ) )pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;}return pRecStr;	
}

2.5人体检测

/* 包含头文件 ----------------------------------------------------------------*/
#include "bsp/HC-SR501/bsp_HC-SR501.h"/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*//*** 函数功能: 板载按键IO引脚初始化.* 输入参数: 无* 返 回 值: 无* 说    明:使用宏定义方法代替具体引脚号,方便程序移植,只要简单修改bsp_key.h*           文件相关宏定义就可以方便修改引脚。*/
void HC_SR501_GPIO_Init(void)
{/* 定义IO硬件初始化结构体变量 */GPIO_InitTypeDef GPIO_InitStructure;/* 使能(开启)KEY1引脚对应IO端口时钟 */  RCC_APB2PeriphClockCmd(HC_SR501_RCC_CLOCKGPIO, ENABLE);/* 设定KEY1对应引脚IO编号 */GPIO_InitStructure.GPIO_Pin = HC_SR501_GPIO_PIN;  /* 设定KEY1对应引脚IO最大操作速度 :GPIO_Speed_50MHz */GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;  /* 设定KEY1对应引脚IO为浮空输入模式 */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  /* 初始化KEY1对应引脚IO */GPIO_Init(HC_SR501_GPIO, &GPIO_InitStructure);
}/*** 函数功能: 简单粗暴的延时函数* 输入参数: time;延时时间设置* 返 回 值: 无* 说    明:软件消抖*/
static void HC_SR501_ScanDelay(void)
{  uint32_t i,j;for(i=0;i<100;++i)for(j=0;j<1000;++j){ }		
}/*** 函数功能: 读取按键KEY1的状态* 输入参数:无* 返 回 值: KEY_DOWN:按键被按下;*           KEY_UP  :按键没被按下* 说    明:无。*/
HC_SR501_State_TypeDef HC_SR501_StateRead(void)
{/* 读取此时按键值并判断是否是被按下状态,如果是被按下状态进入函数内 */if(GPIO_ReadInputDataBit(HC_SR501_GPIO,HC_SR501_GPIO_PIN)==HC_SR501_ACTIVE_LEVEL){/* 延时一小段时间,消除抖动 */HC_SR501_ScanDelay();/* 延时时间后再来判断按键状态,如果还是按下状态说明按键确实被按下 */if(GPIO_ReadInputDataBit(HC_SR501_GPIO,HC_SR501_GPIO_PIN)==HC_SR501_ACTIVE_LEVEL){      /* 按键扫描完毕,确定按键被按下,返回按键被按下状态 */return HC_SR501_HIGH;}}/* 按键没被按下,返回没被按下状态 */return HC_SR501_LOW;
}

2.6 IIC的GPIO

/* 包含头文件 ----------------------------------------------------------------*/
#include "bsp/i2c/bsp_i2c_gpio.h"/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
void i2c_Start(void);
void i2c_Stop(void);
void i2c_SendByte(uint8_t _ucByte);
uint8_t i2c_ReadByte(void);
uint8_t i2c_WaitAck(void);
void i2c_Ack(void);
void i2c_NAck(void);/* 函数体 --------------------------------------------------------------------*/
/*** 函数功能: I2C总线位延迟,最快400KHz* 输入参数: 无* 返 回 值: 无* 说    明:无*/
static void i2c_Delay(void)
{uint8_t i;/* 下面的时间是通过逻辑分析仪测试得到的。CPU主频72MHz时,在内部Flash运行, MDK工程不优化循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us IAR工程编译效率高,不能设置为7*/for (i = 0; i < 10; i++);
}/*** 函数功能: CPU发起I2C总线启动信号* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void i2c_Start(void)
{/* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */I2C_SDA_1();I2C_SCL_1();i2c_Delay();I2C_SDA_0();i2c_Delay();I2C_SCL_0();i2c_Delay();
}/*** 函数功能: CPU发起I2C总线停止信号* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void i2c_Stop(void)
{/* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */I2C_SDA_0();I2C_SCL_1();i2c_Delay();I2C_SDA_1();
}/*** 函数功能: CPU向I2C总线设备发送8bit数据* 输入参数: Byte : 等待发送的字节* 返 回 值: 无* 说    明:无*/
void i2c_SendByte(uint8_t Byte)
{uint8_t i;/* 先发送字节的高位bit7 */for (i = 0; i < 8; i++){		if (Byte & 0x80){I2C_SDA_1();}else{I2C_SDA_0();}i2c_Delay();I2C_SCL_1();i2c_Delay();	I2C_SCL_0();if (i == 7){I2C_SDA_1(); // 释放总线}Byte <<= 1;	/* 左移一个bit */i2c_Delay();}
}/*** 函数功能: CPU从I2C总线设备读取8bit数据* 输入参数: 无* 返 回 值: 读到的数据* 说    明:无*/
uint8_t i2c_ReadByte(void)
{uint8_t i;uint8_t value;/* 读到第1个bit为数据的bit7 */value = 0;for (i = 0; i < 8; i++){value <<= 1;I2C_SCL_1();i2c_Delay();if (I2C_SDA_READ()){value++;}I2C_SCL_0();i2c_Delay();}return value;
}/*** 函数功能: CPU产生一个时钟,并读取器件的ACK应答信号* 输入参数: 无* 返 回 值: 返回0表示正确应答,1表示无器件响应* 说    明:无*/
uint8_t i2c_WaitAck(void)
{uint8_t re;I2C_SDA_1();	/* CPU释放SDA总线 */i2c_Delay();I2C_SCL_1();	/* CPU驱动SCL = 1, 此时器件会返回ACK应答 */i2c_Delay();if (I2C_SDA_READ())	/* CPU读取SDA口线状态 */{re = 1;}else{re = 0;}I2C_SCL_0();i2c_Delay();return re;
}/*** 函数功能: CPU产生一个ACK信号* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void i2c_Ack(void)
{I2C_SDA_0();	/* CPU驱动SDA = 0 */i2c_Delay();I2C_SCL_1();	/* CPU产生1个时钟 */i2c_Delay();I2C_SCL_0();i2c_Delay();I2C_SDA_1();	/* CPU释放SDA总线 */
}/*** 函数功能: CPU产生1个NACK信号* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void i2c_NAck(void)
{I2C_SDA_1();	/* CPU驱动SDA = 1 */i2c_Delay();I2C_SCL_1();	/* CPU产生1个时钟 */i2c_Delay();I2C_SCL_0();i2c_Delay();	
}/*** 函数功能: 配置I2C总线的GPIO,采用模拟IO的方式实现* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void I2C_InitGPIO(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE);	/* 打开GPIO时钟 */GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  	/* 开漏输出 */GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */i2c_Stop();
}/*** 函数功能: 写入数据到i2c* 输入参数: 无* 返 回 值: 无* 说    明:无*/
void write_i2c(uint8_t device,uint8_t addr,uint8_t dat)
{i2c_Start();i2c_SendByte(device);i2c_WaitAck();i2c_SendByte(addr);i2c_WaitAck();i2c_SendByte(dat);i2c_WaitAck();i2c_Stop();
}/*** 函数功能: 从i2c读取数据* 输入参数: 无* 返 回 值: 无* 说    明:无*/
uint8_t read_i2c(uint8_t device,uint8_t addr)
{uint8_t dat;i2c_Start();i2c_SendByte(device);i2c_WaitAck();i2c_SendByte(addr);i2c_WaitAck();i2c_Start();i2c_SendByte(device+0x01);i2c_WaitAck();dat=i2c_ReadByte();i2c_NAck();i2c_Stop();return dat;
}

2.7 OLED的IIC

/* 包含头文件 ----------------------------------------------------------------*/
#include "bsp/i2c/bsp_i2c_gpio.h"
#include "bsp/i2c/bsp_i2c_OLED.h"
#include "bsp/i2c/codetab.h"
#include "bsp/systick/bsp_SysTick.h"/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*//*** @brief  WriteCmd,向OLED写入命令* @param  I2C_Command:命令代码* @retval 无*/
void WriteCmd(unsigned char I2C_Command)//写命令
{write_i2c(OLED_DEV_ADDR,0x00, I2C_Command);
}/*** @brief  WriteDat,向OLED写入数据* @param  I2C_Data:数据* @retval 无*/
void WriteDat(unsigned char I2C_Data)//写数据
{write_i2c(OLED_DEV_ADDR,0x40, I2C_Data);
}/*** @brief  OLED_Init,初始化OLED* @param  无* @retval 无*/
void OLED_Init(void)
{I2C_InitGPIO();Delay_ms(100); //这里的延时很重要WriteCmd(0xAE); //display offWriteCmd(0x20);	//Set Memory Addressing Mode	WriteCmd(0x10);	//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,InvalidWriteCmd(0xb0);	//Set Page Start Address for Page Addressing Mode,0-7WriteCmd(0xc8);	//Set COM Output Scan DirectionWriteCmd(0x00); //---set low column addressWriteCmd(0x10); //---set high column addressWriteCmd(0x40); //--set start line addressWriteCmd(0x81); //--set contrast control registerWriteCmd(0xff); //亮度调节 0x00~0xffWriteCmd(0xa1); //--set segment re-map 0 to 127WriteCmd(0xa6); //--set normal displayWriteCmd(0xa8); //--set multiplex ratio(1 to 64)WriteCmd(0x3F); //WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM contentWriteCmd(0xd3); //-set display offsetWriteCmd(0x00); //-not offsetWriteCmd(0xd5); //--set display clock divide ratio/oscillator frequencyWriteCmd(0xf0); //--set divide ratioWriteCmd(0xd9); //--set pre-charge periodWriteCmd(0x22); //WriteCmd(0xda); //--set com pins hardware configurationWriteCmd(0x12);WriteCmd(0xdb); //--set vcomhWriteCmd(0x20); //0x20,0.77xVccWriteCmd(0x8d); //--set DC-DC enableWriteCmd(0x14); //WriteCmd(0xaf); //--turn on oled panel
}/*** @brief  OLED_SetPos,设置光标* @param  x,光标x位置*					y,光标y位置* @retval 无*/
void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
{ WriteCmd(0xb0+y);WriteCmd(((x&0xf0)>>4)|0x10);WriteCmd((x&0x0f)|0x01);
}/*** @brief  OLED_Fill,填充整个屏幕* @param  fill_Data:要填充的数据* @retval 无*/
void OLED_Fill(unsigned char fill_Data)//全屏填充
{unsigned char m,n;for(m=0;m<8;m++){WriteCmd(0xb0+m);		//page0-page1WriteCmd(0x00);		//low column start addressWriteCmd(0x10);		//high column start addressfor(n=0;n<128;n++){WriteDat(fill_Data);}}
}/*** @brief  OLED_CLS,清屏* @param  无* @retval 无*/
void OLED_CLS(void)//清屏
{OLED_Fill(0x00);
}/*** @brief  OLED_ON,将OLED从休眠中唤醒* @param  无* @retval 无*/
void OLED_ON(void)
{WriteCmd(0X8D);  //设置电荷泵WriteCmd(0X14);  //开启电荷泵WriteCmd(0XAF);  //OLED唤醒
}/*** @brief  OLED_OFF,让OLED休眠 -- 休眠模式下,OLED功耗不到10uA* @param  无* @retval 无*/
void OLED_OFF(void)
{WriteCmd(0X8D);  //设置电荷泵WriteCmd(0X10);  //关闭电荷泵WriteCmd(0XAE);  //OLED休眠
}/*** @brief  OLED_ShowStr,显示codetab.h中的ASCII字符,有6*8和8*16可选择* @param  x,y : 起始点坐标(x:0~127, y:0~7);*					ch[] :- 要显示的字符串; *					TextSize : 字符大小(1:6*8 ; 2:8*16)* @retval 无*/
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{unsigned char c = 0,i = 0,j = 0;switch(TextSize){case 1:{while(ch[j] != '\0'){c = ch[j] - 32;if(x > 126){x = 0;y++;}OLED_SetPos(x,y);for(i=0;i<6;i++)WriteDat(F6x8[c][i]);x += 6;j++;}}break;case 2:{while(ch[j] != '\0'){c = ch[j] - 32;if(x > 120){x = 0;y++;}OLED_SetPos(x,y);for(i=0;i<8;i++)WriteDat(F8X16[c*16+i]);OLED_SetPos(x,y+1);for(i=0;i<8;i++)WriteDat(F8X16[c*16+i+8]);x += 8;j++;}}break;}
}/*** @brief  OLED_ShowCN,显示codetab.h中的汉字,16*16点阵* @param  x,y: 起始点坐标(x:0~127, y:0~7); *					N:汉字在codetab.h中的索引* @retval 无*/
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{unsigned char wm=0;unsigned int  adder=32*N;OLED_SetPos(x , y);for(wm = 0;wm < 16;wm++){WriteDat(F16x16[adder]);adder += 1;}OLED_SetPos(x,y + 1);for(wm = 0;wm < 16;wm++){WriteDat(F16x16[adder]);adder += 1;}
}/*** @brief  OLED_DrawBMP,显示BMP位图* @param  x0,y0 :起始点坐标(x0:0~127, y0:0~7);*					x1,y1 : 起点对角线(结束点)的坐标(x1:1~128,y1:1~8)* @retval 无*/
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{unsigned int j=0;unsigned char x,y;if(y1%8==0)y = y1/8;elsey = y1/8 + 1;for(y=y0;y<y1;y++){OLED_SetPos(x0,y);for(x=x0;x<x1;x++){WriteDat(BMP[j++]);}}
}

2.8 LED

/* 包含头文件 ----------------------------------------------------------------*/
#include "bsp/led/bsp_led.h"/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*//*** 函数功能: 板载LED灯IO引脚初始化.* 输入参数: 无* 返 回 值: 无* 说    明:使用宏定义方法代替具体引脚号,方便程序移植,只要简单修改bsp_led.h*           文件相关宏定义就可以方便修改引脚。*/
void LED_GPIO_Init(void)
{/* 定义IO硬件初始化结构体变量 */GPIO_InitTypeDef GPIO_InitStructure;/* 使能(开启)LED1引脚对应IO端口时钟 */  RCC_APB2PeriphClockCmd(LED1_RCC_CLOCKGPIO, ENABLE);/* 设定LED1对应引脚IO编号 */GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;  /* 设定LED1对应引脚IO最大操作速度 :GPIO_Speed_50MHz */GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  /* 设定LED1对应引脚IO为输出模式 */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  /* 初始化LED1对应引脚IO */GPIO_Init(LED1_GPIO, &GPIO_InitStructure);/* 设置引脚输出为低电平,此时LED1灭 */GPIO_SetBits(LED1_GPIO,LED1_GPIO_PIN);  }/*** 函数功能: 设置板载LED灯的状态* 输入参数: LEDx:其中x可甚至为(1,2,3)用来选择对应的LED灯* 输入参数:state:设置LED灯的输出状态。*             可选值:LED_OFF:LED灯灭;*             可选值:LED_ON: LED灯亮。* 返 回 值: 无* 说    明:该函数使用类似标准库函数的编程方法,方便理解标准库函数编程思想。*/
void LEDx_StateSet(uint8_t LEDx,LEDState_TypeDef state)
{/* 检查输入参数是否合法 */assert_param(IS_LED_TYPEDEF(LEDx));assert_param(IS_LED_STATE(state));/* 判断设置的LED灯状态,如果设置为LED灯灭 */if(state==LED_OFF){if(LEDx & LED1)            GPIO_ResetBits(LED1_GPIO,LED1_GPIO_PIN);/* 设置引脚输出为低电平,此时LED1灭 */}else  /* state=LED_ON :否则,设置LED灯为亮 */{if(LEDx & LED1)GPIO_SetBits(LED1_GPIO,LED1_GPIO_PIN);/* 设置引脚输出为高电平,此时LED1亮 */}
}

三、应用

主函数

int main(void)
{   /* 调试串口初始化配置,115200-N-8-1.使能串口发送和接受 */DEBUG_USART_Init(); /*初始化体重*/Init_HX711pin();/* 初始化系统滴答定时器 */  SysTick_Init();HC_SR501_GPIO_Init();OLED_Init();KEY_GPIO_Init();ESP8266_Init();LED_GPIO_Init();wifi_test();Get_Maopi();				//称毛皮重量Delay_us(1000);Get_Maopi();				//重新获取毛皮重量oled_test();/* 无限循环 */while (1){ Get_Weight();printf("净重量 = %d g\r\n",Weight_Shiwu); //打印demo();Delay_ms(1000);}
}

有些串口打印是调试信息,只有ESP8266的发送才是真正要上传到前端的。

前端和后端不是我写的,没有代码,不过感觉不难。

下面是wifi初始话连接的程序

void wifi_test(void)
{printf("正在配置 ESP8266 ......\n" );if(ESP8266_AT_Test()){printf("AT test OK\n");}printf("\n< 1 >\n");if(ESP8266_Net_Mode_Choose(STA)){printf("ESP8266_Net_Mode_Choose OK\n");}  printf("\n< 2 >\n");while(!ESP8266_JoinAP(User_ESP8266_ApSsid,User_ESP8266_ApPwd));printf("\n< 3 >\n");ESP8266_Enable_MultipleId(DISABLE);	while(!ESP8266_Link_Server(enumTCP,User_ESP8266_TcpServer_IP,User_ESP8266_TcpServer_Port,Single_ID_0));	printf("\n< 4 >\n");while(!ESP8266_UnvarnishSend());	printf("配置 ESP8266 完毕\n");
}

下面是对OLEd的初始化

void oled_test(void)
{uint8_t i;OLED_Fill(0xFF);//全屏点亮Delay_ms(2000);OLED_Fill(0x00);//全屏灭Delay_ms(2000);for(i=4;i<=10;i++){OLED_ShowCN((i-4)*16,0,i);									//测试显示中文}Delay_ms(2000);OLED_CLS();//清屏show((uint8_t *)"0",(uint8_t *)"0",(uint8_t *)"0");Delay_ms(2000);//    OLED_OFF();//测试OLED休眠
//    Delay_ms(2000);
//    OLED_ON();//测试OLED休眠后唤醒
//    OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP2);//测试BMP位图显示
//    Delay_ms(20000);
}

下面是显示函数,里面都是我用字模取的字

void show(uint8_t *a,uint8_t *b, uint8_t *c)
{OLED_ShowCN(0,0,11);//进OLED_ShowCN(16,0,6);//站OLED_ShowCN(32,0,7);//人OLED_ShowCN(48,0,13);//数OLED_ShowCN(64,0,14);//:OLED_ShowStr(80,0,a,2);OLED_ShowCN(0,2,12);//出OLED_ShowCN(16,2,6);//站OLED_ShowCN(32,2,7);//人OLED_ShowCN(48,2,13);//数OLED_ShowCN(64,2,14);//:OLED_ShowStr(80,2,b,2);OLED_ShowCN(0,4,6);//站OLED_ShowCN(16,4,15);//内OLED_ShowCN(32,4,7);//人OLED_ShowCN(48,4,13);//数OLED_ShowCN(64,4,14);//:OLED_ShowStr(80,4,c,2);
}

 然后因为用不了库函数的整型转字符串,又自己写了一个

char *itoa_my(int value,char *string,int radix)
{char zm[37]="0123456789abcdefghijklmnopqrstuvwxyz";char aa[100]={0};int sum=value;char *cp=string;int i=0;if(radix<2||radix>36)//增加了对错误的检测{return string;}if(value<0){return string;}while(sum>0){aa[i++]=zm[sum%radix];sum/=radix;}for(int j=i-1;j>=0;j--){*cp++=aa[j];}*cp='\0';return string;
}

然后是读取wifi发过来的数据

u32 wifi_rec(void)
{u32 pCH,a = 0;ESP8266_ReceiveString(ENABLE);if ( strEsp8266_Fram_Record .InfBit .FramFinishFlag ){strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ]  = '\0';printf ( "\r\n%s\r\n", strEsp8266_Fram_Record .Data_RX_BUF );/*将接收到的字符串转成整形数*/pCH=atoi(strEsp8266_Fram_Record .Data_RX_BUF);switch(pCH){case 0:LED1_ON;printf("1111111111111111111\r\n");a = 0;//进站break;case 1:LED1_OFF;printf("22222222222222222222\r\n");a = 1;//出站break;}         }  return a;
}

完整的测试demo

void demo(void)
{if(wifi_rec() == 0){if((Weight_Shiwu >= 100) && (HC_SR501_StateRead()==HC_SR501_HIGH)){inbound++;GPIO_ResetBits(LED1_GPIO,LED1_GPIO_PIN);//亮printf("%d\r\n",inbound);}else{printf("无人\r\n"); //打印GPIO_SetBits(LED1_GPIO,LED1_GPIO_PIN);//灭}}else if(wifi_rec() == 1){if((Weight_Shiwu >= 100) && (HC_SR501_StateRead()==HC_SR501_HIGH)){outbound++;GPIO_ResetBits(LED1_GPIO,LED1_GPIO_PIN);//亮printf("%d\r\n",inbound);}else{printf("无人\r\n"); //打印GPIO_SetBits(LED1_GPIO,LED1_GPIO_PIN);//灭}}else{//error}station = inbound - outbound;printf("%d+%d+%d",inbound,outbound,station);sprintf(cStr,"%d+%d+%d",inbound,outbound,station);ESP8266_SendString(ENABLE,cStr,0,Single_ID_0);               //发送数据		OLED_CLS();//清屏Delay_ms(20);itoa_my(inbound,in,10);itoa_my(outbound,out,10);itoa_my(station,s,10);show((u8 *)in,(u8 *)out,(u8 *)s);
}

 

四、中断

 

/********************************************************************************* @file    Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c * @author  MCD Application Team* @version V3.5.0* @date    08-April-2011* @brief   Main Interrupt Service Routines.*          This file provides template for all exceptions handler and *          peripherals interrupt service routine.******************************************************************************* @attention** THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.** <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>*******************************************************************************//* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
#include "bsp/systick/bsp_SysTick.h"
#include "bsp/ESP8266/bsp_esp8266.h"
#include <string.h>/** @addtogroup STM32F10x_StdPeriph_Template* @{*/
__IO uint8_t ucTcpClosedFlag = 0;
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*//******************************************************************************/
/*            Cortex-M3 Processor Exceptions Handlers                         */
/******************************************************************************//*** @brief  This function handles NMI exception.* @param  None* @retval None*/
void NMI_Handler(void)
{
}/*** @brief  This function handles Hard Fault exception.* @param  None* @retval None*/
void HardFault_Handler(void)
{/* Go to infinite loop when Hard Fault exception occurs */while (1){}
}/*** @brief  This function handles Memory Manage exception.* @param  None* @retval None*/
void MemManage_Handler(void)
{/* Go to infinite loop when Memory Manage exception occurs */while (1){}
}/*** @brief  This function handles Bus Fault exception.* @param  None* @retval None*/
void BusFault_Handler(void)
{/* Go to infinite loop when Bus Fault exception occurs */while (1){}
}/*** @brief  This function handles Usage Fault exception.* @param  None* @retval None*/
void UsageFault_Handler(void)
{/* Go to infinite loop when Usage Fault exception occurs */while (1){}
}/*** @brief  This function handles SVCall exception.* @param  None* @retval None*/
void SVC_Handler(void)
{
}/*** @brief  This function handles Debug Monitor exception.* @param  None* @retval None*/
void DebugMon_Handler(void)
{
}/*** @brief  This function handles PendSVC exception.* @param  None* @retval None*/
void PendSV_Handler(void)
{
}/*** @brief  This function handles SysTick Handler.* @param  None* @retval None*/
void SysTick_Handler(void)
{TimingDelay_Decrement();
}void ESP8266_USART_INT_FUN(void)
{uint8_t ucCh;if ( USART_GetITStatus (ESP8266_USARTx, USART_IT_RXNE ) != RESET ){ucCh  = USART_ReceiveData(ESP8266_USARTx );if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )                       //预留1个字节写结束符strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ]  = ucCh;}if ( USART_GetITStatus(ESP8266_USARTx, USART_IT_IDLE ) == SET )                                         //数据帧接收完毕{strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;ucCh = USART_ReceiveData(ESP8266_USARTx );ucTcpClosedFlag = strstr(strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;}
}/******************************************************************************/
/*                 STM32F10x Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f10x_xx.s).                                            */
/******************************************************************************//*** @brief  This function handles PPP interrupt request.* @param  None* @retval None*/
/*void PPP_IRQHandler(void)
{
}*//*** @}*/ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

---------------------------------------------------------------------------------------------------------------------------------

以后上传新项目只发应用层。驱动新驱动才发

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_102983.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android framework-ActivityManagerService(AMS)下

一、ActivityThread \frameworks\base\core\java\android\app\ActivityThread.java 1.1、main public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// Install selective syscall interceptionAnd…

Hudi数据湖技术之核心概念

目录 1 基本概念1.1 时间轴Timeline1.2 文件管理1.3 索引Index 2 存储类型2.1 计算模型2.1.1 批式模型&#xff08;Batch&#xff09;2.1.2 流式模型&#xff08;Stream&#xff09;2.1.3 增量模型&#xff08;Incremental&#xff09; 2.2 查询类型&#xff08;Query Type&…

4.3调整基类成员在派生类中的访问属性的方法

同名成员 在定义派生类的时候&#xff0c;C语言允许派生类与基类中的函数名相同。如果在派生类中定义了与基类中相同的成员&#xff0c;则称派生类成员覆盖了基类的同名成员&#xff0c;在派生类中使用这个名字意味着访问在派生类中重新说明的成员。为了在派生类中使用基类的同…

C++ -4- 类和对象(下)

文章目录 1.初始化列表什么是初始化列表&#xff1f;初始化列表的 意义及使用 2.explicit关键字单参数构造函数&#xff08;C98&#xff09;多参数的构造函数&#xff08;C11&#xff09;&#xff08;了解&#xff09; 3.static静态成员静态成员变量与静态成员函数静态成员变量…

前端02:CSS选择器等基础知识

CSS基础选择器、设置字体样式、文本样式、CSS的三种引入方式、能使用Chrome调试工具调试样式 HTML专注做结构呈现&#xff0c;样式交给CSS&#xff0c;即结构&#xff08;HTML&#xff09;和样式CSS相分离 CSS主要由量分布构成&#xff0c;选择器以及一条或多条声明 选择器&…

18.Java泛型

目录 1. Java基本介绍 2. JDK下载安装及其环境配置 3. 一个简单的java程序 4. Eclipse基本使用、数据类型、运算符 5. 控制语句&#xff08;if、switch、for、while、foreach&#xff09; 6. Java数组 7. Java字符串对象(String|StringBuffer|StringBuilder|StringJoiner…

OFDM-LS信道估计 MMSE信道估计公式推导

假设ofdmN个子载波之间是完全正交的&#xff0c;即不考虑ICI影响&#xff0c;通过发送训练序列来实现信道估计。 其中&#xff0c;在推导6.8的时候&#xff0c;需要将6.6先拆解一下。 X − 1 Y X − 1 ( X H Z ) X − 1 X H X − 1 Z H X − 1 Z X^{-1}Y X^{-1}(XHZ)…

LeetCode213 打家劫舍 II 动态规划法

题目地址 https://leetcode.cn/problems/house-robber-ii/ 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 &#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装…

【Hive实战】探索Hive 2.X以及更早版本的MetaStore

探索Hive 2.X以及更早版本的MetaStore 文章目录 探索Hive 2.X以及更早版本的MetaStore概述配置元数据服务和元数据存储库基础配置参数其他配置参数默认配置配置元服务数据库使用内嵌模式的Derby库使用远程数据存储库 配置元数据服务本地/内嵌服务配置远程服务配置 元数据服务配…

【KingSCADA】什么是精灵图以及如何创建精灵图

大家好&#xff0c;我是雷工&#xff01; 本篇学习精灵图的制作&#xff0c;以下为学习内容及相关笔记。 一、什么是精灵图 精灵图是一种在外观上类似组合图&#xff0c;但内部嵌入了比较丰富的动画链接与逻辑控制&#xff0c;工程开发人员只要将其从精灵图库中调出来放置在开…

MySQL基础练习——创建数据库、数据表,并进行修改

目录 题目&#xff1a; 创建库和表&#xff1a; 创建库&#xff1a; 创建表&#xff1a; 将 c_contact 字段插入到 c_birth 字段后面&#xff1a; 将 c_name 字段数据类型改为VARCHAR(70)&#xff1a; 将 c_contact 字段改名为 c_phone&#xff1a; 将表名修改为 customer…

AD9208调试经验分享

背景概述 FMC137 是一款基于 VITA57.4 标准规范的 JESD204B 接口FMC 子 卡 模 块 &#xff0c; 该 模 块 可 以 实 现 4 路 14-bit 、 2GSPS/2.6GSPS/3GSPSADC 采集功能。该板卡 ADC 器件采用 ADI 公司的 AD9208 芯片&#xff0c;&#xff0c;与 ADI 公司的 AD9689 可以实现 …

量子力学 学习

对于同一个竖直向上量子比特&#xff0c;不对他进行任何的干扰&#xff0c;进行第一次水平测试实验会随机得到一个一或者负一&#xff0c;之后再进行多少次水平测试实验都与第一次的试验结果是相同的。 我们换用其他的竖直向上量子比特&#xff0c;或者对原来的量子比特进行干扰…

Matlab绘图中的一些技能

目录 1、matlab坐标轴设置多种字体(复合字体) 2、matlab图片中title生成的标题转移至图像下端 3、指定对应格式和期望dpi的图像进行保存、以及不留白保存 4、设置字体字号&#xff08;x、y轴&#xff0c;标题。全局字体等&#xff09; 5、设置刻度值信息&#xff0c;只有左…

引领文旅新体验!实时云渲染助力打造“永不落幕”的湾区文采会元宇宙

2022年11月25日至27日&#xff0c;2022年粤港澳大湾区公共文化和旅游产品&#xff08;东莞&#xff09;采购会&#xff08;简称“湾区文采会”&#xff09;在广东省东莞市文化馆举行。 文采会期间&#xff0c;文采会元宇宙线上虚拟展厅全新亮相&#xff0c;这艘承载着科技与文化…

5款十分小众的软件,知道的人不多但却很好用

今天推荐5款十分小众的软件&#xff0c;知道的人不多&#xff0c;但是每个都是非常非常好用的&#xff0c;有兴趣的小伙伴可以自行搜索下载。 1.视频直播录制——OBS Studio OBS Studio可以让你轻松地录制和直播你的屏幕、摄像头、游戏等内容。你可以使用OBS Studio来创建多种…

Mysql设置表只存储一段时间的数据

使用MySQL的事件调度器&#xff08;Event Scheduler&#xff09;来定期删除表中的数据。 假设你要删除的表是mytable&#xff0c;并且表中有一个名为created_at的日期时间类型的列&#xff0c;存储了每条记录的创建时间。你可以通过以下步骤设置表只存储30天的数据&#xff1a…

机器学习 协同过滤算法

协同过滤算法 协同过滤算法是根据已有的数据来推测出未知的数据&#xff0c;从海量的数据中找到相似度达到指定范围的数据&#xff0c;而这些数据成为你的邻居&#xff0c;系统将会为你推荐心仪的物品。 余弦相似法 通过计算两个向量的夹角余弦值来评估它们的相似度 修正余弦…

《站在巨人的肩膀上学习Java》

Java从诞生距今已经有28年了&#xff0c;在这段时间里&#xff0c;随着Java版本的不断迭代&#xff0c;Java新特性的不断出现&#xff0c;使得Java被使用的越来越广泛。在工程界Java语言一直是大家最喜欢的语言之一&#xff0c;Java一直排行在编程语言热门程度的前3名。 可想而…

从0搭建Vue3组件库(六):前端流程化控制工具gulp的使用

随着前端诸如webpack&#xff0c;rollup&#xff0c;vite的发展&#xff0c;gulp感觉似乎好像被取代了。其实并没有&#xff0c;只不过它从台前退居到了幕后。我们仍然可以在很多项目中看到它的身影&#xff0c;比如elementplus、vant等。现在gulp更多的是做流程化的控制。 比如…