STM32自建库文件

一、imut.c文件

# include "imut.h"

/***********************************************************************
//函数名称:STM32常用外设函数
//作用:包括LED初始化、按键初始化、串口初始化等。LED分0,1两个;按键分0,1,2三个;串口分1,2两个。
//示例:SysInit();
//作者:陈德强
//时间:2019年4月11日08:06:28
//修改者:
//修改时间:
//修改说明:
************************************************************************/
void LEDInit(u8 LED)
{
	switch(LED)
	{
		case 0:GPIOInit(GPIOB,5,0);break;
		case 1:GPIOInit(GPIOE,5,0);break;
	}
}
void KeyInit(u8 KEY)
{
	switch(KEY)
	{
		case 0:GPIOInit(GPIOE,4,1);break;
		case 1:GPIOInit(GPIOE,3,1);break;	
		case 2:GPIOInit(GPIOA,0,-1);break;
	}
}
void USARTInit(u8 usart,int paudrate)
{
	switch(usart)
	{
		case 1:uart_init(paudrate);
		case 2:USART2_Init(paudrate);
	}
}

/*************************************************************************
//函数名称:IO口初始化函数封装
//作用:第一个参数是GPIO口,第二个参数是引脚号,第三个参数是输出输入模式选择,0是输出,1是上拉输入,-1是下拉输入。
//说明:输出是推挽输出50HZ,输入默认下拉输入。模拟输入和复用功能需单独设置。
//示例:GPIOInit(GPIOB,5,1)
//作者:陈德强
//时间:2019年4月8日17:29:05
//修改者:
//修改时间:
//修改说明:
***************************************************************************/
void GPIOInit(GPIO_TypeDef * GPIOx,u8 Pin,int OutOrIN)
{
	if(GPIOx==GPIOA)RCC->APB2ENR|=1<<2;
	if(GPIOx==GPIOB)RCC->APB2ENR|=1<<3;
	if(GPIOx==GPIOC)RCC->APB2ENR|=1<<4;
	if(GPIOx==GPIOD)RCC->APB2ENR|=1<<5;
	if(GPIOx==GPIOE)RCC->APB2ENR|=1<<6;
	if(GPIOx==GPIOF)RCC->APB2ENR|=1<<7;
	if(GPIOx==GPIOG)RCC->APB2ENR|=1<<8;
	
	if(OutOrIN==0)
	{
		switch (Pin)
		{
			case 0:
				GPIOx->CRL&=0XFFFFFFF0;GPIOx->CRL|=0X00000003;break;
			case 1:
				GPIOx->CRL&=0XFFFFFF0F;GPIOx->CRL|=0X00000030;break;
			case 2:
				GPIOx->CRL&=0XFFFFF0FF;GPIOx->CRL|=0X00000300;break;
			case 3:
				GPIOx->CRL&=0XFFFF0FFF;GPIOx->CRL|=0X00003000;break;
			case 4:
				GPIOx->CRL&=0XFFF0FFFF;GPIOx->CRL|=0X00030000;break;
			case 5:
				GPIOx->CRL&=0XFF0FFFFF;GPIOx->CRL|=0X00300000;break;
			case 6:
				GPIOx->CRL&=0XF0FFFFFF;GPIOx->CRL|=0X03000000;break;
			case 7:
				GPIOx->CRL&=0X0FFFFFFF;GPIOx->CRL|=0X30000000;break;
			case 8:
				GPIOx->CRH&=0XFFFFFFF0;GPIOx->CRH|=0X00000003;break;
			case 9:
				GPIOx->CRH&=0XFFFFFF0F;GPIOx->CRH|=0X00000030;break;			
			case 10:
				GPIOx->CRH&=0XFFFFF0FF;GPIOx->CRH|=0X00000300;break;	
			case 11:
				GPIOx->CRH&=0XFFFF0FFF;GPIOx->CRH|=0X00003000;break;
			case 12:
				GPIOx->CRH&=0XFFF0FFFF;GPIOx->CRH|=0X00030000;break;
			case 13:
				GPIOx->CRH&=0XFF0FFFFF;GPIOx->CRH|=0X00300000;break;
			case 14:
				GPIOx->CRH&=0XF0FFFFFF;GPIOx->CRH|=0X03000000;break;
			case 15:
				GPIOx->CRH&=0X0FFFFFFF;GPIOx->CRH|=0X30000000;break;	
			default:break; 
		}
	}
	
	if(OutOrIN==1)
	{
		switch (Pin)
		{
			case 0:
				GPIOx->CRL&=0XFFFFFFF0;GPIOx->CRL|=0X00000008;GPIOx->ODR|=1<<0;break;
			case 1:
				GPIOx->CRL&=0XFFFFFF0F;GPIOx->CRL|=0X00000080;GPIOx->ODR|=1<<1;break;		
			case 2:
				GPIOx->CRL&=0XFFFFF0FF;GPIOx->CRL|=0X00000800;GPIOx->ODR|=1<<2;break;	
			case 3:
				GPIOx->CRL&=0XFFFF0FFF;GPIOx->CRL|=0X00008000;GPIOx->ODR|=1<<3;break;
			case 4:
				GPIOx->CRL&=0XFFF0FFFF;GPIOx->CRL|=0X00080000;GPIOx->ODR|=1<<4;break;
			case 5:
				GPIOx->CRL&=0XFF0FFFFF;GPIOx->CRL|=0X00800000;GPIOx->ODR|=1<<5;break;
			case 6:
				GPIOx->CRL&=0XF0FFFFFF;GPIOx->CRL|=0X08000000;GPIOx->ODR|=1<<6;break;
			case 7:
				GPIOx->CRL&=0X0FFFFFFF;GPIOx->CRL|=0X80000000;GPIOx->ODR|=1<<7;break;
			case 8:
				GPIOx->CRH&=0XFFFFFFF0;GPIOx->CRH|=0X00000008;GPIOx->ODR|=1<<0;break;
			case 9:
				GPIOx->CRH&=0XFFFFFF0F;GPIOx->CRH|=0X00000080;GPIOx->ODR|=1<<1;break;			
			case 10:
				GPIOx->CRH&=0XFFFFF0FF;GPIOx->CRH|=0X00000800;GPIOx->ODR|=1<<2;break;	
			case 11:
				GPIOx->CRH&=0XFFFF0FFF;GPIOx->CRH|=0X00008000;GPIOx->ODR|=1<<3;break;
			case 12:
				GPIOx->CRH&=0XFFF0FFFF;GPIOx->CRH|=0X00080000;GPIOx->ODR|=1<<4;break;
			case 13:
				GPIOx->CRH&=0XFF0FFFFF;GPIOx->CRH|=0X00800000;GPIOx->ODR|=1<<5;break;
			case 14:
				GPIOx->CRH&=0XF0FFFFFF;GPIOx->CRH|=0X08000000;GPIOx->ODR|=1<<6;break;;
			case 15:
				GPIOx->CRH&=0X0FFFFFFF;GPIOx->CRH|=0X80000000;GPIOx->ODR|=1<<7;break;
			default:break; 			
		}		
	}
	
	if(OutOrIN==-1)
	{
		switch (Pin)
		{
			case 0:
				GPIOx->CRL&=0XFFFFFFF0;GPIOx->CRL|=0X00000008;break;
			case 1:
				GPIOx->CRL&=0XFFFFFF0F;GPIOx->CRL|=0X00000080;break;		
			case 2:
				GPIOx->CRL&=0XFFFFF0FF;GPIOx->CRL|=0X00000800;break;	
			case 3:
				GPIOx->CRL&=0XFFFF0FFF;GPIOx->CRL|=0X00008000;break;
			case 4:
				GPIOx->CRL&=0XFFF0FFFF;GPIOx->CRL|=0X00080000;break;
			case 5:
				GPIOx->CRL&=0XFF0FFFFF;GPIOx->CRL|=0X00800000;break;
			case 6:
				GPIOx->CRL&=0XF0FFFFFF;GPIOx->CRL|=0X08000000;break;
			case 7:
				GPIOx->CRL&=0X0FFFFFFF;GPIOx->CRL|=0X80000000;break;
			case 8:
				GPIOx->CRH&=0XFFFFFFF0;GPIOx->CRH|=0X00000008;break;
			case 9:
				GPIOx->CRH&=0XFFFFFF0F;GPIOx->CRH|=0X00000080;break;			
			case 10:
				GPIOx->CRH&=0XFFFFF0FF;GPIOx->CRH|=0X00000800;break;	
			case 11:
				GPIOx->CRH&=0XFFFF0FFF;GPIOx->CRH|=0X00008000;break;
			case 12:
				GPIOx->CRH&=0XFFF0FFFF;GPIOx->CRH|=0X00080000;break;
			case 13:
				GPIOx->CRH&=0XFF0FFFFF;GPIOx->CRH|=0X00800000;break;
			case 14:
				GPIOx->CRH&=0XF0FFFFFF;GPIOx->CRH|=0X08000000;break;;
			case 15:
				GPIOx->CRH&=0X0FFFFFFF;GPIOx->CRH|=0X80000000;break;
			default:break; 			
		}		
	}
}

