MSP432自主开发笔记6:定时器多通道捕获多条编码器线脉冲数

所用开发板:MSP432P401R

今日在此更新一下编码器测速的定时器捕获写法,之前学习时竟然忘记更新了~~

本文讲如何用定时器的通道来 捕获编码器的脉冲信号数量,不提供速度路程的计算方式,

文章提供源码,测试工程下载;

实践内容:

1.使用定时器TA2捕获四个轮子编码器的信号

2.上升下降沿都捕获

3.串口定时反馈捕获值

程序编写:

程序设计方面十分简单,分为以下步骤,每个步骤有一些注意点:

一、初始化定时器:

            1.关闭定时溢出中断,开启捕获事件的中断

            2.选择合适的定时器频率,略高于编码器最大频率即可

            3.四个通道除了引脚不同,初始化基本一样,结构体名称改改就行

            4.设置为上升沿、下降沿、上升下降沿,三种捕获模式之一,(本文设置为上升下降都捕获    )

二、捕获事件中断服务函数:

            1.因为之前关闭了 定时溢出中断,所以void TA2_N_IRQHandler(void)的进入条件只有捕获事件到来时:(本文捕获事件为:上升下降都是捕获事件    ),就会进一次中断

             2.定时器配置捕获后,可以通过读取TAxIV寄存器来判断是哪个通道传来的捕获事件,借此对其计数。(本文是定时器2,因此读取TA2IV)

             3.     

 有关TAxIV寄存器介绍在801页

 1.初始化定时器TA2四条通道的捕获:

注意点在之前说过了:

开启定时器计时,但关闭计时溢出中断

选择合适的计时溢出频率,这决定了捕获的采样率,比编码器脉冲频率快就行,当然,直接定时器48M也是没有问题的

四条通道初始化相同的

开启TA2端口中断     MAP_Interrupt_enableInterrupt(INT_TA2_N);

//定时器TA2捕获初始化:
void TA2_CAP_init(void)
{
	//四个通道初始化输入
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN7,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,GPIO_PIN7,GPIO_PRIMARY_MODULE_FUNCTION);	
	
	//定时器连续计数模式初始化,关闭定时溢出中断
			const Timer_A_ContinuousModeConfig continuousModeConfig =
		{
						TIMER_A_CLOCKSOURCE_SMCLK,
						TIMER_A_CLOCKSOURCE_DIVIDER_1,  //1分频,分辨率最高48M
						TIMER_A_TAIE_INTERRUPT_DISABLE, 
						TIMER_A_SKIP_CLEAR
		};
//初始化通道1:
				const Timer_A_CaptureModeConfig captureModeConfig_1 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_1, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道2:
				const Timer_A_CaptureModeConfig captureModeConfig_2 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_2, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道3:
				const Timer_A_CaptureModeConfig captureModeConfig_3 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_3, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道4:
				const Timer_A_CaptureModeConfig captureModeConfig_4 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_4, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};		
		
		
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_1);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_2);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_3);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_4);

    MAP_Timer_A_configureContinuousMode(TIMER_A2_BASE, &continuousModeConfig);
    MAP_Interrupt_enableInterrupt(INT_TA2_N);
    MAP_Timer_A_startCounter(TIMER_A2_BASE, TIMER_A_CONTINUOUS_MODE);
}

 2.编写定时器 中断服务函数:

代码中的 Wheel[x].CAPTURE 无须在意,是我给每个轮子定义的结构体,换成普通变量一样用的,这种高速计数脉冲,需要大家时刻注意溢出问题,以下代码段的意思就是防止数据溢出不被记录:

if(Wheel[1].CAPTURE==62700)
					{Wheel[1].CAPTURE=0;Wheel[1].CAT_OUT_TIME++;}

 


