程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)

STM32F103 捕获配置

在《STM32F103 PWM配置》我们介绍了PWM配置,这一节将会介绍输入捕获配置。

一、输入捕获概述

1.1 通用定时器框图

img

在通用定时器框图中,主要涉及如下几个部分:

  • 时钟源的选择(最上面部分);
  • 时基单元(中间部分;);
  • 输入捕获(左下部分);
  • PWM输出(右下部分)。

其中时钟源的选择以及时基单元配置我们在《STM32F103定时器配置》介绍过,而PWM配置在《STM32F103 PWM配置》中介绍过,本节主要介绍输入捕获。

1.2 输入捕获原理

输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6TIM7,其它的定时器都有输入捕获的功能。

下面以一个简单的脉冲输入为例,简单地讲述一下输入捕获用于测量脉冲宽度的工作原理:

先设置输入捕获为上升沿检测,记录发生上升沿时TIMx_CNT的值。

然后配置捕获信号为下降沿捕获,当下降沿到来的时候发生捕获,并记录此时的TIMx_CNT的值。

这样,前后两次TIMx_CNT的值之差就是高电平的脉宽。

同时根据TIMx的计数频率,我们就能知道高电平脉宽的准确时间。

1.3 输入捕获的通道概览

每一个捕获/比较通道都是围绕着着一个捕获/比较寄存器(TIMx_CCRx、包含影子寄存器),包括捕获的输入部分(数字滤波、多路复用和预分频器),和输出部分(比较器和输出控制)。

捕获/比较模块由一个预装载寄存器和一个影子寄存器组成。读写过程仅操作预装载寄存器;

  • 在捕获模式下,捕获发生在影子寄存器上,然后再复制到预装载寄存器中;
  • 在比较模式下,预装载寄存器的内容被复制到影子寄存器中,然后影子寄存器的内容和计数器进行比较;
img

输入部分对相应的TIx输入信号采样,并产生一个滤波后的信号TIxF

然后,一个带极性选择的边缘检测器产生一个信号(TIxFPx),它可以作为从模式控制器的输入触发或者作为捕获控制。该信号通过预分频进入捕获寄存器(ICxPS)。

一句话总结工作过程:通过检测TIMx_CHx通道上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。同时,还可以配置捕获时是否触发中断/DMA等。

1.3.1 设置输入捕获滤波器

输入捕获滤波器ICxF[3:0],这个用于设置采样频率和数字滤波器长度。

其中:fCK_INT是定时器的输入频率,fDTS是根据TIMx_CR1CKD[1:0]的设置来确定的。

这里滤波器的作用是什么意思呢?数字滤波器由一个事件计数器组成,它记录到N个事件后会产生一个输出的跳变。

也就是说连续N次采样,如果都是高电平,则说明这是一个有效的触发,就会进入输入捕捉中断(如果设置了的话)。这样就可以滤除那些高电平脉宽低于8个采样周期的脉冲信号,从而达到滤波的作用。

1.3.2 设置输入捕获极性

捕获输出极性CCxP,这个用于设置捕捉事件是发生在上升沿还是下降沿。

1.3.3 设置输入捕获映射关系

img

TIMx_CH1TIMx_CH2两条通道的情况下,我们可以看出除了TIMx_CH1捕捉到的信号可以连接到IC1TIMx_CH2捕捉到的信号可以连接到IC2之外,TIMx_CH1捕捉到的信号也可以连接到IC2TIMx_CH2捕捉到的信号也可以连接到IC1

一般情况下,我们设置成TIMx_CH1捕捉到的信号可以连接到IC1TIMx_CH2捕捉到的信号可以连接到IC2

输入捕获选择(CCxS)配置为:CC1通道被配置为输入、IC1映射在TI1上(01)。

1.3.4 设置输入捕获分频器

输入捕获预分频器ICxPSC:设置的是每N个事件触发一次捕捉。

也就是说,我们可以设置成每2次上升沿事件触发一次捕捉。

二、输入捕获源码

2.1 输入捕获初始化步骤

输入捕获配置流程如下:

(1) TIMx时钟使能:通过配置RCC_APB1ENR/RCC_APB2ENR寄存器使能TIMx时钟;