/**************************************************************************
//函数名称:单个按键扫描程序
//作用:直连按键扫描程序,包括KE0(PE4)。//mode=1,支持连按。
//示例:KEY_Scan(0)
//作者:陈德强
//时间:2019年4月8日17:29:05
//修改者:
//修改时间:
//修改说明:
***************************************************************************/

u8 KEY_Scan(u8 mode)
{	 
	static u8 key_up=1;//按键按松开标志
	if(mode)key_up=1;  //支持连按		  
	if(key_up&&(KEY0==0||KEY1==0||WakeUP==1))
	{
		delay_ms(10);//去抖动 
		key_up=0;
		if(KEY0==0)return 1;
		else if(KEY1==0)return 2;
		else if(WakeUP==1)return 3;
	}else if(KEY0==1&&KEY1==1&&WakeUP==0)key_up=1; 	    
 	return 0;// 无按键按下
}

/******************************************************************************
//函数名称:UART2初始化函数及中断函数
//作用:UART2初始化函数。注:使用时用杜邦线将PA2和P9下的RXD连接,将PA3和TXD连接。
//示例:USART2_Init(115200);
//作者:陈德强
//时间:2019年4月10日17:16:36
//修改者:
//修改时间:
//修改说明:
*******************************************************************************/
void USART2_Init(int BaudRate)
{
	GPIO_InitTypeDef GPIO_InitStrue;
	USART_InitTypeDef USART_InitStrue;
	
	//使能引脚A
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	//使能串口复用功能
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	
	/*----------------------配置引脚PA2和PA3为复用功能----------------*/
	GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStrue.GPIO_Pin=GPIO_Pin_2;
	GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(GPIOA,&GPIO_InitStrue);
	
	GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStrue.GPIO_Pin=GPIO_Pin_3;
	GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(GPIOA,&GPIO_InitStrue);
	/*----------------------------------------------------------------*/
	
	/*-------------------------配置USART2-----------------------------*/
	USART_InitStrue.USART_BaudRate=BaudRate;
	USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
	USART_InitStrue.USART_Parity=USART_Parity_No;
	USART_InitStrue.USART_StopBits=USART_StopBits_1;
	USART_InitStrue.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART2,&USART_InitStrue);//③
	/*----------------------------------------------------------------*/
	
	//使能串口1
	USART_Cmd(USART2,ENABLE);
	//开启接收中断
	USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
		
}
/*----------------------------串口2中断服务函数--------------------------------*/	