//这是捕获事件中断服务函数(因为定时器溢出中断已关闭)
//注意对照引脚看通道,这里通道情况与PWM控制不一样
void TA2_N_IRQHandler(void)
{
    uint16_t captureSource = TA2IV;
// 根据捕获通道来源进行适当的处理
//脉冲计数到62700时刚好车轮转95圈
//大电机减速比30编码器11线
    switch (captureSource) 
			{
        case 0x02:
            // 处理TA2 CCR1通道的捕获中断
						Wheel[1].CAPTURE++;
					if(Wheel[1].CAPTURE==62700)
					{Wheel[1].CAPTURE=0;Wheel[1].CAT_OUT_TIME++;}
            break;
        case 0x04:
            // 处理TA2 CCR2通道的捕获中断
						Wheel[2].CAPTURE++;
					if(Wheel[2].CAPTURE==62700)
					{Wheel[2].CAPTURE=0;Wheel[2].CAT_OUT_TIME++;}		
            break;
        case 0x06:
            // 处理TA2 CCR3通道的捕获中断
						Wheel[3].CAPTURE++;
					if(Wheel[3].CAPTURE==62700)
					{Wheel[3].CAPTURE=0;Wheel[3].CAT_OUT_TIME++;}					
            break;
        case 0x08:
            // 处理TA2 CCR4通道的捕获中断
						Wheel[4].CAPTURE++;
					if(Wheel[4].CAPTURE==62700)
					{Wheel[4].CAPTURE=0;Wheel[4].CAT_OUT_TIME++;}					
            break;
        default: break;	
}
}			

3.32定时器初始化为1s周期,通过串口反馈捕获情况:

//此句放在初始化,主函数开头,初始化32定时器为1s周期
 Tim32_0_Int_Init(47999999,1);


//32定时器初始化函数,传入的aar psc决定了其周期
void Tim32_0_Int_Init(uint32_t aar, uint8_t psc)
{
    MAP_Timer32_initModule(TIMER32_0_BASE, psc, TIMER32_32BIT, TIMER32_PERIODIC_MODE);
    MAP_Timer32_setCount(TIMER32_0_BASE, aar);
    MAP_Timer32_enableInterrupt(TIMER32_0_BASE);
    MAP_Timer32_startTimer(TIMER32_0_BASE, false); //连续计数模式 false
    MAP_Interrupt_enableInterrupt(INT_T32_INT1);
}




/* Timer32 ISR 中断服务函数,1s进一次*/
void T32_INT1_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
		  printf("W1_CAP=%d\r\n",Wheel[1].CAPTURE);
			printf("W2_CAP=%d\r\n",Wheel[2].CAPTURE);
			printf("W3_CAP=%d\r\n",Wheel[3].CAPTURE);
			printf("W4_CAP=%d\r\n",Wheel[4].CAPTURE);
}

整体代码:

#include "main.h"

//单个车轮状态与参数结构体:
Wheel_dat Wheel[5];


int main(void)
{
	  inint_all();   //初始化所有模块
    while (1)
    {  }
}

/* Timer32 ISR */
void T32_INT1_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
		  printf("W1_CAP=%d\r\n",Wheel[1].CAPTURE);
			printf("W2_CAP=%d\r\n",Wheel[2].CAPTURE);
			printf("W3_CAP=%d\r\n",Wheel[3].CAPTURE);
			printf("W4_CAP=%d\r\n",Wheel[4].CAPTURE);
}


//初始化所有模块
void inint_all(void)
{
    SysInit();                                  //时钟配置    
    delay_init();								 								//delay_ms函数配置
		uart_init(115200);	
	  TA2_CAP_init();
	  Tim32_0_Int_Init(47999999,1);
	  printf("Hello,MSP432!\r\n");								//串口打印测试字符
		MAP_Interrupt_enableMaster();               // 开启总中断
}