(2)GPIO口配置:以TIM2_CH1PA0)为例;

  • 配置PA0为下拉输入;
  • GPIOA时钟使能;

(3) 配置TIMx时基单元;

  • 配置TIMx_ARR寄存器自动重装载的值(0xFFFF);
  • 配置TIMx_PSC寄存器预分频系数(71);

(4) 配置输入捕获相关寄存器;

  • 配置TIMx_CCMRx寄存器:
    • 输入捕获预滤波器(ICxF):配置采样频率和数字滤波器长度,用于消除输入信号的抖动;
    • 输入捕获/比较输出选择(CCxS):配置为01,即CC1通道被配置为输入、IC1映射在TI1上;用于实现输入信号捕获功能;
    • 输入捕获预分频器(ICxPSC):配置为无预分频器(00);
  • 配置TIMx_CCER寄存器:
    • 输入捕获/比较输出使能(CCxE):即开启输入捕获功能,这样捕获事件发生时,计数器的值会被保存到捕获寄存器(TIMx_CCRx);
    • 捕获输出极性(CCxP):0用于上升沿捕获,1up没回下降沿捕获;

(5) 配置TIMx_DIER寄存器:

  • 更新中断(UIE)配置为允许(1b);
  • 输入捕获/比较输出中断(CCxE)配置为允许(1b);

(6) 设置NVIC;

(7) 中断处理函数;

  • 设置中断服务函数(包括清除中断标志,清SR寄存器状态标志位(UIF=0CCxIF=0))。

(8) 允许TIMx工作:配置TIMx_CR101

2.2 源码实现

2.2.1 输入捕获初始化

输入捕获初始化函数TIM_CAP_Init定义如下:

/******************************************************************************************************
 *
 *	  Description:    电平脉宽捕获
             timn:	  定时器   TIMER1~5 8     定时器8程序有问题 勿用
		  Channel:	  输入通道 CAP_CH1~4
		     mode:	  0:捕获低电平   1:捕获高电平 
 *
 ******************************************************************************************************/