void USART2_IRQHandler(void)
{
	u8 res;
	static int num;
	 if(USART_GetITStatus(USART2,USART_IT_RXNE)) //当接收寄存器接收到数据时
 {
	 res= USART_ReceiveData(USART2); //将数据放在res变量中
	 USART_SendData(USART2,res); //将数据发送到串口,这时电脑串口接收到数据,并在串口调试助手显示出来。
	 num++;
	 if(num==5)
	 {
	   num=0;
		 LED0 =1;
	 }		
  }
}
/*----------------------------------------------------------------------------*/	

/******************************************************************************
//函数名称:外部中断初始化函数及中断函数
//作用:外部中断初始化函数。带注释的地方需要改。1上升沿,0上升沿。
//示例:EXTIX_Init(GPIOE,3,0);
//说明:PE3引脚,下降沿
//作者:陈德强
//时间:2019年4月11日00:56:11
//修改者:
//修改时间:
//修改说明:
*******************************************************************************/

void ExtiInit(GPIO_TypeDef * GPIOx,u8 BITx,u8 UpOrDown)
{
	u8 EXTADDR;
	u8 EXTOFFSET;
	u8 gpiox;
	if(GPIOx==GPIOA)gpiox=0;
  if(GPIOx==GPIOB)gpiox=1;	
	if(GPIOx==GPIOC)gpiox=2;
	if(GPIOx==GPIOD)gpiox=3;
	if(GPIOx==GPIOE)gpiox=4;
	if(GPIOx==GPIOF)gpiox=5;
	if(GPIOx==GPIOG)gpiox=6;
	EXTADDR=BITx/4;
	EXTOFFSET=(BITx%4)*4; 
	RCC->APB2ENR|=0x01;		 
	AFIO->EXTICR[EXTADDR]&=~(0x000F<<EXTOFFSET);
	AFIO->EXTICR[EXTADDR]|=gpiox<<EXTOFFSET;
	EXTI->IMR|=1<<BITx;
 	if(UpOrDown==0)EXTI->FTSR|=1<<BITx;
	if(UpOrDown==1)EXTI->RTSR|=1<<BITx;	  	
}