//串口0服务函数
//串口0接收命令,存在数组中
void EUSCIA0_IRQHandler(void)
{
	uint32_t status = UART_getEnabledInterruptStatus(EUSCI_A0_BASE);
	if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)      //接收中断
	{
		USART0_save[USART0_xb++]=MAP_UART_receiveData(EUSCI_A0_BASE);
		if(USART0_xb== 20){USART0_xb=0;	}							      //下标最大不超过20
		if(USART0_save[USART0_xb-1]=='\0'){USART0_flag=1;}  //命令以\0结尾
	}
}


//这是捕获事件中断服务函数(因为定时器溢出中断已关闭)
//注意对照引脚看通道,这里通道情况与PWM控制不一样
void TA2_N_IRQHandler(void)
{
    uint16_t captureSource = TA2IV;
// 根据捕获通道来源进行适当的处理
//脉冲计数到62700时刚好车轮转95圈
//大电机减速比30编码器11线
    switch (captureSource) 
			{
        case 0x02:
            // 处理TA2 CCR1通道的捕获中断
						Wheel[1].CAPTURE++;
					if(Wheel[1].CAPTURE==62700)
					{Wheel[1].CAPTURE=0;Wheel[1].CAT_OUT_TIME++;}
            break;
        case 0x04:
            // 处理TA2 CCR2通道的捕获中断
						Wheel[2].CAPTURE++;
					if(Wheel[2].CAPTURE==62700)
					{Wheel[2].CAPTURE=0;Wheel[2].CAT_OUT_TIME++;}		
            break;
        case 0x06:
            // 处理TA2 CCR3通道的捕获中断
						Wheel[3].CAPTURE++;
					if(Wheel[3].CAPTURE==62700)
					{Wheel[3].CAPTURE=0;Wheel[3].CAT_OUT_TIME++;}					
            break;
        case 0x08:
            // 处理TA2 CCR4通道的捕获中断
						Wheel[4].CAPTURE++;
					if(Wheel[4].CAPTURE==62700)
					{Wheel[4].CAPTURE=0;Wheel[4].CAT_OUT_TIME++;}					
            break;
        default: break;	
}
}			


//定时器TA2捕获初始化:
void TA2_CAP_init(void)
{
	//四个通道初始化输入
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN7,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,GPIO_PIN7,GPIO_PRIMARY_MODULE_FUNCTION);	
	
	//定时器连续计数模式初始化,关闭定时溢出中断
			const Timer_A_ContinuousModeConfig continuousModeConfig =
		{
						TIMER_A_CLOCKSOURCE_SMCLK,
						TIMER_A_CLOCKSOURCE_DIVIDER_1,  //1分频,分辨率最高48M
						TIMER_A_TAIE_INTERRUPT_DISABLE, 
						TIMER_A_SKIP_CLEAR
		};
//初始化通道1:
				const Timer_A_CaptureModeConfig captureModeConfig_1 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_1, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道2:
				const Timer_A_CaptureModeConfig captureModeConfig_2 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_2, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道3:
				const Timer_A_CaptureModeConfig captureModeConfig_3 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_3, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道4:
				const Timer_A_CaptureModeConfig captureModeConfig_4 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_4, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};		
		
		
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_1);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_2);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_3);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_4);

    MAP_Timer_A_configureContinuousMode(TIMER_A2_BASE, &continuousModeConfig);
    MAP_Interrupt_enableInterrupt(INT_TA2_N);
    MAP_Timer_A_startCounter(TIMER_A2_BASE, TIMER_A_CONTINUOUS_MODE);
}

#ifndef _main_h_
#define _main_h_

#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include "string.h"				   	//C标准库、字符串处理库
#include "sysinit.h"			   	//时钟配置
#include "delay.h"				   	//滴答定时器初始化(提供delay_ms延时)
#include "Public.h"
#include "DATA.h"