void TIM_CAP_Init(TIMn timn,CAP_CHANNEL Channel,u8 mode)
{
	u8 REMAP=0x00;                          //映射情况 0x00默认 0x01  0x02:  0x03  自己设置
//	if(timn==0||timn==7) 	                //定时器1或8   
//	{
//		 fclk = 72;                        //默认APB2 1倍频
//	}
//	else 
//	{
//	     fclk =72;						   //默认APB1 2倍频
//	} 
//******************************************************************************************
	if(timn==0)                        //定时器1
	{
	  RCC->APB2ENR |=1<<11;                 //高级定时器1时钟使能 
	  if(REMAP==0x00)
	  {
		  if(Channel==CAP_CH1)
		  {
		     gpio_init(PA8,GPI_DOWN,HIGH);            //输入下拉
			 PAout(8)=0;               
			 TIM1->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			 TIM1->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM1->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		  } 
		  else if(Channel==CAP_CH2)
		  {
		      gpio_init(PA9,GPI_DOWN,HIGH);            //输入下拉
			  PAout(9)=0; 
			  TIM1->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM1->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM1->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		  }
		  else if(Channel==CAP_CH3)
		  {
		     gpio_init(PA10,GPI_DOWN,HIGH);            //输入下拉
			 PAout(10)=0;               
			 TIM1->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM1->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM1->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		  } 
		  else if(Channel==CAP_CH4)
		  {
		      gpio_init(PA11,GPI_DOWN,HIGH);            //输入下拉
			  PAout(11)=0; 
			  TIM1->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM1->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM1->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		  }
		  else
		  {
		   ASSERT(0); 
		  }
	   }
	                       //*******************************
	  else if(REMAP==0x01)
	  {
	      RCC->APB2ENR |= 1<<0;                       //使能I/O复用时钟
		  AFIO->MAPR   &=~(0x3<<6);                   //位7:6清零   
		  AFIO->MAPR   |= REMAP<<6;                   //TIM1部分映射
		  if(Channel==CAP_CH1)
		  {
		     gpio_init(PA8,GPI_DOWN,HIGH);            //输入下拉
			 PAout(8)=0;               
			 TIM1->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			 TIM1->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM1->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		  } 
		  else if(Channel==CAP_CH2)
		  {
		      gpio_init(PA9,GPI_DOWN,HIGH);            //输入下拉
			  PAout(9)=0; 
			  TIM1->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM1->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM1->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		  }
		  else if(Channel==CAP_CH3)
		  {
		     gpio_init(PA10,GPI_DOWN,HIGH);            //输入下拉
			 PAout(10)=0;               
			 TIM1->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM1->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM1->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		  } 
		  else if(Channel==CAP_CH4)
		  {
		      gpio_init(PA11,GPI_DOWN,HIGH);            //输入下拉
			  PAout(11)=0; 
			  TIM1->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM1->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM1->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		  } 
		  
		  else
		  {
		   ASSERT(0); 
		  }	
	   }
	                         //**********************************
	  else if(REMAP==0x03)									   //完全映射
	  {
	     RCC->APB2ENR |= 1<<0;                       //使能I/O复用时钟
		 AFIO->MAPR   &=~(0x3<<6);                   //位7:6清零   
		 AFIO->MAPR   |= REMAP<<6;                   //TIM1完全映射
		 if(Channel==CAP_CH1)
		 {
		      gpio_init(PE9,GPI_DOWN,HIGH);            //输入下拉
		   	  PEout(9)=0;               
			  TIM1->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			  TIM1->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM1->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		 } 
		 else if(Channel==CAP_CH2)
		 {
		      gpio_init(PE11,GPI_DOWN,HIGH);            //输入下拉
			  PEout(11)=0; 
			  TIM1->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM1->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM1->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		 }
		 else if(Channel==CAP_CH3)
		 {
		     gpio_init(PE13,GPI_DOWN,HIGH);            //输入下拉
			 PEout(13)=0;               
			 TIM1->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM1->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM1->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		 } 
		 else if(Channel==CAP_CH4)
		 {
		      gpio_init(PE14,GPI_DOWN,HIGH);            //输入下拉
			  PEout(14)=0; 
			  TIM1->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM1->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM1->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		 }
		 else
		 {
		   ASSERT(0); 
		 }	
	  } 
	                  //****************************************
	  else
	  {
	    ASSERT(0);
	  }
	}
  //**********************************************************************************************************
	else if(timn==1)                   //定时器2
	{
	//  REMAP=0x01;
	  RCC->APB1ENR |=1<<0;                  //定时器2时钟使能
	  if(REMAP==0x00)
	  {
		  if(Channel==CAP_CH1)
		  {
		     gpio_init(PA0,GPI_DOWN,HIGH);            //输入下拉
			 PAout(0)=0;               
			 TIM2->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			 TIM2->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM2->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		  } 
		  else if(Channel==CAP_CH2)
		  {
		      gpio_init(PA1,GPI_DOWN,HIGH);            //输入下拉
			  PAout(1)=0; 
			  TIM2->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM2->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		  }
		  else if(Channel==CAP_CH3)
		  {
		     gpio_init(PA2,GPI_DOWN,HIGH);            //输入下拉
			 PAout(2)=0;               
			 TIM2->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM2->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM2->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		  } 
		  else if(Channel==CAP_CH4)
		  {
		      gpio_init(PA3,GPI_DOWN,HIGH);            //输入下拉
			  PAout(3)=0; 
			  TIM2->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM2->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		  }
		  else
		  {
		   ASSERT(0); 
		  }
	   }
	                       //*******************************
	  else if(REMAP==0x01)	     //部分映射
	  {
	      RCC->APB2ENR |= 1<<0;                       //使能I/O复用时钟
		  AFIO->MAPR   &=~(0x3<<8);                   //位9:8清零   
		  AFIO->MAPR   |= REMAP<<8;                   //TIM2部分映射 
		  if(Channel==CAP_CH1)
		  {
		     gpio_init(PA15,GPI_DOWN,HIGH);            //输入下拉
			 PAout(15)=0;               
			 TIM2->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			 TIM2->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM2->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		  } 
		  else if(Channel==CAP_CH2)
		  {
		      gpio_init(PB3,GPI_DOWN,HIGH);            //输入下拉
			  PBout(3)=0; 
			  TIM2->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM2->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		  }
		  else if(Channel==CAP_CH3)
		  {
		     gpio_init(PA2,GPI_DOWN,HIGH);            //输入下拉
			 PAout(2)=0;               
			 TIM2->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM2->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM2->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		  } 
		  else if(Channel==CAP_CH4)
		  {
		      gpio_init(PA3,GPI_DOWN,HIGH);            //输入下拉
			  PAout(3)=0; 
			  TIM2->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM2->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		  } 
		  else
		  {
		   ASSERT(0); 
		  }	
	   }
	                         //*********************************
	  else if(REMAP==0x02)									   //部分映射
	  {
	     RCC->APB2ENR |= 1<<0;                       //使能I/O复用时钟
		 AFIO->MAPR   &=~(0x3<<8);                   //位9:8清零   
		 AFIO->MAPR   |= REMAP<<8;                   //TIM2部分映射 
		 if(Channel==CAP_CH1)
		 {
		      gpio_init(PA0,GPI_DOWN,HIGH);            //输入下拉
		   	  PAout(0)=0;               
			  TIM2->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			  TIM2->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		 } 
		 else if(Channel==CAP_CH2)
		 {
		      gpio_init(PA1,GPI_DOWN,HIGH);            //输入下拉
			  PAout(1)=0; 
			  TIM2->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM2->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		 }
		 else if(Channel==CAP_CH3)
		 {
		     gpio_init(PB10,GPI_DOWN,HIGH);            //输入下拉
			 PBout(10)=0;               
			 TIM2->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM2->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM2->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		 } 
		 else if(Channel==CAP_CH4)
		 {
		      gpio_init(PB11,GPI_DOWN,HIGH);            //输入下拉
			  PBout(11)=0; 
			  TIM2->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM2->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		 }
		 else
		 {
		   ASSERT(0); 
		 }
	  }
	                         //**********************************
	  else if(REMAP==0x03)									   //完全映射
	  {
         RCC->APB2ENR |= 1<<0;                       //使能I/O复用时钟
		 AFIO->MAPR   &=~(0x3<<8);                   //位9:8清零   
		 AFIO->MAPR   |= REMAP<<8;                   //TIM2部分映射               
		 if(Channel==CAP_CH1)
		 {
		      gpio_init(PA15,GPI_DOWN,HIGH);            //输入下拉
		   	  PAout(15)=0;               
			  TIM2->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			  TIM2->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		 } 
		 else if(Channel==CAP_CH2)
		 {
		      gpio_init(PB3,GPI_DOWN,HIGH);            //输入下拉
			  PBout(3)=0; 
			  TIM2->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM2->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		 }
		 else if(Channel==CAP_CH3)
		 {
		     gpio_init(PB10,GPI_DOWN,HIGH);            //输入下拉
			 PBout(10)=0;               
			 TIM2->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM2->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM2->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		 } 
		 else if(Channel==CAP_CH4)
		 {
		      gpio_init(PB11,GPI_DOWN,HIGH);            //输入下拉
			  PBout(11)=0; 
			  TIM2->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM2->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM2->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		 }
		 else
		 {
		   ASSERT(0); 
		 }	
	  } 
	                  //****************************************
	  else
	  {
	    ASSERT(0);
	  } 
	   
	}          
	//**************************************************************************************************************
    else if(timn==2)                   //定时器3
	{
	  RCC->APB1ENR |=1<<1;                  //定时器3时钟使能
	  if(REMAP==0x00)
	  {
		  if(Channel==CAP_CH1)
		  {
		     gpio_init(PA6,GPI_DOWN,HIGH);            //输入下拉
			 PAout(6)=0;               
			 TIM3->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			 TIM3->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM3->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		  } 
		  else if(Channel==CAP_CH2)
		  {
		      gpio_init(PA7,GPI_DOWN,HIGH);            //输入下拉
			  PAout(7)=0; 
			  TIM3->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM3->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM3->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		  }
		  else if(Channel==CAP_CH3)
		  {
		     gpio_init(PB0,GPI_DOWN,HIGH);            //输入下拉
			 PBout(0)=0;               
			 TIM3->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM3->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM3->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		  } 
		  else if(Channel==CAP_CH4)
		  {
		      gpio_init(PB1,GPI_DOWN,HIGH);            //输入下拉
			  PBout(1)=0; 
			  TIM3->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM3->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM3->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		  }
		  else
		  {
		   ASSERT(0); 
		  }
	   }
	                       //*******************************
	  else if(REMAP==0x02)
	  {
	      RCC->APB2ENR |= 1<<0;                       //使能I/O复用时钟
		  AFIO->MAPR   &=~(0x3<<10);                   //位7:6清零   
		  AFIO->MAPR   |= REMAP<<10;                   //TIM3部分映射
		  if(Channel==CAP_CH1)
		  {
		     gpio_init(PB4,GPI_DOWN,HIGH);            //输入下拉
			 PBout(4)=0;               
			 TIM3->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			 TIM3->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM3->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		  } 
		  else if(Channel==CAP_CH2)
		  {
		      gpio_init(PB5,GPI_DOWN,HIGH);            //输入下拉
			  PBout(5)=0; 
			  TIM3->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM3->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM3->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		  }
		  else if(Channel==CAP_CH3)
		  {
		     gpio_init(PB0,GPI_DOWN,HIGH);            //输入下拉
			 PBout(0)=0;               
			 TIM3->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM3->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM3->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		  } 
		  else if(Channel==CAP_CH4)
		  {
		      gpio_init(PB1,GPI_DOWN,HIGH);            //输入下拉
			  PBout(1)=0; 
			  TIM3->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM3->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM3->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		  } 
		  
		  else
		  {
		   ASSERT(0); 
		  }	
	   }
	                         //**********************************
	  else if(REMAP==0x03)									   //完全映射
	  {
	     RCC->APB2ENR |= 1<<0;                       //使能I/O复用时钟
		 AFIO->MAPR   &=~(0x3<<10);                   //位7:6清零   
		 AFIO->MAPR   |= REMAP<<10;                   //TIM1完全映射
		 if(Channel==CAP_CH1)
		 {
		      gpio_init(PC6,GPI_DOWN,HIGH);            //输入下拉
		   	  PCout(6)=0;               
			  TIM3->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			  TIM3->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM3->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		 } 
		 else if(Channel==CAP_CH2)
		 {
		      gpio_init(PC7,GPI_DOWN,HIGH);            //输入下拉
			  PCout(7)=0; 
			  TIM3->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM3->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM3->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		 }
		 else if(Channel==CAP_CH3)
		 {
		     gpio_init(PC8,GPI_DOWN,HIGH);            //输入下拉
			 PCout(8)=0;               
			 TIM3->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM3->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM3->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		 } 
		 else if(Channel==CAP_CH4)
		 {
		      gpio_init(PC9,GPI_DOWN,HIGH);            //输入下拉
			  PCout(9)=0; 
			  TIM3->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM3->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM3->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		 }
		 else
		 {
		   ASSERT(0); 
		 }	
	  } 
	                  //****************************************
	  else
	  {
	    ASSERT(0);
	  }  
	}       
	//********************************************************************************************************************
	else if(timn==3)                   //定时器4
	{
	  RCC->APB1ENR |=1<<2;                  //定时器4时钟使能
	  if(REMAP==0x00)
	  {
		  if(Channel==CAP_CH1)
		  {
		     gpio_init(PB6,GPI_DOWN,HIGH);            //输入下拉
			 PBout(6)=0;               
			 TIM4->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			 TIM4->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM4->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		  } 
		  else if(Channel==CAP_CH2)
		  {
		      gpio_init(PB7,GPI_DOWN,HIGH);            //输入下拉
			  PBout(7)=0; 
			  TIM4->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM4->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM4->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		  }
		  else if(Channel==CAP_CH3)
		  {
		     gpio_init(PB8,GPI_DOWN,HIGH);            //输入下拉
			 PBout(8)=0;               
			 TIM4->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM4->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM4->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		  } 
		  else if(Channel==CAP_CH4)
		  {
		      gpio_init(PB9,GPI_DOWN,HIGH);            //输入下拉
			  PBout(9)=0; 
			  TIM4->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM4->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM4->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		  }
		  else
		  {
		   ASSERT(0); 
		  }
	   }
	                       //*******************************
	  else if(REMAP==0x01)
	  {
	      RCC->APB2ENR |= 1<<0;                       //使能I/O复用时钟
		  AFIO->MAPR   &=~(0x1<<12);                   //位12清零   
		  AFIO->MAPR   |= REMAP<<12;                   //TIM4部分映射
		  if(Channel==CAP_CH1)
		  {
		     gpio_init(PD12,GPI_DOWN,HIGH);            //输入下拉
			 PDout(12)=0;               
			 TIM4->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			 TIM4->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM4->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		  } 
		  else if(Channel==CAP_CH2)
		  {
		      gpio_init(PD13,GPI_DOWN,HIGH);            //输入下拉
			  PDout(13)=0; 
			  TIM4->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM4->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM4->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		  }
		  else if(Channel==CAP_CH3)
		  {
		     gpio_init(PD14,GPI_DOWN,HIGH);            //输入下拉
			 PDout(14)=0;               
			 TIM4->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM4->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM4->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		  } 
		  else if(Channel==CAP_CH4)
		  {
		      gpio_init(PD15,GPI_DOWN,HIGH);            //输入下拉
			  PDout(15)=0; 
			  TIM4->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM4->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM4->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		  } 
		  
		  else
		  {
		   ASSERT(0); 
		  }	
	  }  
	  else
	  {
	    ASSERT(0);
	  } 
	} 
	//*********************************************************************************************************  	              
    else if(timn==4)                   //定时器5
	{
	   RCC->APB1ENR |=1<<3;                  //定时器5时钟使能
	   if(Channel==CAP_CH1)
		  {
		     gpio_init(PA0,GPI_DOWN,HIGH);            //输入下拉
			 PAout(0)=0;               
			 TIM5->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			 TIM5->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM5->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		  } 
		  else if(Channel==CAP_CH2)
		  {
		      gpio_init(PA1,GPI_DOWN,HIGH);            //输入下拉
			  PAout(1)=0; 
			  TIM5->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM5->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM5->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		  }
		  else if(Channel==CAP_CH3)
		  {
		     gpio_init(PA2,GPI_DOWN,HIGH);            //输入下拉
			 PAout(2)=0;               
			 TIM5->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM5->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM5->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		  } 
		  else if(Channel==CAP_CH4)
		  {
		      gpio_init(PA3,GPI_DOWN,HIGH);            //输入下拉
			  PAout(3)=0; 
			  TIM5->CCMR2 |=0x01<<8;                      //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM5->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM5->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		  } 
		  
		  else
		  {
		   ASSERT(0); 
		  }	

	}    
	//******************************************************************************************************   
	else  if(timn==7)
	{
	     RCC->APB2ENR |=1<<13;                  //定时器8时钟使能  
	     if(Channel==CAP_CH1)
		 {
		      gpio_init(PC6,GPI_DOWN,HIGH);            //输入下拉
		   	  PCout(6)=0;               
			  TIM8->CCMR1 |=0x01;                      //CC1S=1 CC1配置为输入 IC1映射到TI1上
			  TIM8->CCMR1 |=0x03<<4;                   //IC1F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM8->CCMR1 |=0x00<<2;                   //IC1PS=0  不分频
		 } 
		 else if(Channel==CAP_CH2)
		 {
		      gpio_init(PC7,GPI_DOWN,HIGH);            //输入下拉
			  PCout(7)=0; 
			  TIM8->CCMR1 |=0x01<<8;                    //01: CC2配置为输入 IC2映射到TI2上
			  TIM8->CCMR1 |=0x03<<12;                   //IC2F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM8->CCMR1 |=0x00<<10;                   //IC2PS=0  不分频
		 }
		 else if(Channel==CAP_CH3)
		 {
		     gpio_init(PC8,GPI_DOWN,HIGH);            //输入下拉
			 PCout(8)=0;               
			 TIM8->CCMR2 |=0x01;                      //01: CC3配置为输入 IC3映射到TI3上
			 TIM8->CCMR2 |=0x03<<4;                   //IC3F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			 TIM8->CCMR2 |=0x00<<2;                   //IC3PS=0  不分频
		 } 
		 else if(Channel==CAP_CH4)
		 {
		      gpio_init(PC9,GPI_DOWN,HIGH);            //输入下拉
			  PCout(9)=0; 
			  TIM8->CCMR2 |=0x01<<8;                   //01:CC4通道被配置为输入,IC4映射在TI4上;
			  TIM8->CCMR2 |=0x03<<12;                  //IC4F=3 配置滤波器以FCKint采样,8个事件有效(消除抖动)
			  TIM8->CCMR2 |=0x00<<10;                  //IC4PS=0  不分频
		 }
		 else
		 {
		   ASSERT(0); 
		 }	 
	}
	//********************************************************************************************************
    else
	{
		ASSERT(0); 
	}	
	                                      
    TIMx[timn]->PSC  = 71;                  //预分频值   Fclk=fclk/(71+1)   1MHZ
    TIMx[timn]->ARR  = 0xFFFF;			    //重新装载的值
    if(mode==0x00)                          //捕获低电平
	{
	   TIMx[timn]->CCER |= 0x3<<(4*Channel);   //下降沿捕获 捕获低电平 捕获使能  
	}
	else                                    //捕获高电平
	{
       TIMx[timn]->CCER |= 0x01<<(4*Channel);  //上升沿捕获 捕获高电平 捕获使能	  
	}

	TIMx[timn]->DIER |= 1<<(Channel+1);     //开启捕获比较中断  
    TIMx[timn]->DIER |= 1<<0;			    //允许更新中断   UIE=1;
	TIMx[timn]->CR1  |= 0<<4;               //DIR=0; 向上计数
   	TIMx[timn]->CR1  |= 1<<0;               //使能计数器 开始计数
    //中断优先级设置  

}

TIM_CAP_Init函数同时实现了高电平和低电平脉冲宽度的捕获。

2.2.2 TIM1/8溢出/捕获/比较中断

定时器1和定时器8都是高级定时器,拥有独立的溢出(更新)中断、以及捕获/比较中断事件。

接下来我们将会以高级定时器TIM1为例介绍这个脉冲宽度捕获是如何实现的,并且我们以捕获高电平为例进行讲解。

在中断处理函数中,先判断是否捕获成功,如果捕获成功了,说明是在脉冲低电平的阶段,什么都不需要做。

如果捕获没有成功,说明是在脉冲高电平的阶段,就需要执行不同的处理逻辑;

  • 在更新(溢出)中断中,表示此时高电平脉冲长度过长,TIM1CH1_CAP_STA1
  • 在捕获/比较中断中;
    • 判断是否是第一次捕获到(捕捉到的是上升沿),如果是,计数器当前值(TIM1_CNT)清零,TIM1CH1_CAP_VAL清零,同时标记第一次捕获到高电平,设置极性下降沿捕捉;
    • 判断是否是第二次捕获到(捕获到的是下降沿),如果是标记捕获完成,保存当前计数器(TIM1_CNT)的值到TIM1CH1_CAP_VAL,设置极性上升沿捕获。
2.2.2.1 TIM1_UP_IRQHandler

定时器1更新(溢出)中断TIM1_UP_IRQHandler实现;

/*******************************************************************************
* Function Name  : TIM1_UP_IRQHandler
* Description    : This function handles TIM1 overflow and update interrupt 
*                  request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void TIM1_UP_IRQHandler(void)				    //定时器1溢出中断
{
    u16 timsr;              //存放定时器标志位
	timsr = TIM1->SR; 
    if((TIM1CH1_CAP_STA&0x80)==0)            //还未成功捕获
	{
	   /****************************************/
	   if(timsr&0x01)                        //发生更新(溢出)中断
	   {
	      if(TIM1CH1_CAP_STA&0x40)                 //已经捕获到高/低电平
		  {
		     if((TIM1CH1_CAP_STA&0x3F)==0X3F)      //高/低电平太长了 强制捕获完成
			 {
			    TIM1CH1_CAP_STA |=0x80;            //标记成功捕获一次
				TIM1CH1_CAP_VAL  =0xFFFF;
			 }
			 else
			 {
			    TIM1CH1_CAP_STA++;                 //自增1
			 }
		  }
	    }
	 }
	    //***********************************************
	if((TIM1CH2_CAP_STA&0x80)==0)            //还未成功捕获
	{
	   /****************************************/
	   if(timsr&0x01)                        //发生更新(溢出)中断
	   {
	      if(TIM1CH2_CAP_STA&0x40)                 //已经捕获到高/低电平
		  {
		     if((TIM1CH2_CAP_STA&0x3F)==0X3F)      //高/低电平太长了 强制捕获完成
			 {
			    TIM1CH2_CAP_STA |=0x80;            //标记成功捕获一次
				TIM1CH2_CAP_VAL  =0xFFFF;
			 }
			 else
			 {
			    TIM1CH2_CAP_STA++;                 //自增1
			 }
		  }
	    }
	 }
	 //********************************************
	if((TIM1CH3_CAP_STA&0x80)==0)            //还未成功捕获
	{
	   /****************************************/
	   if(timsr&0x01)                        //发生更新(溢出)中断
	   {
	      if(TIM1CH3_CAP_STA&0x40)                 //已经捕获到高/低电平
		  {
		     if((TIM1CH3_CAP_STA&0x3F)==0X3F)      //高/低电平太长了 强制捕获完成
			 {
			    TIM1CH3_CAP_STA |=0x80;            //标记成功捕获一次
				TIM1CH3_CAP_VAL  =0xFFFF;
			 }
			 else
			 {
			    TIM1CH3_CAP_STA++;                 //自增1
			 }
		  }
	    }
	 }
	 //*********************************************
	if((TIM1CH4_CAP_STA&0x80)==0)            //还未成功捕获
	{
	   /****************************************/
	   if(timsr&0x01)                        //发生更新(溢出)中断
	   {
	      if(TIM1CH4_CAP_STA&0x40)                 //已经捕获到高/低电平
		  {
		     if((TIM1CH4_CAP_STA&0x3F)==0X3F)      //高/低电平太长了 强制捕获完成
			 {
			    TIM1CH4_CAP_STA |=0x80;            //标记成功捕获一次
				TIM1CH4_CAP_VAL  =0xFFFF;
			 }
			 else
			 {
			    TIM1CH4_CAP_STA++;                 //自增1
			 }
		  }
	    }
	 }
	//**********************自定义用户任务****************************//
    
    
	//*****************************************************************//
	TIM1->SR &=~(1<<0);                       //清中断标志   必须  (置0清 非写1)
 
}