/*----------------------外部中断3服务程序中断服务函数--------------------------*/
void EXTI3_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(KEY1==0)	 //按键KEY1
	{		
		LED0=!LED0;
		LED1=!LED1;
	}		 
	EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位  
}

/******************************************************************************
//函数名称:NVIC设置函数
//作用:设置NVIC。数值越小,优先级越高。
//示例:NVICInit(2,1,EXTI3_IRQn,2);
//说明:设置抢占优先级为2,子优先级为1,中断类型为EXTI3_IRQn,中断分组方式为组2.
//作者:陈德强
//时间:2019年4月11日00:52:32
//修改者:
//修改时间:
//修改说明:
*******************************************************************************/   

void NVICPriorityGroupConfig(u8 NVIC_Group)	 
{ 
	u32 temp,temp1;	  
	temp1=(~NVIC_Group)&0x07;
	temp1<<=8;
	temp=SCB->AIRCR;  
	temp&=0X0000F8FF; 
	temp|=0X05FA0000; 
	temp|=temp1;	   
	SCB->AIRCR=temp;      	  				   
}
void NVICInit(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)	 
{ 
	u32 temp;	
	NVICPriorityGroupConfig(NVIC_Group);
	temp=NVIC_PreemptionPriority<<(4-NVIC_Group);	  
	temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
	temp&=0xf;								  
	NVIC->ISER[NVIC_Channel/32]|=(1<<NVIC_Channel%32);
	NVIC->IP[NVIC_Channel]|=temp<<4;		  	    	  				   
} 

/******************************************************************************
//函数名称:独立看门狗初始化
//作用:程序卡死时自动复位。
//示例:IWDG_Init(4,625);//约为1s
//说明:时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
//作者:陈德强
//时间:2019年4月11日08:20:43
//修改者:
//修改时间:
//修改说明:
*******************************************************************************/   
void IWDG_Init(u8 prer,u16 rlr) 
{	
 	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);  	
	IWDG_SetPrescaler(prer);  
	IWDG_SetReload(rlr);  
	IWDG_ReloadCounter();  	
	IWDG_Enable();  
}