//单个车轮状态与参数结构体:
typedef struct wheel_data
{
	uint16_t Sta;            //正反转状态,0不转,2正,1反
	uint16_t PWM_DIV;        //车轮电机占空比6 - 99
  uint32_t CAT_OUT_TIME;   //编码器 脉冲溢出次数,溢出一次就加一,记录有几个65530
  uint32_t CAPTURE;        //编码器 外部中断次数记录最大65530次脉冲,溢出后CAT_OUT_TIME会加一,CAPTURE归零
	uint32_t CAPTURE_LAST;   //上一次外部中断次数记录
  uint32_t CAPTURE_NEW;    //最新外部中断次数记录
	uint32_t DISTANCE;       //单轮行驶总路程长度单位cm,最大65535cm
  uint32_t SPEED;          //瞬时速度值存储,单位cm/s
}Wheel_dat;


void inint_all(void);               //初始化所有模块
//定时器TA2捕获初始化:
void TA2_CAP_init(void);

#endif

 测试工程下载:

https://download.csdn.net/download/qq_64257614/88214201?spm=1001.2014.3001.5503

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

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

相关文章

Jmeter 参数化的几种方法

目录 配置元件-用户自定义变量 前置处理器-用户参数 配置元件-CSV Data Set Config Tools-函数助手 配置元件-用户自定义变量 可在测试计划、线程组、HTTP请求下创建用户定义的变量 全局变量&#xff0c;可以跨线程组调用 jmeter执行的时候&#xff0c;只获取一次&#xff0…

PromQL实现Actuator获取的JVM指标的Full GC次数监控

Spring Boot 版本需要2.0.0或更高版本。 添加Micrometer Prometheus registry依赖: <dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId> </dependency>在application.properties中开…

linux-删除KVM虚拟机

1.查看主机 #virsh list 2.关闭主机 #virsh shutdown 虚拟机名称 3.删除主机定义 #virsh undefine 虚拟机名称 4.删除KVM虚拟机文件 #find / -name 虚拟机名称 #rm -rf 虚拟机文件

WebSocket与消息推送

B/S结构的软件项目中有时客户端需要实时的获得服务器消息&#xff0c;但默认HTTP协议只支持请求响应模式&#xff0c;这样做可以简化Web服务器&#xff0c;减少服务器的负担&#xff0c;加快响应速度&#xff0c;因为服务器不需要与客户端长时间建立一个通信链接&#xff0c;但…

原生js发送ajax请求---ajax请求篇(一)

在原生js中我们使用的是XMLHttpRequest对象来发送ajax请求 主要步骤就是&#xff1a; 1.创建XMLHTTPRequest对象 2.使用open方法设置和服务器的交互信息 3.设置发送的数据&#xff0c;开始和服务器端交互 4.注册事件 5.更新界面 &#xff08;1&#xff09; get方式 //步骤一…

教你如何为博客网站申请阿里云的免费域名HTTPS证书

如何为博客网站申请阿里云的免费域名HTTPS证书 文章目录 如何为博客网站申请阿里云的免费域名HTTPS证书前置条件&#xff1a;步骤1 例如阿里云控制台&#xff0c;选择SSL证书步骤2 申请购买免费证书步骤3 创建证书步骤3.1 证书申请步骤3.2 DNS域名验证 步骤4 等待证书审核成功&…

善于用兵的人,军队粮草取自敌人

善于用兵的人&#xff0c;军队粮草取自敌人 【安志强趣讲《孙子兵法》第8讲】 【原文】 善用兵者&#xff0c;役不再籍&#xff0c;粮不三载&#xff1b;取用于国&#xff0c;因粮于敌&#xff0c;故军食可足也。 【注释】 役不再籍&#xff1a;役&#xff0c;兵役&#xff1b;…

一周开发问题回顾(2023年08月07日-2023年08月13日)

一周开发问题回顾2023年08月07日-2023年08月13日 1. Arrays.asList()与 new ArrayList()的区别1.1 Arrays1.1.1补充 ArrayList(Arrays.asList(array)) 1.2 ArrayList()1.2.1 创建ArrayList的几种方法 2.Mysql中group by的使用方式3.画图4. 时间倒排5. 工厂策略设计模式6.List注…