在更新(溢出)中断处理函数中,先判断是否捕获成功,如果捕获成功了,什么都不需要做。如果捕获没有成功,就需要进行逻辑处理。

由于我们进行输入捕获,一旦捕捉到了上升沿,就设置计数器当前值为0,让它从0开始重新计数。

但是如果高脉冲的长度过于宽了,也就是说,从0开始计数到自动重加载值一个循环结束了,脉冲还是没有结束。这个情况下,显而易见不能只记录一下最后的计数器当前值。

亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。

日期姓名金额
2023-09-06*源19
2023-09-11*朝科88
2023-09-21*号5
2023-09-16*真60
2023-10-26*通9.9
2023-11-04*慎0.66
2023-11-24*恩0.01
2023-12-30I*B1
2024-01-28*兴20
2024-02-01QYing20
2024-02-11*督6
2024-02-18一*x1
2024-02-20c*l18.88
2024-01-01*I5
2024-04-08*程150
2024-04-18*超20
2024-04-26.*V30
2024-05-08D*W5
2024-05-29*辉20
2024-05-30*雄10
2024-06-08*:10
2024-06-23小狮子666
2024-06-28*s6.66
2024-06-29*炼1
2024-06-30*!1
2024-07-08*方20
2024-07-18A*16.66
2024-07-31*北12
2024-08-13*基1
2024-08-23n*s2
2024-09-02*源50
2024-09-04*J2
2024-09-06*强8.8
2024-09-09*波1
2024-09-10*口1
2024-09-10*波1
2024-09-12*波10
2024-09-18*明1.68
2024-09-26B*h10
2024-09-3010
2024-10-02M*i1
2024-10-14*朋10
2024-10-22*海10
2024-10-23*南10
2024-10-26*节6.66
2024-10-27*o5
2024-10-28W*F6.66
2024-10-29R*n6.66
2024-11-02*球6
2024-11-021*鑫6.66
2024-11-25*沙5
2024-11-29C*n2.88
posted @   大奥特曼打小怪兽  阅读(127)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
如果有任何技术小问题,欢迎大家交流沟通,共同进步

公告 & 打赏

>>

欢迎打赏支持我 ^_^

最新公告

程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)。

了解更多

点击右上角即可分享
微信分享提示