/******************************************************************************
//函数名称:通用定时器初始化函数
//作用:初始化通用定时器,即定时器2、3、4、5。
//示例:TIMInit(TIM3,500);
//说明:500ms更新一次,arr和psc随便设置,不超过2^16-1就行。.
//作者:陈德强
//时间:2019年4月11日09:12:40
//修改者:
//修改时间:
//修改说明:
*******************************************************************************/ 
void TIMInit(TIM_TypeDef* TIMx,u16 uptime)
{
	u8 addr;
	if(TIMx==TIM2)addr=1;
	if(TIMx==TIM3)addr=2;	
	if(TIMx==TIM4)addr=3;	
	if(TIMx==TIM5)addr=4;	
	RCC->APB1ENR|=1<<addr;	 
 	TIMx->ARR=uptime*10-1;  
	TIMx->PSC=7200-1;		  
	TIMx->DIER|=1<<0; 
	TIMx->CR1|=0x01;							 
}
/*---------------------------定时器3中断服务程序------------------------------*/
void TIM3_IRQHandler(void)   
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  
		{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );   
		LED1=!LED1;
		}
}

/******************************************************************************
//函数名称:PWM初始化函数
//作用:初始化PWM。TIM2-TIM5,每个定时器4个通道。每个通道有固定引脚。
//      目前仅写了PWMInit(TIM2,2,900);和PWMInit(TIM3,1,900);和PWMInit(TIM3,2,900);
//示例:PWMInit(TIM2,1,900);//启用定时器2的CH1通道,自动装载值为0-899。
//说明:PWM频率=72000000/900=80Khz。
//PWM的调用函数:TIM_SetCompare2(TIM2,100);	//第二个参数要在自动装载值的范围内,即0-899
//作者:陈德强
//时间:2019年4月11日12:23:19
//修改者:
//修改时间:
//修改说明:
*******************************************************************************/ 
void PWMInit(TIM_TypeDef *TIMx,u8 CHx,u16 arr)
{		 					 
	u8 addr;
	if(TIMx==TIM2)addr=1;
	if(TIMx==TIM3)addr=2;	
	if(TIMx==TIM4)addr=3;	
	if(TIMx==TIM5)addr=4;	
	RCC->APB1ENR|=1<<addr;	   

	if((TIMx==TIM2)&&(CHx==2))//TIM2的CH2通道PA1
	{
		RCC->APB1ENR|=1<<0; 		//TIM2时钟使能    
		RCC->APB2ENR|=1<<1;    	//使能PORTA时钟	
		GPIOA->CRL&=0XFFFFFF0F;	//PA1输出
		GPIOA->CRL|=0X000000B0;	//复用功能输出 	  	 	 
		RCC->APB2ENR|=0x01;     	   
		TIMx->ARR=arr-1;			
		TIMx->PSC=0;			
		TIMx->CCMR1|=7<<12;  	 
		TIMx->CCMR1|=1<<11; 	   
		TIMx->CCER|=1<<4;   	   
		TIMx->CR1=0x0080;   	
		TIMx->CR1|=0x01;    	 		
	}	
	if((TIMx==TIM3)&&(CHx==1))//TIM3的CH1通道PB5
	{
		RCC->APB1ENR|=1<<1; 	    
		RCC->APB2ENR|=1<<3;    	
		GPIOB->CRL&=0XFF0FFFFF;	
		GPIOB->CRL|=0X00B00000;		  	 		 
		RCC->APB2ENR|=1<<0;       
		AFIO->MAPR&=0XFFFFF3FF; 
		AFIO->MAPR|=1<<11;      
		TIM3->ARR=arr;			
		TIM3->PSC=0;			
		TIM3->CCMR1|=7<<12;  		 
		TIM3->CCMR1|=1<<11; 		   
		TIM3->CCER|=1<<4;   	   
		TIM3->CR1=0x0080;   	
		TIM3->CR1|=0x01;    	
	}
		if((TIMx==TIM3)&&(CHx==2))//TIM3的CH2通道PA7
	{
		RCC->APB1ENR|=1<<1; 		  
		RCC->APB2ENR|=1<<1;    		
		GPIOA->CRL&=0X0FFFFFFF;	
		GPIOA->CRL|=0XB0000000;		  	 	 
		RCC->APB2ENR|=0x01;     	   
		TIMx->ARR=arr-1;			
		TIMx->PSC=0;			
		TIMx->CCMR1|=7<<12;  	 
		TIMx->CCMR1|=1<<11; 	   
		TIMx->CCER|=1<<4;   	   
		TIMx->CR1=0x0080;   	
		TIMx->CR1|=0x01;    	 		
	}	
}  

