ESP8266WiFi模块实现代码

2023-05-16

ESP8266WiFi模块实现TCP连接服务器

在前面的博客里(STM32-ESP8266wifi模块实现)说到了通过AT命令配置ESP8266实现TCP连接。
他的流程是,
1,使能串口,及中断。
2,发送AT指令到ESP8266WiFi模块,进行配置一些参数。

串口配置

串口初始化

// //配置串口,串口初始化。(usart1/usart2)
void MX_USART1_UART_Init(void)
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;//设置波特率
  huart1.Init.WordLength = UART_WORDLENGTH_8B;//字长为8位数据格式
  huart1.Init.StopBits = UART_STOPBITS_1;//一个停止位
  huart1.Init.Parity = UART_PARITY_NONE;//无奇偶校验位
  huart1.Init.Mode = UART_MODE_TX_RX;//收发模式
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)//初始化
  {
    Error_Handler();
  } 
 //在这个函数里使能usart1的接收中断,中断接收的每个字节存储在 uart1_receive_rx 中
  HAL_UART_Receive_IT(&huart1 , &uart1_receive_rx, 1);
}
void MX_USART2_UART_Init(void)
{
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;//设置波特率
  huart2.Init.WordLength = UART_WORDLENGTH_8B;//字长为8位数据格式
  huart2.Init.StopBits = UART_STOPBITS_1;//一个停止位
  huart2.Init.Parity = UART_PARITY_NONE;//无奇偶校验位
  huart2.Init.Mode = UART_MODE_TX_RX;//收发模式
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)//初始化
  {
    Error_Handler();
  }
 //使能usart2的接收中断,中断接收的每个字节存储在 uart2_receive_rx 变量中
//每接收一个字节就会进入一次中断USART1_IRQHandler
//处理数据的函数,读取接收寄存器,将数据赋值给结构体huart的pRxBuffer并清除中断标志,
  HAL_UART_Receive_IT(&huart2 , &uart2_receive_rx, 1);
}
HAL_UART_Receive_IT(&huart1 , uint8_t *pData, uint16_t Size);

功能:串口中断接收,以中断方式接收指定长度数据。大致过程是,设置数据存放位置,接收数据长度,然后使能串口接收中断。接收到数据时,会触发串口中断。再然后,串口中断函数处理,直到接收到指定长度数据,而后关闭中断,进入中断接收回调函数,不再触发接收中断。(只触发一次中断)

参数:

UART_HandleTypeDef *huart 操作句柄
*pData 接收到的数据存放地址
Size 接收的字节数

GPIO配置及开启中断

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();//使能串口USART1时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIO时钟
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
   
    */配置GPIO
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	//根据GPIO_INITTypeDef结构体中Pin来找到对应的要操作的引脚位置
	//初始化我们需要用到的引脚的工作模式,包括具体引脚的工作速度、是否复用模式、上下拉等等参数。
    
    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  
  }
  else if(uartHandle->Instance==USART2)
  {
  
    /* USART2 clock enable */
    __HAL_RCC_USART2_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART2 GPIO Configuration
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    //根据GPIO_INITTypeDef结构体中Pin来找到对应的要操作的引脚位置
    //初始化我们需要用到的引脚的工作模式,包括具体引脚的工作速度、是否复用模式、上下拉等等参数。

    /* USART2 interrupt Init */
    HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART2_IRQn);
  
  }
}

