目录
一、概述
二、驱动程序
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>© 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****/
---------------------------------------------------------------------------------------------------------------------------------
以后上传新项目只发应用层。驱动新驱动才发