/******************************************************************************
//函数名称:输入捕获初始化函数
//作用:捕获PA0的上升沿,并输出结果。
//示例:CapInit(0XFFFF,72-1);
//说明:
//PWM的调用函数:由定时器中断处理。
//作者:陈德强
//时间:2019年4月11日16:56:00
//修改者:
//修改时间:
//修改说明:
*******************************************************************************/ 
void CapInit(u16 arr,u16 psc)
{		 
	RCC->APB1ENR|=1<<3;   	//TIM5 时钟使能 
	RCC->APB2ENR|=1<<2;    	//使能PORTA时钟  
	 
	GPIOA->CRL&=0XFFFFFFF0;	//PA0 清除之前设置  
	GPIOA->CRL|=0X00000008;	//PA0 输入   
	GPIOA->ODR|=0<<0;		//PA0 下拉
	  
 	TIM5->ARR=arr;  		//设定计数器自动重装值   
	TIM5->PSC=psc;  		//预分频器 

	TIM5->CCMR1|=1<<0;		//CC1S=01 	选择输入端 IC1映射到TI1上
 	TIM5->CCMR1|=0<<4; 		//IC1F=0000 配置输入滤波器 不滤波
 	TIM5->CCMR1|=0<<10; 	//IC2PS=00 	配置输入分频,不分频 

	TIM5->CCER|=0<<1; 		//CC1P=0	上升沿捕获
	TIM5->CCER|=1<<0; 		//CC1E=1 	允许捕获计数器的值到捕获寄存器中

	TIM5->DIER|=1<<1;   	//允许捕获中断				
	TIM5->DIER|=1<<0;   	//允许更新中断	
	TIM5->CR1|=0x01;    	//使能定时器2
}

void TIM5_IRQHandler(void)
{ 		    
	if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
	{	    
		if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)
		{	
			printf("捕获到一次上升沿输入!
");
			LED0=!LED0;
		}			     	    					   
	TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位	    
	}
}

二、imut.h文件

#ifndef __IMUT_H__
#define __IMUT_H__

#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "usart.h"	

#define KEY0 		PEin(4)
#define LED0 		PBout(5)
#define LED1 		PEout(5)
#define KEY0 		PEin(4)
#define KEY1 		PEin(3)
#define WakeUP  PAin(0)
#define BEEP    PBout(8)



void SysInit(void);
void GPIOInit(GPIO_TypeDef * GPIOx,u8 Pin,int OutOrIN);
u8 KEY_Scan(u8 mode);
void NVICPriorityGroupConfig(u8 NVIC_Group);
void NVICInit(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group);
void USART2_Init(int BaudRate);
void ExtiInit(GPIO_TypeDef * GPIOx,u8 BITx,u8 UpOrDown);
void LEDInit(u8 LED);
void KeyInit(u8 KEY);
void USARTInit(u8 usart,int paudrate);
void IWDG_Init(u8 prer,u16 rlr);
void TIMInit(TIM_TypeDef* TIMx,u16 uptime);
void PWMInit(TIM_TypeDef* TIMx,u8 CHx,u16 arr);
void CapInit(u16 arr,u16 psc);

#endif

原文地址:https://www.cnblogs.com/chendeqiang/p/12861630.html