初始化之后的引脚恢复成默认的状态–各个寄存器复位时的值

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART1)
  {
  
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
    //将初始化之后的引脚恢复成默认的状态–各个寄存器复位时的值
	
    /* USART1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART1_IRQn);
 
  }
  else if(uartHandle->Instance==USART2)
  {
  
    /* Peripheral clock disable */
    __HAL_RCC_USART2_CLK_DISABLE();

    /**USART2 GPIO Configuration
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
	//将初始化之后的引脚恢复成默认的状态–各个寄存器复位时的值

    /* USART2 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART2_IRQn);
  
  }
}

串口中断服务函数

串口产生中断,就会自动调用USART1_IRQHandler,USART2_IRQHandler中断服务函数,以串口1USART1为例;

void USART1_IRQHandler(void)                	
{ 
	uint32_t timeout=0;
  	uint32_t maxDelay=0x1FFFF;
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	
	HAL_UART_IRQHandler(&huart1);	//调用HAL库中断处理函数,通过这个中断处理函数会调用UART_Receive_IT(huart);
	
	timeout=0;
    while (HAL_UART_GetState(&huart1)!=HAL_UART_STATE_READY)//等待就绪
	{
        timeout++;超时处理
        if(timeout>maxDelay)
        	break;		
	}
	timeout=0;
	while(HAL_UART_Receive_IT(&huart1,uart1_receive_rx, 1)!=HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1
	{
        timeout++; //超时处理
        if(timeout>maxDelay) 
        	break;	
	}
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
} 

这个函数中,首先调用HAL_UART_IRQHandler(&huart1);
其主要用于判断中断类型。通过这个中断处理函数会调用UART_Receive_IT(huart);
该函数是将接收到的数据保存到指定的串口缓冲区,也就是变量uart1_receive_rx;。该函数每执行一次(接受一个字符),pRxBufferPtr指针加1,并保存接收到的字符到 uart1_receive_rx ,同时RxXferCount数据减1;接着再判断,RxXferCount自减后是否等于0.如果等于0 ,则关闭接收完成中断,进行中断回调函数。如果需要再一次开启时。需要再一次开启中断,也就是调用 HAL_UART_Receive_IT()函数

定义接收buffer

我们在usart.c 文件中要定义相关中断接收buffer。

//USART1
static uint8_t  uart1_receive_rx;
char	        buf1[256];
uint8_t			uart1_b;
//USART2
static uint8_t	uart2_receive_rx;
char			buf2[256];
uint8_t			uart2_b;

中断接收回调函数

//将uart1,uart2接收数据加进buf中。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if (huart->Instance == USART1)
	{		
			if( uart1_b< sizeof(uart1_receive_buf) )
			{
				buf2[uart1_b++] = uart1_receive_rx;
			}
			HAL_UART_Receive_IT(&huart1 , &uart1_receive_rx, 1);
	}

	if (huart->Instance == USART2)
	{
			if( uart1_b< sizeof(buf2) )
			{
				buf2[uart2_b++] = uart2_receive_rx;
			}
			HAL_UART_Receive_IT(&huart2 , &uart2_receive_rx, 1);
	}
}

下面一张流程图也可以很好的理解串口中断接收:
在这里插入图片描述
函数流程图:

HAL_UART_Receive_IT(中断接收函数) -> USART_IRQHandler(void)(中断服务函数) -> HAL_UART_IRQHandler(UART_HandleTypeDef *huart)(中断处理函数) -> UART_Receive_IT(UART_HandleTypeDef *huart) (接收函数) -> HAL_UART_RxCpltCallback(huart);(中断回调函数)

串口发送数据:

HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

功能:串口发送指定长度的数据。如果超时没发送完成,则不再发送,返回超时标志(HAL_TIMEOUT)。
参数:

UART_HandleTypeDef *huart 转发huart1/huart2的句柄
*pData 需要发送的数据
Size 发送的字节数
Timeout 最大发送时间,发送数据超过该时间退出发送

//举例:
HAL_UART_Transmit(&huart1, uart1_receive_rx, uart1_b, 0xffff);   //串口发送uart1_b字节数据,最大传输时间0xffff

串口的转发函数

// 这个函数在我们来手动测试AT命令时需要用到串口转发函数,下篇博文会自动完成相关AT命令的操作;
void uart_forward(void)
{
	if ( strstr(buf1, "/r/n") )
	{
			HAL_UART_Transmit(&huart2 ,(uint8_t *)buf1, uart1_b, 0xFF);//最大传输时间0xFF
			clear_buf1();//这是一个宏用来清理buf1中的数据。保证每次转发的数据都是最新的数据
	}
	if ( uart2_b > 0{
		HAL_UART_Transmit(&huart1, (uint8_t *)buf2, uart2_b, 0xFF);
		clear_buf2(); 
	}

}
//宏定义:
extern char                     buf1[256];
extern uint8_t                 uart1_b;

#define clear_buf1() do { memset( buf1, 0, sizeof(buf1)); \
								 uart1_b=0; } while(0)


extern char                      buf2[256];	
extern uint8_t                   uart2_b;

#define clear_buf2() do { memset(buf2, 0, sizeof(buf2)); \
								 uart2_b=0; } while(0)

这样我们可以用AT命令从串口接收数据到转发数据来配置esp8266wifi模块。

esp8266.c

接下我们写一下通过AT命令连接WiFi和连接服务器的代码;

一、ESP8266WiFi模块初始化
1, AT+RST 重启、复位ESP8266命令
2, AT 确认模块是否正常工作
3, AT+GMR 获取WiFi模块的软件版本信息
4, AT+CWMODE_CUR=1 设置WiFi为Station模式
5, AT+CWDHCP_CUR=1,1 设置使能Station模式的DHCP服务;
二、连网
1, AT+CWJAP_CUR=“路由器的ID”,“密码” 连接无线路由器
2, AT+CIPSTA_CUR? 查询是否获取到IP地址
三、TCP连接
3, AT+CIPSTART=“TCP”,“192.168.2.172”,12345 IP和端口
4,AT+CIPSEND=bytes (等收到模块返回 > 后再输入bytes个字节数据将会通过WiFi模块发送出去;)
5, AT+CIPCLOSE //关闭TCP连接;

但是,由于这个流程是我们自己需要每次使用AT指令去实现,比较麻烦。所以我们自己需要编写程序代码来自动实现这些功能。 这样,我们就可以直接连接好服务器来接收ESP8266WiFi模块发送到服务器的数据了。

在写代码之前我们做一个简单的梳理,我们现在可以通过桥接好的串口1,2给esp8266wifi模块发送AT命令了,具体流程是:pc通过串口1发送AT命令到串口转发程序(通信猫测试软件;)然后通过串口2转发AT命令到esp8266wifi模块; 每当我们发送一个AT命令完成时,esp8266WiFi模块都会做相应的reply,正确执行会reply “AT命令加OK”;否则会reply "At命令加ERROR ";
比如:
在这里插入图片描述

// 我们将实现的功能按模块来封装,每一个函数模块来执行相应地功能,最后将其连贯成一个功能;
//WiFi模块初始化,这个函数是用来初始化WiFi模块的一些配置,如设置station模式,使能DHCP自动获取IP
//这个函数是一个无参函数,相对于连接WiFi和连接服务器函数来说,只需要输入我们的所配置的AT指令,不需要变化;
void esp8266_wifi_init(void)
{
	AT_send("AT+RST\r\n", 500);
	clear_buf();
	HAL_Delay(500);
	
	AT_send("AT\r\n");
	clear_buf();
	
	AT_send("AT+GMR"\r\n, 500);
	clear_buf();

	AT_send("AT+CWMODE_CUR=1", 500);
	clear_buf();
	
	AT_send("AT+CWDHCP_CUR=1,1", 500);
	clear_buf();
}

//发送AT指令函数,将AT指令发送到串口2。
//之前我们实现了AT指令从串口1一接收,发送给串口2,串口2转发到esp8266.
int AT_send(char *at_buf2, unsigned int timeout)//timeout:
{
		int 			rv = -1;
	   unsigned int 			i;// 0 - 255
			
		if(!at_buf2 || strlen(at_buf2) <= 0)
		{
			return -1;
			esp8266wifi_print("error to get data\r\n");
		}
		esp8266wifi_print("Start to send AT command to esp8266\n");
		HAL_UART_Transmit(wifi_huart2, (uint_8 *)at_buf2, strlen(at_buf2), 1000);
		//当我们发送一个数据到esp8266WiFi模块,它会reply;
		for(i=0; i<timeout; i++)
		{
			if (strstr(at_buf2, "OK\r\n"))
			{
					rv = 0;
					esp8266wifi_print("\r\nget data%s", at_buf2);
					return 0}
			if (strstr(at_buf2, "ERROR\r\n"))
			{
					rv = 1;
					esp8266wifi_print("\r\n error to get data:%s", at_buf2);
					return 1}
			if (strstr(at_buf2, "FAIL\r\n"))
			{
					rv = 1;
					esp8266wifi_print("\r\n error to connecte WIFI");
			}
			HAL_Delay(5);
			return 0;	
		}	
}
//接下来我们初始化完成之后就可以去加入网络了,连接WiFi;
int esp8266_enter_network(char 	*id, char *password)
{
	int 	rv ;
	char	at_buf2[256];
	if (!id || strlen(password) <= 0)
	{
		esp8266wifi_print("\r\n error to get data");
		return -1;
	}
	memset(at_buf2, 0, sizeof(at_buf2));
	snprintf(at_buf2, sizeof(at_buf2), "AT+CWJAP_CUR="%s","%s"\r\n", id, password);
	
	AT_send(at_buf2, 8000);
	chear_buf();
	return 0;
}
//下面我们就可以连接服务器了。
int esp8266_socket_connecte(char *serverip, int port)
{
	char at_buf2[256];
	int  rv = -1;
	if (!serverip || !port)
	{
		esp8266wifi_print("\r\n error to get data");
		return  rv;
	} 
	AT_send("AT+CIPMUX=0\r\n", 500);
	memset(at_buf2, 0, sizeof(at_buf2));
	snprintf(at_buf2, sizeof(at_buf2), "AT+CIPSTART="%s","%d"\r\n", serverip, port);
	
	AT_send(at_buf2,500);
	clear_buf();
}
int esp8266_socket_disconnecte(void)
{
	int 	rv=0;
	AT_send("AT+CIPCLOSE\r\n", 500);
	return rv;
}

//下面就可以发送数据给server了。
int sock_send_data(unsigned char *data, int at_uart2_bytes)
{
	int  sta;
	char 	at_buf2[64];
	memset(at_buf2, 0, sizeof(at_buf2));
	snprintf(at_buf2, sizeof(at_buf2), "AT+CIPSEND="%d"\r\n", at_uart2_bytes);
	
	if (strstr(at_buf2, ">\r\n"))
	{
		sta = 1;
		esp8266wifi_print("send data to server\r\n");
	}
	else
	{
	  sta = 0;
	  esp8266wifi_print("send data to server error\r\n");
	}
	if (sta != 0)
	{
		AT_send_data(data, at_uart2_bytes, 800);
		return at_uart2_bytes;
	}
}
//发送我们编写数据data的函数,用来发送我们想要给server的信息;
int AT_send_data(unsigned char *data, int at_uart2_bytes, unsigned char timeout)
{
	int rv = -1;
	unsigned int 	i;
	if (!data || at_uart2_bytes <= 0)
	{
			esp8266wifi_print("ERROR %s:%d %s(): Invalid input arguments\r\n", __FILE__, __LINE__, __FUNCTION__);
		return -1;
	}
	esp8266wifi_print(">>>Start to send data \r\n");
	clear_buf();
	HAL_UART_Transmit(wifi_huart2, (uint8_t *)data, at_uart2_bytes, 1000);
	
	for (i=0; i<timeout; i++)
	{
		if (strstr(at_buf2, "OK\r\n"))
		{
			rv = 0;
			esp8266wifi_print(">>>Start to send data :%s\r\n", at_buf2);
			return rv;
		}
		if (strstr(at_buf2, "ERROR\r\n"))
		{
			rv =1;
			esp8266wifi_print(">>>Start to send data error:%s\r\n", at_buf2);
			return rv;
		}
		HAL_Delay(5);
	}
}

esp8266.h

#ifndef _ESP8266_H_
#define	_ESP8266_H_


#define  at_buf2	      buf2
#define  at_uart2_bytes   uart2_b
#define  wifi_huart2      huart2

#ifdef CONFIG_DEBUG_WIFI
#define esp8266wifiprint(format,args...) printf(format, ##args)
#else
#define esp8266wifiprint(format,args...) do{} while(0)
#endif

extern 	void esp8266_wifi_init(void);
extern 	int AT_send(char *at_buf2, unsigned int timeout);
extern int AT_send_data(unsigned char *data, int at_uart2_bytes, unsigned int timeout);
extern  int esp8266_enter_network(char 	*id, char *password);
extern 	int esp8266_socket_connecte(char *serverip, int port);
extern int int esp8266_socket_disconnecte(void);

main.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"esp8266.h"

//添加WiFi ID PASSORD   , serverip, port ,
#define DEF_ROUTER_SSID          "Router_wifi"
#define DEF_ROUTER_PWD           "Router@wifi"
#define DEF_ROUTER_IP            "192.168.101.5"

#define SOCKET_SERVER_IP         "192.168.101.5"
#define SOCKET_SERVER_PORT       12345

//初始化,连接WiFi,连接服务器。
 	esp8266_wifi_init();
 	esp8266_enter_network(DEF_ROUTER_SSID, DEF_ROUTER_PWD);
    esp8266_socket_connecte(SOCKET_SERVER_IP, SOCKET_SERVER_PORT);


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ESP8266WiFi模块实现代码 的相关文章

  • 手把手教你使用Vue搭建注册登录界面及前端源码

    文章目录 一 前言二 概况三 搭建注册页面四 改造登录页面四 整体效果动画演示五 前端源码下载六 后续 一 前言 本文将在vue admin template模板基础上完成搭建注册与登录页面 文末处有完整的前端源码下载 环境准备 浏览器 x
  • 从传感器和算法原理讲起,机器人是如何避障的

    导语 xff1a 本文内容来自大道智创CTO邢志伟在雷锋网硬创公开课的分享 xff0c 由雷锋网旗下栏目 新智造 整理 编者按 xff1a 本文内容来自大道智创CTO邢志伟在雷锋网 公众号 xff1a 雷锋网 硬创公开课的分享 xff0c
  • or1200处理器中的特殊寄存器

    以下内容摘自 步步惊芯 软核处理器内部设计分析 一书 OR1200中的寄存器分为两类 xff1a 通用寄存器r0 r31 特殊寄存器 特殊寄存器又分为11组 xff0c 在本书第1 3 3节简单地列出了所有的特殊寄存器组 从列表中可以发现除
  • 基础面试题 :大端、小端及转换方式

    理解网络中大端和小端往往是一道基础面试题 xff0c 这里作为记录和整理 xff0c 希望能帮到大家 目录 前言 一 字节序 二 什么小端顺序 三 什么大端顺序 四 处理器体系所属网络字节顺序 五 大小端转换 1 大端整形转换为小端 2 小
  • RS485——A与B波形与电路分析

    一 理论知识 发送端 AB间的电压差 xff0b 2 xff5e xff0b 6v 逻辑1 xff0d 2 xff5e xff0d 6v 逻辑0 xff1b 接收端 AB间的电压差 大于 xff0b 200mv 逻辑1 小于 xff0d 2
  • vsCode软件安装code runner插件,运行shell脚本,terminal终端不显示运行结果数据

    问题 vsCode软件安装code runner插件 xff0c 运行shell脚本 xff0c terminal终端不显示运行结果数据 原因分析 运行shell脚本 xff0c 没有指定运行的bash环境 解决办法 在Code runne
  • Microsoft Visual C++ Redistributable 与 Visual C++ 的区别与联系?

    Visual Studio xff1a 是一款开发软件 xff0c 即我们俗称的 IDE xff0c 有很多版本 xff0c 如 Visual Studio 2010 Visual C 43 43 xff1a Visual C 43 43
  • ROS下采用camera_calibration进行单目相机标定

    参考 xff1a https blog csdn net learning tortosie article details 79901255https blog csdn net learning tortosie article det
  • C++使用libcurl做HttpClient

    当使用C 43 43 做HTTP客户端时 xff0c 目前通用的做法就是使用libcurl 其官方网站的地址是http curl haxx se xff0c 该网站主要提供了Curl和libcurl Curl是命令行工具 xff0c 用于完
  • ROS小车打造(十一)--arduino订阅/发布Topic

    1 安装arduino Software Arduino 选择对应的版本下载 xff0c 下载后解压安装运行 sudo tar xvf arduino 1 8 18 linux64 tar tar sudo mv arduino 1 8 1
  • 简单谈谈5G/C-V2X技术与自动驾驶的关系

    一 什么叫自动驾驶 自动驾驶分为 6 个等级 xff1a Level 0 xff1a 人工驾驶 xff0c 无驾驶辅助系统 xff0c 仅提醒 Level 1 xff1a 辅助人工驾驶 xff0c 可实现单一的车速或转向控制自动化 xff0
  • axios详解

    文章目录 axios是干啥的原生XMLHttpRequest实现axios介绍 发送并发请求 axios API 创建一个实例Config配置选项默认设置 全局默认设置实例中自定义默认值设置的优先级 响应信息 response schema
  • 浅谈一下汽车行业中的OTA/FOTA/SOTA

    首先来一个背景知识铺垫 xff1a 被誉为汽车界 苹果 的特斯拉 xff0c 从它的第一款ModelS上市开始 xff0c 截止到2017年3月份的5年时间里 xff0c 总计对车辆推送了25次远程升级 特斯拉每次发布新系统新功能就可以通过

随机推荐

  • 三分钟看懂什么是边缘计算和云计算

    随着科技的发展 xff0c 社会的进步 xff0c 各种尖端科技层出不穷 xff0c 各种新概念和课题也是百花齐放 xff0c 前几年如雨后春笋般涌现出来的大数据 云计算这些个高科技 xff0c 左查右问 xff0c 花了好大工夫好不容易才
  • 如何提升github的clone速度(简单粗暴,亲测有效)

    今天在github上看上了一个项目 xff0c 想要clone到本地来 项目比较大 xff0c clone速度很慢 xff0c 一开始还有50 60k的速度在跑 xff0c 到后来居然给我降到了4K s xff0c 看得实在是蛋疼 于是去百
  • CAN总线数据帧/标准帧/扩展帧/远程帧/错误帧的组成格式对比

    最近在研究CAN总线的驱动 xff0c 需要详细了解数据帧 标准帧 扩展帧 远程帧 错误帧这几种帧的详细组成格式 xff0c 于是收集了一下 xff0c 统一放在这里进行对比和记录 xff0c 以便日后需要时查阅 1 数据帧 标准帧 CAN
  • 图解CAN总线数据的组成和帧格式

    CAN 是Controller Area Network 的缩写 xff08 以下称为CAN xff09 xff0c 是ISO国际标准化的串行通信协议 在汽车产业中 xff0c 出于对安全性 舒适性 方便性 低公害 低成本的要求 xff0c
  • 关于CAN总线的位时间/同步段/传播时间段/相位缓冲段/采样点

    根据 CAN 规范的要求 xff0c 总线上的所有器件都必须使用相同的比特率才能完成通信 然而 xff0c 并非所有器件都要求具有相同的主振荡器时钟频率 所以 xff0c CAN 总线能够在一定的范围内容忍总线上 CAN 节点的通信波特率的
  • NAND FLASH/NOR FLASH/EMMC等存储器的比较和区别

    首先介绍一下NAND FLASH NOR FLASH xff1a Nand Flash xff1a Nand Flash存储器是Flash存储器的一种 xff0c 其内部采用非线性宏单元模式 xff0c 为固态大容量内存的实现提供了廉价有效
  • 如何计算CAN总线的负载率以及每帧耗时和每秒最多传输帧数

    今天遇到一个问题 xff0c 需要计算一下CAN总线上 xff0c 不同的波特率下 xff0c 每秒钟最多能够传输多少帧数据 xff0c 或者说 xff0c 每帧数据需要耗时多少时间 一开始以为这个东西是很基础的确定性数据 xff0c 百度
  • 如何在bat脚本中显示出该脚本文件的相关信息

    今天在研究windows系统下的bat脚本 xff0c 想要在bat脚本运行的过程中 xff0c 输出脚本文件自身的一些信息 xff0c 经过一番查阅和摸索 xff0c 采用以下代码就可以实现 xff1a 64 span class tok
  • 如何在bat脚本中列出指定目录下的所有文件信息

    今天在研究windows系统下的bat脚本 xff0c 想要去遍历一个目录并输出该目录下的所有文件的详细信息 经过一番查找和摸索 xff0c 使用以下代码即可实现 xff1a 64 span class token function ech
  • 解决IDEA导入maven项目Plugin ‘org.apache.maven.pluginsmaven-compiler-plugin‘ not found问题

    问题 xff1a 导入了maven项目 xff0c 报错Plugin org apache maven plugins maven compiler plugin not found等问题 xff0c 不仅仅是 maven compiler
  • ISO11898/ISO14229/ISO14230/ISO15031/ISO15765标准对比简介

    各行各业都有很多的国际标准和规范 xff0c 汽车行业也不例外 xff0c 经常遇到一套一套的标准和规范 xff0c 什么ISO11898 xff0c ISO14229 xff0c ISO14230 xff0c ISO15031 xff0c
  • 如何解决UltraCompare中中文显示乱码的问题

    作为一名程序猿 xff0c 对代码进行对比分析是经常避免不了的 xff0c 这时候就需要一个很好用的对比工具 xff0c 我选择了大名鼎鼎的Ultra Compare 但是 xff0c 使用过程中发现 xff0c 这家伙居然不支持中文 xf
  • 一文简单介绍眼图

    搞通信行业的 xff0c 经常要关注信号的传输质量 xff0c 近几年开始出现了一个新的名词 xff0c 叫眼图 xff0c 可以非常直观的体现出信号传输的情况 那么 xff0c 什么是眼图 xff0c 怎么解读眼图 xff0c 下面就为大
  • 下一代CAN通信技术CAN XL简介

    众所周知 xff0c CAN网络具有易于实现 可扩展 并支持复杂拓扑结构等诸多优点 xff0c 所以目前在各个行业特别是汽车领域 xff0c 得到了非常广泛的应用 但是 xff0c 它也存在着诸多问题 xff0c 其中最大的一点就是总线带宽
  • 聊一下质量管理体系中的DQE/SQE/PQE/CQE

    最近接触了不少质量体系的话题 xff0c 反复的听到SQE DQE等 xff0c 大概知道是跟质量管理相关的一些职位 xff0c 但是具体也不是很清楚 xff0c 于是干脆来理一下 正式开始之前 xff0c 先要介绍一下他们的老祖宗 xff
  • C语言字符串库函数 #include <string.h>

    c语言字符串库函数 include lt string h gt 在头文件 lt string h gt 中定义了两组字符串函数 第一组函数的名字以str开头 xff1b 第二组函数的名字以mem开头 只有函数memmove对重叠对象间的拷
  • gcc编译动态库静态库及Makefile知识汇总;

    gcc编译 动态库静态库及Makefile知识汇总 gcc编译过程gcc的常用选项静态库 xff0c 动态库并制作 xff1b Makefile 基本使用make工具简介 gcc编译过程 我们在Linux下使用vim命令写的 c文件 xff
  • 简单学习一下Linux中的环境变量

    环境变量 最近在学习Linux下的C程序编写 xff0c 在运行可执行程序的时候有个问题就是链接的问题 xff0c 最后通过学习才知道是因为环境变量没有设置好 xff1b 环境变量在进行linux开发过程中经常碰到 xff0c 那什么是环境
  • STM32-ESP8266wifi模块实现

    1 ESP8266WiFi模块介绍 1 1ESP8266wifi 模块 低功耗串口WiFi模块ESP8266内置一个Tensilica xff08 泰思立达 xff09 Xtensa架构的32位处理器L106 xff0c 具有5级流水线 A
  • ESP8266WiFi模块实现代码

    ESP8266WiFi模块实现TCP连接服务器 在前面的博客里 xff08 STM32 ESP8266wifi模块实现 xff09 说到了通过AT命令配置ESP8266实现TCP连接 他的流程是 xff0c 1 xff0c 使能串口 xff