Observable设计模式简介

Observable设计模式存在于许多Java API和响应式编程中。下面介绍Java中永恒的Observable模式。 Observable设计模式用于许多重要的Java API。一个众所周知的示例是使用ActionListenerAPI执行操作的JButton。在这个例子中&#xff0c;我们ActionListener在按钮上进行了监听或…

2.Model、ModelMap和ModelAndView的使用详解

1.前言 最近SSM框架开发web项目&#xff0c;用得比较火热。spring-MVC肯定用过&#xff0c;在请求处理方法可出现和返回的参数类型中&#xff0c;最重要就是Model和ModelAndView了&#xff0c;对于MVC框架&#xff0c;控制器Controller执行业务逻辑&#xff0c;用于产生模型数据…

汽车制造业上下游协作时 外发数据如何防泄露?

数据文件是制造业企业的核心竞争力&#xff0c;一旦发生数据外泄&#xff0c;就会给企业造成经济损失&#xff0c;严重的&#xff0c;可能会带来知识产权剽窃损害、名誉伤害等。汽车制造业&#xff0c;会涉及到重要的汽车设计图纸&#xff0c;像小米发送汽车设计图纸外泄事件并…

电子拣货标签2代系统简介

CK_Label_v2 一、革新点 无线 容易安装和移动 按键及指示导引系统 128*64点阵屏幕&#xff0c;自带LED背光 红绿两色高亮LED灯光指示 长电池寿命&#xff0c;常规使用3年以上 二、特点与效益 提升作业速度与品质 简易快速部署 实现无纸化标准化作业 缩短操作人员培训时…

Jmeter-压力测试工具

文章目录 Jmeter快速入门1.1.下载1.2.解压1.3.运行 2.快速入门2.1.设置中文语言2.2.基本用法 Jmeter快速入门 1s内发送大量请求&#xff0c;模拟高QPS&#xff0c;用以测试网站能承受的压力有多大 Jmeter依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了JDK&#xff0…

docker的服务/容器缺少vim问题

背景/问题&#xff1a; docker的服务/容器缺少vim问题 bash: vim: command not found 在docker的mysql服务中安装Vim 1、执行apt-get update root6d8d17e320a0:/# apt-get update问题:文件下载失败 Err:1 http://security.debian.org/debian-security buster/updates InRe…

顺序表的插入,删除,修改和查找(详细解析)

目录 一.顺序表的初始化----静态分配 二.顺序表的初始化----动态分配 三.顺序表的插入 1.插入操作 2.插入操作的时间复杂度 三.顺序表的删除操作 1.顺序表的删除 2.删除操作的时间复杂度 四.顺序表的查找 1.按位查找操作&#xff1a;查找第i位置的元素 2.按位查找操作…

c++字符串函数

在 C 中有大量用于操作 C-style 字符串的函数&#xff0c;它们集成在头文件 <cstring> 中。其常见的函 函数作用strcpy(s1,s2) 复制字符串 s2 到 s1strcat(s1,s2) 将字符串 s2 连接到 s1 末尾strlen(s) 计算字符串 s 长度strcmp(s1,s2) 比较字符串 s1 和 s2 …

DoIP诊断入门

简介 DoIP&#xff08;Diagnosis over Internet Protocol&#xff09;是一种用于车辆诊断的网络通信协议。它基于现代互联网技术&#xff0c;允许通过以太网或IP网络进行车辆诊断和通信。 DoIP的背景是现代车辆中使用的电子控制单元&#xff08;ECU&#xff09;数量不断增加&…

内网穿透——使用Windows自带的网站程序建立网站

文章目录 1.前言2.Windows网页设置2.1 Windows IIS功能设置2.2 IIS网页访问测试 3. Cpolar内网穿透3.1 下载安装Cpolar3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5.结语 1.前言 在网上各种教程和介绍中&#xff0c;搭建网页都会借助各种软件的帮助&#xff0c;比如…