单片机-STM32 WIFI模块--ESP8266 (十二)
1.WIFI模块--ESP8266
名字由来:
Wi-Fi这个术语被人们普遍误以为是指无线保真(Wireless Fidelity),并且即便是Wi-Fi联盟本身也经常在新闻稿和文件中使用“Wireless Fidelity”这个词,Wi-Fi还出现在ITAA的一个论文中。但事实上,Wi-Fi一词没有任何意义,也是没有全写的。
原理部分
无线网络在无线局域网的范畴是指“无线相容性认证”,实质上是一种商业认证,同时也是一种无线联网技术,以前通过网线连接电脑,而Wi-Fi则是通过无线电波来连网;常见的就是一个无线路由器,那么在这个无线路由器的电波覆盖的有效范围都可以采用Wi-Fi连接方式进行联网,如果无线路由器连接了一条ADSL线路或者别的上网线路,则又被称为热点。
ESP8266外观图:
ESP8266如何通信:
需要使用单片机的串口控制ESP8266
因为ESP8266目前预留的就是。
单片机---》ESP8266
ESP8266的特性:
不同的WIFI模块对比:
了解以下公司:
乐鑫信息科技
安信可
有人科技
移远科技
TCP和UDP的区别
TCP是一种面向连接,可靠的稳定的网络通信方式,连接的时候必须有应答,可以确定数据传输的顺序
UDP连接是一种面向无连接的通信,发送方发送数据,不需要给回复,发送方只负责发送数据,但是数据是否发送完成,不去负责。
2.AT指令集
AT指令集是从终端设备(Terminal Equipment,TE)或数据终端设备(Data Terminal Equipment,DTE)向终端适配器(Terminal Adapter, TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)发送的。
AT指令集是现在已经设置好的一套指令,用于驱动外部设备,如果需要使用AT指令集控制外部设备的话,需要首先熟悉AT操作。
单片机和ESP8266连接图:
为什么使用AT指令集??
1.ESP8266内部已经集成了TCP/IP协议,而且也烧写了相关固件
2.我们的MCU部分只需要像控制OLED屏一样发送指令即可
3.ESP8266控制指令全部用的都是AT指令集
ESP8266相关的AT指令集
AT指令集的四种类型:
比如,我们要查询串口配置:
AT_UART?
设置串口:
AT+UART=<baudrate>,<databits>,<stopbits>,<pa rity>,<flow control>
AT--测试指令
ATE--回显设置
AT+RST--复位
AT+GMR--查询版本信息
AT+CWMODE—设置 Wi-Fi 模式
Station--客户端
SoftAP--服务器
SoftAP+Station--混合模式
AT+CWJAP—连接 AP
AT+CPIMUX--设置连接
AT+CIPMODE—设置传输模式
AT+CIPSTART—建⽴立 TCP 连接, UDP 传输或 SSL 连接
ESP8266透传
AT
ATE0 关闭回显
AT+CWMODE= 1 //客户端
AT+CWJAP="WLL001","123456789" //
AT+CIPMUX=0 //0--单链接AT+CIPSTART1
="TCP","120.76.100.197",10002 //设置服务器IP端口
AT+CIPMODE=1 //透传模式AT+CIPSEND
> //收发数据
注意每一个指令的结尾都需要换行符
[15:24:06.186]发→◇ATOK[15:24:27.367]发→◇AT+CWMODE=1
□
[15:24:27.372]收←◆AT+CWMODE=1OK[15:27:47.266]发→◇AT
□
[15:27:47.271]收←◆ATOK[15:27:51.816]发→◇AT+CWMODE=1
□
[15:27:51.820]收←◆AT+CWMODE=1OK[15:27:55.146]发→◇AT+CWJAP="WLL001","123456789"
□
[15:27:55.153]收←◆AT+CWJAP="WLL001","123456789"[15:28:09.220]收←◆+CWJAP:3FAIL[15:28:43.918]发→◇AT+CWJAP="WLL001","123456789"
□
[15:28:43.925]收←◆AT+CWJAP="WLL001","123456789"[15:28:47.907]收←◆WIFI CONNECTED[15:28:48.731]收←◆
OK
WIFI GOT IP[15:28:53.611]发→◇AT+CIPMUX=0
□
[15:28:53.616]收←◆AT+CIPMUX=0OK[15:29:16.708]发→◇AT+CIPSTART="TCP","192.168.137.1",8080
□
[15:29:16.714]收←◆AT+CIPSTART="TCP","192.168.137.1",8080
CONNECTOK[15:29:42.209]发→◇AT+CIPMODE=1
□
[15:29:42.219]收←◆AT+CIPMODE=1OK[15:30:15.994]发→◇AT+CIPSEND
>
□
[15:30:15.999]收←◆AT+CIPSEND
>busy p...OK>
[15:30:27.237]发→◇hello
□
[15:30:31.699]收←◆http://www.cmsoft.cn
[15:30:47.653]发→◇+++
□
[15:31:23.607]发→◇+++□
[15:31:28.834]发→◇+++□
[15:31:28.837]收←◆+++
[15:31:55.340]发→◇AT+CIPMODE=0□
[15:31:55.346]收←◆AT+CIPMODE=0busy p..
ERROR[15:33:24.341]发→◇AT+CIPSTART="TCP","192.168.137.1",8080
□
[15:33:24.349]收←◆AT+CIPSTART="TCP","192.168.137.1",8080
ALREADY CONNECTEDERROR[15:33:24.560]发→◇AT+CIPSTART="TCP","192.168.137.1",8080
□
[15:33:24.566]收←◆AT+CIPSTART="TCP","192.168.137.1",8080
ALREADY CONNECTED
3.单片机串口配置
1.选择一个串口(串口2 或者串口3 串口4.。。。。都可以)
2.串口的接收中断,用于接收数据
3.判断数据是否接收完成的方式:
a.串口的空闲中断,用于判断数据是否接收完成,(因为接受的数据是不定长)
b.使用定时器进行判断,比如当开始接收数据的时候,打开定时器,当定时器计数3秒还没有数据再次到来,就可以判断数据接收。
4.接收到数据之后,解析数据
查找接收到的字符串中的关键字,比如“Ok”
5.复位管教和使能管教的的配置
随便找两个管教设置为,通用推完输出即可
使能(EN)---驱动ESP8266
RST--拉高--PG14
EN--拉高--PG13
使用的是串口3
TX--PB10
RX--PB11
串口3的配置部分:
void esp8266_Init(void)
{GPIO_InitTypeDef GPIOInitTypeDef;USART_InitTypeDef USARTInitTypeDef;//打开时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//配置PB10--TX PB11--RX//PB10--复用推挽输出GPIOInitTypeDef.GPIO_Pin=GPIO_Pin_10;GPIOInitTypeDef.GPIO_Mode=GPIO_Mode_AF_PP;GPIOInitTypeDef.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIOInitTypeDef);//PB11--浮空GPIOInitTypeDef.GPIO_Pin=GPIO_Pin_11;GPIOInitTypeDef.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB,&GPIOInitTypeDef);//usart3的配置USARTInitTypeDef.USART_BaudRate=115200;USARTInitTypeDef.USART_HardwareFlowControl=USART_HardwareFlowControl_None;USARTInitTypeDef.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;USARTInitTypeDef.USART_Parity=USART_Parity_No;USARTInitTypeDef.USART_StopBits=USART_StopBits_1;USARTInitTypeDef.USART_WordLength=USART_WordLength_8b;USART_Init(USART3,&USARTInitTypeDef);//配置中断//设置空闲中断和接收中断USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);//NVIC_SetPriority(USART3_IRQn,0);//占先优先级:1 次级优先级:1 NVIC_EnableIRQ(USART3_IRQn);USART_Cmd(USART3,ENABLE);}
ESP8266的使能管脚和复位管脚的配置:
void ESP8266_IO_Config(void)
{GPIO_InitTypeDef gpio_initsources;//打开时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);gpio_initsources.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14;gpio_initsources.GPIO_Mode=GPIO_Mode_Out_PP;gpio_initsources.GPIO_Speed=GPIO_Speed_2MHz;//void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);GPIO_Init(GPIOG,&gpio_initsources);
}
串口3中断服务函数:
void USART3_IRQHandler(void)
{u8 data=0;//接收数据--接收中断if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET){USART_ClearITPendingBit(USART3,USART_IT_RXNE);//用于接收ESP8266的数据rxbuff[usart_count++]=USART_ReceiveData(USART3);//打印ESP8266的数据到串口助手上USART1->DR=USART_ReceiveData(USART3);
// printf("0000\r\n");}if(USART_GetITStatus(USART3,USART_IT_IDLE)==SET){
// rxbuff[rx_count++]=USART_ReceiveData(USART3);//清除数据over_flag=1;//一旦进入空闲中断,置1,本次传输结束rx_count=usart_count;//没有用usart_count=0;data=USART_ReceiveData(USART3);//清空缓存区
// printf("11111\r\n");USART_ClearITPendingBit(USART3,USART_IT_IDLE);}
}
数据发送部分:
//发送单个字节函数
void USART3_SendData(char data)
{USART_SendData(USART3,data);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); }void Usart3_SendStr(char *str)
{int i=0;while(*(str+i)!='\0'){USART3_SendData(*(str+i));i++;}while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET){}}
ESP8266每次上电的时候需要复位一下:
u8 Esp8266_AT_test(void)
{//"AT\r\n"char count=0;GPIO_SetBits ( GPIOG, GPIO_Pin_13 );GPIO_SetBits ( GPIOG, GPIO_Pin_14 );printf("\r\nAT测试.....\r\n");delay_ms ( 2000 );while ( count < 10 ){printf("\r\nAT测试次数 %d......\r\n", count);if( esp8266_SendCmd ( "AT\r\n", "OK",NULL,500) ){printf("\r\nAT测试启动成功 %d......\r\n", count);return 1;}//复位以下GPIO_ResetBits ( GPIOG, GPIO_Pin_14 );delay_ms ( 500 ); GPIO_SetBits ( GPIOG, GPIO_Pin_14 );++ count;}return 0;
}
发送AT指令的函数:
1、strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。
2、找到所搜索的字符串,则该函数返回第一次匹配的字符串的地址;
3、如果未找到所搜索的字符串,则返回NULL。
uint8_t esp8266_SendCmd(char *ctl_cmd,char *ret01,char *ret02,uint32_t time)
{uint8_t tim=time;memset(rxbuff,0,sizeof(rxbuff));//发送数据Usart3_SendStr(ctl_cmd);delay_ms(time);//接收数据while(tim--){delay_ms(100);if(over_flag==1)//代表进入了空闲中断,本次接收数据完成{over_flag=0;tim=0;if ( ( ret01 != 0 ) && ( ret02 != 0 ) ) return ( ( bool ) strstr ( rxbuff, ret01 ) || ( bool ) strstr ( rxbuff, ret02 ) ); else if ( ret01 != 0 )return ( ( bool ) strstr ( rxbuff, ret01 ) );elsereturn ( ( bool ) strstr ( rxbuff, ret02 ) );}
// memset(rxbuff,0,sizeof(rxbuff));}//发送完成之后,等待接收数据,比较返回值的内容return 0;}
主函数中的配置:(联网流程)
esp8266_Init();ESP8266_IO_Config();printf("底层配置初始化完成\r\n");Esp8266_AT_test();delay_ms(3000);printf("配置联网模式\r\n");while(!esp8266_SendCmd("AT+CWMODE=1\r\n","OK",NULL,300))
{}printf("配置热点\r\n");
sprintf(buff,"AT+CWJAP=\"%s\",\"%s\"\r\n",WIFI_ID,WIFI_PW);
while(!esp8266_SendCmd(buff,"OK",NULL,1000))
{}printf("配置服务器端\r\n");memset(buff,0,sizeof(buff));sprintf(buff,"AT+CIPSTART=\"TCP\",\"172.20.10.4\",%d\r\n",WIFI_PORT);
while(!esp8266_SendCmd(buff,"OK",NULL,1000))
{}printf("配置透传\r\n");
while(!esp8266_SendCmd("AT+CIPMODE=1\r\n","OK",NULL,500))
{}printf("收发数据\r\n");while(!esp8266_SendCmd("AT+CIPSEND\r\n",">",NULL,10000))
{}
网络部分:
服务器端的配置:
完整配置:
#include "esp8266.h"
#include "stdio.h"
#include "string.h"
#include "delay.h"
#include "stdlib.h"
#include "stdbool.h"
char rxbuff[256]={0};
uint8_t rx_count=0;
uint8_t usart_count=0;
uint8_t over_flag=0;void esp8266_Init(void)
{GPIO_InitTypeDef GPIOInitTypeDef;USART_InitTypeDef USARTInitTypeDef;//打开时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//配置PB10--TX PB11--RX//PB10--复用推挽输出GPIOInitTypeDef.GPIO_Pin=GPIO_Pin_10;GPIOInitTypeDef.GPIO_Mode=GPIO_Mode_AF_PP;GPIOInitTypeDef.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIOInitTypeDef);//PB11--浮空GPIOInitTypeDef.GPIO_Pin=GPIO_Pin_11;GPIOInitTypeDef.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB,&GPIOInitTypeDef);//usart3的配置USARTInitTypeDef.USART_BaudRate=115200;USARTInitTypeDef.USART_HardwareFlowControl=USART_HardwareFlowControl_None;USARTInitTypeDef.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;USARTInitTypeDef.USART_Parity=USART_Parity_No;USARTInitTypeDef.USART_StopBits=USART_StopBits_1;USARTInitTypeDef.USART_WordLength=USART_WordLength_8b;USART_Init(USART3,&USARTInitTypeDef);//配置中断//设置空闲中断和接收中断USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);//NVIC_SetPriority(USART3_IRQn,0);//占先优先级:1 次级优先级:1 NVIC_EnableIRQ(USART3_IRQn);USART_Cmd(USART3,ENABLE);}
void ESP8266_IO_Config(void)
{
GPIO_InitTypeDef gpio_initsources;//打开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
gpio_initsources.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14;
gpio_initsources.GPIO_Mode=GPIO_Mode_Out_PP;
gpio_initsources.GPIO_Speed=GPIO_Speed_2MHz;//void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);GPIO_Init(GPIOG,&gpio_initsources);
}void USART3_IRQHandler(void)
{u8 data=0;//接收数据--接收中断if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET){USART_ClearITPendingBit(USART3,USART_IT_RXNE);//用于接收ESP8266的数据rxbuff[usart_count++]=USART_ReceiveData(USART3);//打印ESP8266的数据到串口助手上USART1->DR=USART_ReceiveData(USART3);
// printf("0000\r\n");}if(USART_GetITStatus(USART3,USART_IT_IDLE)==SET){
// rxbuff[rx_count++]=USART_ReceiveData(USART3);//清除数据over_flag=1;//一旦进入空闲中断,置1,本次传输结束rx_count=usart_count;//没有用usart_count=0;data=USART_ReceiveData(USART3);//清空缓存区
// printf("11111\r\n");USART_ClearITPendingBit(USART3,USART_IT_IDLE);}
}void esp8266_Analysis(void)
{int i=0;if(over_flag==1){printf("000000\r\n");over_flag=0;//开始处理数据
// for(i=0;i<rx_count;i++)printf("rx_data:%s\r\n",rxbuff);}memset(rxbuff,0,sizeof(rxbuff));
}//发送单个字节函数
void USART3_SendData(char data)
{USART_SendData(USART3,data);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); }void Usart3_SendStr(char *str)
{int i=0;while(*(str+i)!='\0'){USART3_SendData(*(str+i));i++;}while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET){}}//发送--AT+.....
uint8_t sendcou=0;
//AT
//回复:OK
//time--每次发送数据等待接受的时间uint8_t esp8266_SendCmd(char *ctl_cmd,char *ret01,char *ret02,uint32_t time)
{uint8_t tim=time;memset(rxbuff,0,sizeof(rxbuff));//发送数据Usart3_SendStr(ctl_cmd);delay_ms(time);//接收数据while(tim--){delay_ms(100);if(over_flag==1)//代表进入了空闲中断,本次接收数据完成{over_flag=0;tim=0;if ( ( ret01 != 0 ) && ( ret02 != 0 ) ) return ( ( bool ) strstr ( rxbuff, ret01 ) || ( bool ) strstr ( rxbuff, ret02 ) ); else if ( ret01 != 0 )return ( ( bool ) strstr ( rxbuff, ret01 ) );elsereturn ( ( bool ) strstr ( rxbuff, ret02 ) );}
// memset(rxbuff,0,sizeof(rxbuff));}//发送完成之后,等待接收数据,比较返回值的内容return 0;}
u8 Esp8266_AT_test(void)
{//"AT\r\n"char count=0;GPIO_SetBits ( GPIOG, GPIO_Pin_13 );GPIO_SetBits ( GPIOG, GPIO_Pin_14 );printf("\r\nAT测试.....\r\n");delay_ms ( 2000 );while ( count < 10 ){printf("\r\nAT测试次数 %d......\r\n", count);if( esp8266_SendCmd ( "AT\r\n", "OK",NULL,500) ){printf("\r\nAT测试启动成功 %d......\r\n", count);return 1;}//复位以下GPIO_ResetBits ( GPIOG, GPIO_Pin_14 );delay_ms ( 500 ); GPIO_SetBits ( GPIOG, GPIO_Pin_14 );++ count;}return 0;
}主函数:#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h>
#include "my_usart1.h"
#include "my_key.h"
#include "delay.h"
#include "my_tim.h"
#include "my_dma.h"
#include "esp8266.h"
#include "string.h"#define WIFI_ID "WLL001"
#define WIFI_PW "123456789"
#define WIFI_PORT 8087#define LED1(x) x?(GPIOB->ODR &=~(0X01<<5)):(GPIOB->ODR |=(0X01<<5))
void Led_Config(void);
void delay_tim(u32 tim);
void led_Breath(void);int main(void)
{char buff[256]={0};// 来到这里的时候,系统的时钟已经被配置成72M。NVIC_SetPriorityGrouping(6);//0---7 占先优先级--7bit 次级优先级4--6bitsystick_Init();Led_Config();usart1_Config(115200);
// key_Config();
// key_Interrupt_Cfg();
// tim3_Ch2_Config();
// DMA1_Config();
// printf("底层配置初始化完成\r\n");
// LED1(1);esp8266_Init();ESP8266_IO_Config();//pG13 PG14printf("底层配置初始化完成\r\n");Esp8266_AT_test();//复位delay_ms(3000);/*AT
AT+CWMODE= 1 //客户端
AT+CWJAP="WLL001","123456789" //
AT+CIPMUX=0 //0--单链接AT+CIPSTART1
="TCP","120.76.100.197",10002 //设置服务器IP端口
AT+CIPMODE=1 //透传模式AT+CIPSEND
> //收发数据*/printf("配置联网模式\r\n");
while(!esp8266_SendCmd("AT+CWMODE=1\r\n","OK",NULL,300))
{}printf("配置热点\r\n");
sprintf(buff,"AT+CWJAP=\"%s\",\"%s\"\r\n",WIFI_ID,WIFI_PW);
while(!esp8266_SendCmd(buff,"OK",NULL,1000))
{}printf("配置服务器端\r\n");memset(buff,0,sizeof(buff));sprintf(buff,"AT+CIPSTART=\"TCP\",\"192.168.137.1\",%d\r\n",WIFI_PORT);
while(!esp8266_SendCmd(buff,"OK",NULL,1000))
{}printf("配置透传\r\n");
while(!esp8266_SendCmd("AT+CIPMODE=1\r\n","OK",NULL,500))
{}printf("收发数据\r\n");while(!esp8266_SendCmd("AT+CIPSEND\r\n",">",NULL,10000))
{}while(1){
// esp8266_SendCmd("AT\r\n","OK",NULL,300);esp8266_Analysis();Usart3_SendStr("hello world");
// Get_Data();delay_ms(1000);LED1(1);delay_ms(1000);LED1(0);delay_ms(1000);}
}
void Led_Config(void)
{//时钟RCC->APB2ENR |=0X01<<3;//配置通用推挽输出GPIOB->CRL &=~(0X0F<<20);//清零GPIOB->CRL |=0x01<<20;//通用推挽输出--10MHZ
}void led_Breath(void)
{u32 i=0;for(i=0;i<1500;i++){LED1(1);delay_us(i);LED1(0);delay_us(1500-i);}for(i=0;i<1500;i++){LED1(1);delay_us(1500-i);LED1(0);delay_us(i);}
}void delay_tim(u32 tim)
{while(tim--);
}
相关文章:

单片机-STM32 WIFI模块--ESP8266 (十二)
1.WIFI模块--ESP8266 名字由来: Wi-Fi这个术语被人们普遍误以为是指无线保真(Wireless Fidelity),并且即便是Wi-Fi联盟本身也经常在新闻稿和文件中使用“Wireless Fidelity”这个词,Wi-Fi还出现在ITAA的一个论文中。…...

linux日志排查相关命令
实时查看日志 tail -f -n 100 文件名 -f:实时查看 -n:查看多少行 直接查看日志文件 .log文件 cat 文件名 .gz文件 zgcat 文件名 在日志文件搜索指定内容 .log文件 grep -A 3 “呀1” 文件名 -A:向后查看 3:向后查看行数 “呀1”:搜…...

每日一题-二叉搜索树与双向链表
将二叉搜索树转化为排序双向链表 问题描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,要求空间复杂度为 O(1),时间复杂度为 O(n),并且不能创建新的结点,只能调整树中结点的指针指向。 数据范围 …...

【多视图学习】Self-Weighted Contrastive Fusion for Deep Multi-View Clustering
Self-Weighted Contrastive Fusion for Deep Multi-View Clustering 用于深度多视图聚类的自加权对比融合 TMM 2024 代码链接 论文链接 0.摘要 多视图聚类可以从多个视图中探索共识信息,在过去二十年中越来越受到关注。然而,现有的工作面临两个主要挑…...

ASK-HAR:多尺度特征提取的深度学习模型
一、探索多尺度特征提取方法 在近年来,随着智能家居智能系统和传感技术的快速发展,人类活动识别(HAR)技术已经成为一个备受瞩目的研究领域。HAR技术的核心在于通过各种跟踪设备和测量手段,如传感器和摄像头࿰…...

C语言:数据的存储
本文重点: 1. 数据类型详细介绍 2. 整形在内存中的存储:原码、反码、补码 3. 大小端字节序介绍及判断 4. 浮点型在内存中的存储解析 数据类型结构的介绍: 类型的基本归类: 整型家族 浮点家族 构造类型: 指针类型&…...

深入理解动态规划(dp)--(提前要对dfs有了解)
前言:对于动态规划:该算法思维是在dfs基础上演化发展来的,所以我不想讲的是看到一个题怎样直接用动态规划来解决,而是说先用dfs搜索,一步步优化,这个过程叫做动态规划。(该文章教你怎样一步步的…...

单片机基础模块学习——数码管(二)
一、数码管模块代码 这部分包括将数码管想要显示的字符转换成对应段码的函数,另外还包括数码管显示函数 值得注意的是对于小数点和不显示部分的处理方式 由于小数点没有单独占一位,所以这里用到了两个变量i,j用于跳过小数点导致的占据其他字符显示在数…...

【大数据】机器学习----------强化学习机器学习阶段尾声
一、强化学习的基本概念 注: 圈图与折线图引用知乎博主斜杠青年 1. 任务与奖赏 任务:强化学习的目标是让智能体(agent)在一个环境(environment)中采取一系列行动(actions)以完成一个…...

flink写parquet解决timestamp时间格式字段问题
背景 Apache Parquet 是一种开源的列式数据文件格式,旨在实现高效的数据存储和检索。它提供高性能压缩和编码方案(encoding schemes)来批量处理复杂数据,并且受到许多编程语言和分析工具的支持。 在我们通过flink写入parquet文件的时候,会遇到timestamp时间格式写入的问题。…...

redis实现lamp架构缓存
redis服务器环境下mysql实现lamp架构缓存 ip角色环境192.168.242.49缓存服务器Redis2.2.7192.168.242.50mysql服务器mysql192.168.242.51web端php ***默认已安装好redis,mysql 三台服务器时间同步(非常重要) # 下载ntpdate yum -y install…...

正则表达式中常见的贪婪词
1. * 含义:匹配前面的元素零次或者多次。示例:对于正则表达式 a*,在字符串 "aaaa" 中,它会匹配整个 "aaaa",因为它会尽可能多地匹配 a 字符。代码示例(Python):…...

CF 339A.Helpful Maths(Java实现)
题目分析 输入一串式子,输出从小到大排列的式子 思路分析 如上所说核心思路,但是我要使用笨方法,输入一串式子用split分割开,但是此时需要用到转义字符,即函数内参数不能直接使用“”,而是“\\”。分割开后…...

SQL 指南
SQL 指南 引言 SQL(Structured Query Language,结构化查询语言)是一种用于管理关系数据库系统的标准计算机语言。自1970年代问世以来,SQL已经成为了数据库管理和数据操作的事实标准。本文旨在为初学者和有经验的数据库用户提供一个全面的SQL指南,涵盖SQL的基础知识、高级…...

DDD架构实战第七讲总结:分层模型和代码组织
云架构师系列课程之DDD架构实战第七讲总结:分层模型和代码组织 一、引言 在前几讲中,我们介绍了领域驱动设计(DDD)的基本构造块和生命周期模型中的聚合。本讲将重点讨论如何将这些构造块和代码组织起来,探讨分层架构和六边形模型,以及如何组织代码结构。 二、工厂和资…...

Python “字典” 实战案例:5个项目开发实例
Python “字典” 实战案例:5个项目开发实例 内容摘要 本文包括 5 个使用 Python 字典的综合应用实例。具体是: 电影推荐系统配置文件解析器选票统计与排序电话黄页管理系统缓存系统(LRU 缓存) 以上每一个实例均有完整的程序代…...

(一)QT的简介与环境配置WIN11
目录 一、QT的概述 二、QT的下载 三、简单编程 常用快捷键 一、QT的概述 简介 Qt(发音:[kjuːt],类似“cute”)是一个跨平台的开发库,主要用于开发图形用户界面(GUI)应用程序,…...

在 Windows 系统上,将 Ubuntu 从 C 盘 迁移到 D 盘
在 Windows 系统上,如果你使用的是 WSL(Windows Subsystem for Linux)并安装了 Ubuntu,你可以将 Ubuntu 从 C 盘 迁移到 D 盘。迁移过程涉及导出当前的 Ubuntu 发行版,然后将其导入到 D 盘的目标目录。以下是详细的步骤…...

vue2的$el.querySelector在vue3中怎么写
这个也属于直接操作 dom 了,不建议在项目中这样操作,不过我是在vue2升级vue3的时候遇到的,是以前同事写的代码,也没办法 先来看一下对比 在vue2中获取实例是直接通过 this.$refs.xxx 获取绑定属性 refxxx 的实例,并且…...

GPSd定时检测保活TCP GPS源
为了在 TCP GPS 源丢失连接时自动重新连接,可以编写一个监控脚本,定期检查 gpspipe 输出中的 TCP 源数据是否存在。如果检测到丢失,则使用 gpsdctl 或直接命令重新添加 TCP 源。 1、工具 检查并安装必要工具,本例需要使用 gpspi…...

IDEA中Maven使用的踩坑与最佳实践
文章目录 IDEA中Maven使用的踩坑与最佳实践一、环境配置类问题1. Maven环境配置2. IDEA中Maven配置建议 二、常见问题与解决方案1. 依赖下载失败2. 依赖冲突解决3. 编译问题修复 三、效率提升技巧1. IDEA Maven Helper插件使用2. 常用Maven命令配置3. 多模块项目配置4. 资源文件…...

使用 Python 调用 OpenAI 的接口初识
使用 Python 调用 OpenAI 的接口非常简单,以下将结合实际代码示例和使用场景进行详细讲解,步骤如下: 文章目录 1. 安装 OpenAI 官方库2. 准备 API Key3. 基本使用示例:调用 ChatGPT**代码示例:****运行结果:…...

2025 最新flutter面试总结
目录 1.Dart是值传递还是引用传递? 2.Flutter 是单引擎还是双引擎 3. StatelessWidget 和 StatefulWidget 在 Flutter 中有什么区别? 4.简述Dart语音特性 5. Navigator 是什么?在 Flutter 中 Routes 是什么? 6、Dart 是不是…...

【MQ】RabbitMq的可靠性保证
消息队列中的可靠性主要是分为三部分: 消息不丢失:确保消息从生产者发送到消费者消息不丢失消息不重复:确保消息不被重复消费消息顺序性:确保消费的顺序性 解决方案主要有以下几部分: 消息不丢失 生产者确认机制持久…...

STM32 GPIO配置 点亮LED灯
本次是基于STM32F407ZET6做一个GPIO配置,实现点灯实验。 新建文件 LED.c、LED.h文件,将其封装到Driver文件中。 双击Driver文件将LED.c添加进来 编写头文件,这里注意需要将Driver头文件声明一下。 在LED.c、main.c里面引入头文件LED.h LED初…...

Flink把kafa数据写入Doris的N种方法及对比。
用Flink+Doris来开发实时数仓,首要解决是如何接入kafka实时流,下面是参考Doris官方文档和代码,在自己项目开发的实践中总结,包括一些容易踩坑的细节。 目录 Routine Load方法 接入kafka实时数据 踩坑的问题细节 Flink Doris Connector方法 完整示例 Routine Load方法…...

Vue - 标签中 ref 属性的使用
在 Vue 3 中,ref 属性用于在模板中引用 DOM 元素或组件实例。通过 ref,可以直接访问这些元素或组件的实例,从而进行更复杂的操作,比如获取元素的尺寸、调用组件的方法等。 基本语法: <template><div ref&qu…...

leetcode-不同路径问题
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? 看见题目…...

MongoDB 数据库备份和恢复全攻略
在当今数据驱动的时代,数据库的稳定运行和数据安全至关重要。MongoDB 作为一款流行的 NoSQL 数据库,以其灵活的文档模型和高扩展性备受青睐。然而,无论数据库多么强大,数据丢失的风险始终存在,因此掌握 MongoDB 的备份…...

CentOS7使用源码安装PHP8教程整理
CentOS7使用源码安装PHP8教程整理 下载安装包解压下载的php tar源码包安装所需的一些依赖扩展库安装前的配置修改配置文件1、进入php8的安装包 配置环境变量开机自启启动服务创建软连接常见问题1、checking for icu-uc > 50.1 icu-io icu-i18n... no2、configure: error: Pa…...