关于STM32的C++使用的那些事,(C工程变C++工程),new和delete的实现

最近要用到C++来写keil工程,要把之前的C工程变成C++工程,好家伙。
学习一下keil怎么建立一个C++工程,还有STM32在C++语言下怎么兼容C。

1.keil工程的魔法棒设置
我这里选择的是版本5,我看网上说要版本6,不是很理解。
然后选择不要使用微库,C++不支持MicroLIB
关于STM32的C++使用的那些事,(C工程变C++工程),new和delete的实现_第1张图片

2.选择编译的方法
把C99Mode选项去掉,然后改成–cpp11关于STM32的C++使用的那些事,(C工程变C++工程),new和delete的实现_第2张图片
3.把中断函数全部都要加extern “C”
例如在这里插入图片描述

或者在头文件中加上

#ifdef __cplusplus
 extern "C" {
#endif 
。。。。
。。。。
。。。
。。。

#ifdef __cplusplus
}
#endif

例如

/**
  ******************************************************************************
  * @file    Demonstrations/CM4/Inc/stm32h7xx_it.h
  * @author  MCD Application Team
  * @brief   This file contains the headers of the interrupt handlers for Cortex-M4.
  ******************************************************************************
  * @attention
  *
  * 

© Copyright (c) 2018 STMicroelectronics. * All rights reserved.

* * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32H7xx_IT_H #define __STM32H7xx_IT_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ void NMI_Handler(void); void HardFault_Handler(void); void MemManage_Handler(void); void BusFault_Handler(void); void UsageFault_Handler(void); void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); void HSEM2_IRQHandler(void); void Error_Handler(void); #ifdef __cplusplus } #endif #endif /* __STM32H7xx_IT_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

4.都这里基本上C++的工程例程就建立起来了。

我用到的C++程度不深,可以说是和C没什么区别,
之前C写程序,都喜欢用全局变量,
现在写C++,就要把这个C++文件抽象成一个类,然后需要用到的全局变量都放进类里面。

这个编程思路逻辑我觉得就是C和C++最大的区别。

有时候写着写着就喜欢面向过程了,而C++是面向对象的,意思就是,我的这个函数完成的功能一定是这个对象的某一个行为。

这句话也很难理解,我过几天再来看都会觉得,这博主在写什么鬼。
再通俗一下,就是一个类成员函数里的变量,都必须只能是类里面所需要的,外界不能访问,只能通知这个对象,让这个对象告诉你要访问的东西,这样的类封装是最好的。

可是我现在写的工程几乎就是C。哈哈哈

下面是我i写的一个类,和网上的没法比。我只用到了继承,和一个类的基本功能,
可以看到,毫无C++的特性。。。。

class ADC__BasClass
{
  public :
		void ADC_DMA_Start_M4(ADC_TypeDef *ADCX);
		uint8_t  Find_MAX_VAL_POS_M4(uint32_t (*val_Sort),int length,uint8_t chn);
    uint8_t  Find_MIN_VAL_POS_M4(uint32_t (*val_Sort),int length,uint8_t chn);
	  void ADC_RegularChnConfig_M4(ADC_HandleTypeDef *hadc, u32 Chn, u32 Rank, u32 SamplingTime);
	  void ADC_DMA_Init_M4(ADC_HandleTypeDef* hadc);
	  WORD DichotomySearch(WORD TargetData, BYTE bOrder, const DWORD DataArray[], WORD ArryNum);
	private:
};

class ADC1_Class: public ADC__BasClass
{
	public:
		
			uint32_t ADC_Average_Val_m4[ADC1_CHANNAL_NUM_m4];
			uint8_t         ubADCDualConversionComplete ;                        /* Set into ADC conversion complete callback */

			ADC1_Class();
			void ADC1_Init_M4();
			ADC1_Collect ADC_Collect_Real_Name;
			void CalBusBarVoltAndCurr_M4(void);
			void CalDC26Voltage_M4(void);
			void CalNtcAndPtcTemperature_M4(void);
			void ADC1_DATA_Deal_Average_M4(void);
	private:
};
extern ADC1_Class ADC1_API;

//以后ADC3负责ADC1的工作,ADC1可能去到M7那里处理电流。
class ADC3_Class: public ADC__BasClass
{
	public:
		uint32_t ADC3_Average_Val_m4[ADC3_CHANNAL_NUM_m4];
		void ADC3_Init_M4();
	  ADC3_Collect ADC3_Collect_Real_Name;
	  void Cal_Break_Temperature(void);
	  void Cal_Bridge_Temperature(void);
	  void Cal_Motor_Temperature(void);
	  void Cal_IGBTABC_Temperature(void);
	  void Cal_5V_Detection	(void);
	  void Cal_Bus_Current(void);
	  void Cal_Bus_Voltage(void);
	  void ADC3_DATA_Deal_Average_M4(void);
	private:
};
extern ADC3_Class ADC3_API;

然后类成员函数的实现如下

void ADC3_Class::Cal_Break_Temperature(void)
{
	 static uint32_t dwTime = 0;
		uint32_t dwADValTemp;
		uint16_t	wBrakeTemperature_Val;
	
   // 1S 计算一次温度
	 if(lwTickCount_M4 >=  dwTime + 1000)
	 {
			dwTime = lwTickCount_M4;
		 
		 	//按照查找表方法计算NTC温度,BRAKE模块IGBT温敏电阻
			dwADValTemp = ADC3_Average_Val_m4[3];         //最近8次的平均
			wBrakeTemperature_Val = DichotomySearch(dwADValTemp, 1, NTCTempArray, 110);
			dwBreak_Temp = (int)(wBrakeTemperature_Val + 1);
		  ADC3_Collect_Real_Name.wBreak_IGTB_temp_m4 = (WORD)(wBrakeTemperature_Val + 1);
	 }

}
void ADC3_Class::Cal_Bridge_Temperature(void)
{
  	static uint32_t dwTime = 0;
		uint32_t dwADValTemp;
		uint16_t	wBridgeTemperature_Val;
	
   // 1S 计算一次温度
	 if(lwTickCount_M4 >=  dwTime + 1000)
	 {
			dwTime = lwTickCount_M4;
		 
		 	//按照查找表方法计算NTC温度,BRAKE模块IGBT温敏电阻
			dwADValTemp = ADC3_Average_Val_m4[4];         //最近8次的平均
			wBridgeTemperature_Val = DichotomySearch(dwADValTemp, 1, NTCTempArray, 110);
			dwPtcMainTemp = (int)(wBridgeTemperature_Val + 1);
		  ADC3_Collect_Real_Name.wBridge_Temp_m4 =(WORD)(wBridgeTemperature_Val + 1);
	 }
}
void ADC3_Class::Cal_Motor_Temperature(void)
{
   	static uint32_t dwTime = 0;
		uint32_t dwADValTemp;
		uint16_t	wMotorTemperature_Val;
	
   // 500ms 计算一次温度
	 if(lwTickCount_M4 >=  dwTime + 500)
	 {
			dwTime = lwTickCount_M4;
		 
		 	//按照查找表方法计算NTC温度,BRAKE模块IGBT温敏电阻
			dwADValTemp = ADC3_Average_Val_m4[0];         //最近8次的平均
			wMotorTemperature_Val = DichotomySearch(dwADValTemp, 1, NTCTempArray, 110);
			dwMotor_Tmep = (int)(wMotorTemperature_Val + 1);
		  ADC3_Collect_Real_Name.w_Motor_temp_m4  = (WORD)(wMotorTemperature_Val + 1);
	 }
}
void ADC3_Class::Cal_IGBTABC_Temperature(void)
{
   static uint32_t dwTime = 0;
		uint32_t dwADValTemp;
		uint16_t	wITBGTemperature_Val;
	
   // 100ms 计算一次温度
	 if(lwTickCount_M4 >=  dwTime + 200)
	 {
			dwTime = lwTickCount_M4;
		 
		 	//按照查找表方法计算 A 相IGBT模块内的温度
			dwADValTemp = ADC3_Average_Val_m4[5];    
			wITBGTemperature_Val = DichotomySearch(dwADValTemp, 1, IGBTTempArray, 140);
		  ADC3_Collect_Real_Name.w_Driver_IGBT_A_Temp_m4 = (WORD)(wITBGTemperature_Val + 1);
			dwNtcDriveTemp1 = (int)(wITBGTemperature_Val + 1);
		 
		 	//按照查找表方法计算 B 相IGBT模块内的温度
			dwADValTemp = ADC3_Average_Val_m4[6];    
			wITBGTemperature_Val = DichotomySearch(dwADValTemp, 1, IGBTTempArray, 140);
			ADC3_Collect_Real_Name.w_Driver_IGBT_B_Temp_m4 = (WORD)(wITBGTemperature_Val + 1);
		  dwNtcDriveTemp2 = (int)(wITBGTemperature_Val + 1);
		 		 
		 	//按照查找表方法计算 C 相IGBT模块内的温度
			dwADValTemp = ADC3_Average_Val_m4[7];    
			wITBGTemperature_Val = DichotomySearch(dwADValTemp, 1, IGBTTempArray, 140);
			ADC3_Collect_Real_Name.w_Driver_IGBT_C_Temp_m4 = (WORD)(wITBGTemperature_Val + 1);
		  dwNtcDriveTemp3 = (int)(wITBGTemperature_Val + 1);
	 }
}
//真实电压值 =  (AD*3.3/65536) *5/2
//数组最后一个数值
void ADC3_Class::Cal_5V_Detection	(void)
{
	float FiveVoltage_Val=0;
	FiveVoltage_Val = ADC3_Average_Val_m4[8]*0.000125;
	//赋值给结构体,判断错误用,*10为了判断准确
	ADC3_Collect_Real_Name.w_5V_Detect_m4 = (WORD)FiveVoltage_Val*10;
	//显示用
	dwDC_FiVe_Vol = (int)(FiveVoltage_Val*10);
	 

}
//计算母线电流漏电
//母线电流:由计算公式 -0.4*Ima+1.67 = AD/65536*3.3 简化而来。
void ADC3_Class::Cal_Bus_Current(void)
{
  float Bus_leakage_Current=0;
	Bus_leakage_Current = ADC3_Average_Val_m4[1]*0.000125 *(-1);
	Bus_leakage_Current +=4.175;
	Bus_leakage_Current *=1000;
	//判断错误用
	ADC3_Collect_Real_Name.iBusBarCurrent_m4 = (WORD)Bus_leakage_Current;
	//显示用
	dwBus_Leakage_Current = (int)Bus_leakage_Current;
}
//Uo = (5* Ui *Rm)/R1 = AD*(3.3/65536)
//
void ADC3_Class::Cal_Bus_Voltage(void)
{
   u16 RM = 120;
	 u32 R1 = 120*1000;
	 float Bus_Vol =0;
	 Bus_Vol =  ADC3_Average_Val_m4[2] * 0.00001 * (R1/RM);
	 //判断错误用
	 ADC3_Collect_Real_Name.wBusBarVoltage_m4  = (WORD)Bus_Vol;
	//显示用
	 dwBusVoltage = (int)Bus_Vol;
	 
}

void ADC3_Class::ADC3_DATA_Deal_Average_M4(void)
{
   uint16_t i=0,j=0,MAX_POS=0,MIN_POS=0,k=0,m=0;
	
   uint32_t val[ADC3_SIMPLE_NUM_m4]={0};
	 uint32_t val_sum[ADC3_CHANNAL_NUM_m4]={0};
	                                        //采集个数    通道数
   uint32_t val1_Sort[ADC3_SIMPLE_NUM_m4][ADC3_CHANNAL_NUM_m4]={0};//5 5
	 
	 if(__HAL_DMA_GET_FLAG(&ADC3_DMAx_Handler,DMA_FLAG_TCIF3_7))
	{

   // printf("aaa\r\n");		
		//	SCB_InvalidateDCache_by_Addr((uint32_t*)ADC_GetDMA_Buf,sizeof(ADC_GetDMA_Buf));
		 	__HAL_DMA_CLEAR_FLAG(&ADC3_DMAx_Handler,DMA_FLAG_TCIF3_7);
	   // count++;
		//采集DMA数据
			 for(i=0;i=base)
	       {
	         base =val_Sort[i];
	         loc =i;

	       }
	    }
 
  return loc;
}
uint8_t ADC__BasClass::Find_MIN_VAL_POS_M4(uint32_t *val_Sort,int length,uint8_t chn)
{
  	uint32_t left=0,right=0,loc=0,i,base;
	    base = val_Sort[0];
    	 loc =left;
	    for (i = 0; i < length; ++i)
	    {
	    	//比比较数还小,就把原来的替代掉
	       if(val_Sort[i]<=base)
	       {
	         base =val_Sort[i];
	         loc =i;

	       }
	    }
 
  return loc;
}

//初始化ADC
//ch: ADC_channels 
//通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
void ADC1_Class::ADC1_Init_M4()
{ 
		ADC1_Handler.Instance												=	ADC1;
		
		#if defined(ADC_36M_m4)
			ADC1_Handler.Init.ClockPrescaler						=	ADC_CLOCK_ASYNC_DIV2; //2分频,ADCCLK=PER_CK/2=72/2=32MHZ
	
		#elif defined(ADC_32M_m4)
			ADC1_Handler.Init.ClockPrescaler						=	ADC_CLOCK_ASYNC_DIV2; //2分频,ADCCLK=PER_CK/2=64/2=32MHZ
		
		#endif
	
		ADC1_Handler.Init.Resolution								=	ADC_RESOLUTION_16B;       //16位模式
		
		 #if  defined(ADC_DMA_m4)
   	ADC1_Handler.Init.ScanConvMode							=	ADC_SCAN_ENABLE;                  //扫描模式	
  	#else
  	ADC1_Handler.Init.ScanConvMode							=	DISABLE;                  //非扫描模式
		
   #endif
		
		ADC1_Handler.Init.EOCSelection							=	ADC_EOC_SEQ_CONV;      //关闭EOC中断
		
		
		ADC1_Handler.Init.LowPowerAutoWait					=	DISABLE;									//自动低功耗关闭				
	
		#if defined(ADC1_TRIGGER_FROM_TIMER)
			ADC1_Handler.Init.ContinuousConvMode    	= DISABLE;       						//关闭连续转换,Continuous mode disabled to have only 1 conversion at each conversion trig
		#else
			ADC1_Handler.Init.ContinuousConvMode      = DISABLE;                   // Continuous mode to have maximum conversion speed (no delay between conversions)
		#endif
		
	#if  defined(ADC_DMA_m4)
	    ADC1_Handler.Init.ContinuousConvMode      = ENABLE;                   // Continuous mode to have maximum conversion speed (no delay between conversions)
	#else
  	  ADC1_Handler.Init.ContinuousConvMode      = DISABLE;                   // Continuous mode to have maximum conversion speed (no delay between conversions)
		
   #endif
		 
		ADC1_Handler.Init.NbrOfConversion						=	ADC1_CHANNAL_NUM_m4;    //1个转换在规则序列中 也就是只转换规则序列1 
		ADC1_Handler.Init.DiscontinuousConvMode			=	DISABLE;            			//禁止不连续采样模式
		ADC1_Handler.Init.NbrOfDiscConversion				=	0;                    		//不连续采样通道数为0
	 
		#if defined(ADC1_TRIGGER_FROM_TIMER)
			ADC1_Handler.Init.ExternalTrigConv        = ADC1_TRIGEER_TRGO; //Timer 15 external event triggering the conversion
			ADC1_Handler.Init.ExternalTrigConvEdge    = ADC_EXTERNALTRIGCONVEDGE_RISING;
		#else
			ADC1_Handler.Init.ExternalTrigConv        = ADC_SOFTWARE_START;       //软件触发
			ADC1_Handler.Init.ExternalTrigConvEdge    = ADC_EXTERNALTRIGCONVEDGE_NONE;   	//使用软件触发
		#endif
		
		
		ADC1_Handler.Init.Overrun										=	ADC_OVR_DATA_OVERWRITTEN;	//有新的数据的死后直接覆盖掉旧数据
		
		ADC1_Handler.Init.OversamplingMode					=	DISABLE;									//过采样关闭
		
  #if  defined(ADC_DMA_m4)
		ADC1_Handler.Init.ConversionDataManagement	=	ADC_CONVERSIONDATA_DMA_CIRCULAR;  	
	#else
  	ADC1_Handler.Init.ConversionDataManagement	=	ADC_CONVERSIONDATA_DR;  	//规则通道的数据仅仅保存在DR寄存器里面
		
   #endif
		
		if (HAL_ADC_Init(&ADC1_Handler) != HAL_OK)															//初始化 
		{
			Error_Handler();
		}   
		
//PA3 温度 ADC1-15
//PA5 母线电压 ADC1-19
//PB0 母线电流 ADC1-9
//PB1 26V检测  ADC1-5
//PF11 温度    ADC1-2
		//通道号是引脚对应表规定好的。
		
		//ADC1_INP15 PA3
 		 ADC_RegularChnConfig_M4(&ADC1_Handler,ADC_CHANNEL_15 ,ADC_REGULAR_RANK_1,ADC_SAMPLETIME_32CYCLES_5); 
		///PA5
		 ADC_RegularChnConfig_M4(&ADC1_Handler,ADC_CHANNEL_19 ,ADC_REGULAR_RANK_2,ADC_SAMPLETIME_32CYCLES_5);
		//PB0
		 ADC_RegularChnConfig_M4(&ADC1_Handler,ADC_CHANNEL_9  ,ADC_REGULAR_RANK_3,ADC_SAMPLETIME_32CYCLES_5);
		//PB1
		 ADC_RegularChnConfig_M4(&ADC1_Handler,ADC_CHANNEL_5  ,ADC_REGULAR_RANK_4,ADC_SAMPLETIME_32CYCLES_5);
	  //PF11
		 ADC_RegularChnConfig_M4(&ADC1_Handler,ADC_CHANNEL_2  ,ADC_REGULAR_RANK_5,ADC_SAMPLETIME_32CYCLES_5);
		
		HAL_ADCEx_Calibration_Start(&ADC1_Handler,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED); 	//ADC校准
	
		#if defined(ADC1_TRIGGER_FROM_TIMER)
			ADC_Timer_Init(&ADC1_Handler);
			if(HAL_TIM_Base_Start(&ADC1Timer_Handler) != HAL_OK)
			{
				Error_Handler();
			}
		#endif
}

void ADC3_Class::ADC3_Init_M4()
{
	
  		ADC3_Handler.Instance												=	ADC3;
		 
		#if defined(ADC_36M_m4)
			  ADC3_Handler.Init.ClockPrescaler						=	ADC_CLOCK_ASYNC_DIV2; //2分频,ADCCLK=PER_CK/2=72/2=36MHZ
	
		#elif defined(ADC_32M_m4)
			  ADC3_Handler.Init.ClockPrescaler						=	ADC_CLOCK_ASYNC_DIV2; //2分频,ADCCLK=PER_CK/2=64/2=32MHZ
		
		#endif
	
		    ADC3_Handler.Init.Resolution								=	ADC_RESOLUTION_16B;       //16位模式
		 
		 #if  defined(ADC_DMA_m4)
      	ADC3_Handler.Init.ScanConvMode							=	ADC_SCAN_ENABLE;                  //扫描模式	
  	#else
  	    ADC3_Handler.Init.ScanConvMode							=	DISABLE;                  //非扫描模式
		
   #endif
		
		ADC3_Handler.Init.EOCSelection							=	ADC_EOC_SEQ_CONV;      //关闭EOC中断
		
		
		ADC3_Handler.Init.LowPowerAutoWait					=	DISABLE;									//自动低功耗关闭				
	
		#if defined(ADC1_TRIGGER_FROM_TIMER)
			ADC3_Handler.Init.ContinuousConvMode    	= DISABLE;       						//关闭连续转换,Continuous mode disabled to have only 1 conversion at each conversion trig
		#else
			ADC3_Handler.Init.ContinuousConvMode      = DISABLE;                   // Continuous mode to have maximum conversion speed (no delay between conversions)
		#endif
		
	#if  defined(ADC_DMA_m4)
	    ADC3_Handler.Init.ContinuousConvMode      = ENABLE;                   // Continuous mode to have maximum conversion speed (no delay between conversions)
	#else
  	  ADC3_Handler.Init.ContinuousConvMode      = DISABLE;                   // Continuous mode to have maximum conversion speed (no delay between conversions)
		
   #endif
		 
		ADC3_Handler.Init.NbrOfConversion						=	ADC3_CHANNAL_NUM_m4;                        //1个转换在规则序列中 也就是只转换规则序列1 
		ADC3_Handler.Init.DiscontinuousConvMode			=	DISABLE;                             //禁止不连续采样模式
		ADC3_Handler.Init.NbrOfDiscConversion				=	0;                    		//不连续采样通道数为0
	 
		#if defined(ADC1_TRIGGER_FROM_TIMER)
			ADC3_Handler.Init.ExternalTrigConv        = ADC1_TRIGEER_TRGO; //Timer 15 external event triggering the conversion
			ADC3_Handler.Init.ExternalTrigConvEdge    = ADC_EXTERNALTRIGCONVEDGE_RISING;
		#else
			ADC3_Handler.Init.ExternalTrigConv        = ADC_SOFTWARE_START;       //软件触发
			ADC3_Handler.Init.ExternalTrigConvEdge    = ADC_EXTERNALTRIGCONVEDGE_NONE;   	//使用软件触发
		#endif
		
		
		ADC3_Handler.Init.Overrun										=	ADC_OVR_DATA_OVERWRITTEN;	//有新的数据的死后直接覆盖掉旧数据
		
		ADC3_Handler.Init.OversamplingMode					=	DISABLE;									//过采样关闭
		
  #if  defined(ADC_DMA_m4)
		ADC3_Handler.Init.ConversionDataManagement	=	ADC_CONVERSIONDATA_DMA_CIRCULAR;  	
	#else
  	ADC3_Handler.Init.ConversionDataManagement	=	ADC_CONVERSIONDATA_DR;  	//规则通道的数据仅仅保存在DR寄存器里面
		
   #endif
		
		if (HAL_ADC_Init(&ADC3_Handler) != HAL_OK)															//初始化 
		{
			Error_Handler();
		}        
		//刹车单元的温度(PF6),整流单元温度(PF7),
		//3个IGBT温度(PF8, PF9,PF10),电机温度(PF3),母线电流漏电(PF4),母线电压采样(PF5),5V检测(PC0)共9个
		//电机温度(PF3)         ADC3_INP5
 		ADC_RegularChnConfig_M4(&ADC3_Handler,ADC_CHANNEL_5  ,ADC_REGULAR_RANK_1,ADC_SAMPLETIME_32CYCLES_5); 
		//母线电流漏电(PF4)    ADC3_INP9
	  ADC_RegularChnConfig_M4(&ADC3_Handler,ADC_CHANNEL_9  ,ADC_REGULAR_RANK_2,ADC_SAMPLETIME_32CYCLES_5);
		//母线电压采样(PF5)    ADC3_INP4
		ADC_RegularChnConfig_M4(&ADC3_Handler,ADC_CHANNEL_4  ,ADC_REGULAR_RANK_3,ADC_SAMPLETIME_32CYCLES_5);
		// 刹车单元的温度(PF6) ADC3_INP8
		ADC_RegularChnConfig_M4(&ADC3_Handler,ADC_CHANNEL_8  ,ADC_REGULAR_RANK_4,ADC_SAMPLETIME_32CYCLES_5);
		// 整流单元温度(PF7)   ADC3_INP3
		ADC_RegularChnConfig_M4(&ADC3_Handler,ADC_CHANNEL_3  ,ADC_REGULAR_RANK_5,ADC_SAMPLETIME_32CYCLES_5);
		// 3个IGBT温度(PF8)      ADC3_INP7
		ADC_RegularChnConfig_M4(&ADC3_Handler,ADC_CHANNEL_7  ,ADC_REGULAR_RANK_6,ADC_SAMPLETIME_32CYCLES_5);
		// 3个IGBT温度(PF9)      ADC3_INP2
		ADC_RegularChnConfig_M4(&ADC3_Handler,ADC_CHANNEL_2  ,ADC_REGULAR_RANK_7,ADC_SAMPLETIME_32CYCLES_5);
		// 3个IGBT温度(PF10)     ADC3_INP6
		ADC_RegularChnConfig_M4(&ADC3_Handler,ADC_CHANNEL_6  ,ADC_REGULAR_RANK_8,ADC_SAMPLETIME_32CYCLES_5);
		// 5V检测(PC0)         ADC3_INP10
		ADC_RegularChnConfig_M4(&ADC3_Handler,ADC_CHANNEL_10  ,ADC_REGULAR_RANK_9,ADC_SAMPLETIME_32CYCLES_5);
		
		 HAL_ADCEx_Calibration_Start(&ADC3_Handler,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED); 	//ADC校准
	
		#if defined(ADC2_TRIGGER_FROM_TIMER)
			ADC_Timer_Init(&ADC3_Handler);
			if(HAL_TIM_Base_Start(&ADC2Timer_Handler) != HAL_OK)
			{
				Error_Handler();
			}
		#endif	
}
//ADC底层驱动,引脚配置,时钟使能
//此函数会被HAL_ADC_Init()调用
//hadc:ADC句柄
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
	GPIO_InitTypeDef GPIO_Initure;
	
	if(hadc->Instance == ADC1)
	{
  
	}
	else if(hadc->Instance == ADC2)
	{
	
	}
	else if(hadc->Instance == ADC3)
	{

		__HAL_RCC_GPIOF_CLK_ENABLE();									//开启GPIOF时钟
		__HAL_RCC_GPIOC_CLK_ENABLE();									//开启GPIOF时钟
		__HAL_RCC_ADC3_CLK_ENABLE();           			//使能ADC3时钟
	
		#if defined(ADC_36M_m4)
			/* 配置PLL2时钟为的72MHz,方便分频产生ADC最高时钟36MHz */
			  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
	PeriphClkInitStruct.PLL2.PLL2M = 25;
	PeriphClkInitStruct.PLL2.PLL2N = 504;
	PeriphClkInitStruct.PLL2.PLL2P = 7;
	PeriphClkInitStruct.PLL2.PLL2Q = 7;
	PeriphClkInitStruct.PLL2.PLL2R = 7;
	PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0;
	PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
	PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
	PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
	if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
	{
	//	Error_Handler(__FILE__, __LINE__);  
	}
		#elif defined(ADC_32M_m4)
	ADC外设时钟选择 //这个就是选择per_ck为ADC的内核时钟,寄存器RCC_D3CCIPR ,而寄存器是RCC_D1CCIPR 又是默认选择了高速内部时钟作为per_ck的时钟,64M
		 __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);	
	//printf("bbb32\n");
		#endif

		//刹车单元的温度(PF6),整流单元温度(PF7),
	  //3个IGBT温度(PF8, PF9,PF10),电机温度(PF3),母线电流漏电(PF4),母线电压采样(PF5),5V检测(PC0)共9个
		GPIO_Initure.Pin=GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;     
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;     			//模拟
    GPIO_Initure.Pull=GPIO_NOPULL;          			//不带上下拉
    HAL_GPIO_Init(GPIOF,&GPIO_Initure);
	
		GPIO_Initure.Pin=GPIO_PIN_0;       					//PCC
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;     			//模拟
    GPIO_Initure.Pull=GPIO_NOPULL;          			//不带上下拉
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);
		
	 #if defined(ADC_DMA_m4)	
	   ADC3_API.ADC_DMA_Init_M4(hadc);
		#endif	
	}
}

void ADC__BasClass::ADC_DMA_Init_M4(ADC_HandleTypeDef* hadc)
{
	//DMA_HandleTypeDef  DMAx_Handler;
	
	if(hadc->Instance == ADC1)
	{
		__HAL_RCC_DMA1_CLK_ENABLE();
		
		DMAx_Handler.Instance = DMA1_Stream1;

    DMAx_Handler.Init.Request             = DMA_REQUEST_ADC1;
    DMAx_Handler.Init.Direction           = DMA_PERIPH_TO_MEMORY;
    DMAx_Handler.Init.PeriphInc           = DMA_PINC_DISABLE;
    DMAx_Handler.Init.MemInc              = DMA_MINC_ENABLE;
    DMAx_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;       /* Transfer from ADC by word to match with ADC configuration: Dual mode, ADC master contains conversion results on data register (32 bits) of ADC master and ADC slave  */
    DMAx_Handler.Init.MemDataAlignment    = DMA_PDATAALIGN_WORD;       /* Transfer to memory by word to match with buffer variable type: word */
    DMAx_Handler.Init.Mode                = DMA_CIRCULAR;              /* DMA in circular mode to match with ADC configuration: DMA continuous requests */
    DMAx_Handler.Init.Priority            = DMA_PRIORITY_HIGH;
		
		//
    DMAx_Handler.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;    /* 禁止FIFO*/
    DMAx_Handler.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
    DMAx_Handler.Init.MemBurst            = DMA_MBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于存储器突发 */
    DMAx_Handler.Init.PeriphBurst         = DMA_PBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于外设突发 */
    // Deinitialize  & Initialize the DMA for new transfer
    HAL_DMA_DeInit(&DMAx_Handler);
    HAL_DMA_Init(&DMAx_Handler);

    // Associate the initialized DMA handle to the ADC handle */
    __HAL_LINKDMA(hadc, DMA_Handle, DMAx_Handler);
  
    // NVIC configuration for DMA interrupt (transfer completion or error)
    // Priority: high-priority
  // HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 1, 0);
  // HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
	}
	else if(hadc->Instance == ADC3)
	{
		__HAL_RCC_DMA1_CLK_ENABLE();
		
		ADC3_DMAx_Handler.Instance = DMA1_Stream3;

    ADC3_DMAx_Handler.Init.Request             = DMA_REQUEST_ADC3;
    ADC3_DMAx_Handler.Init.Direction           = DMA_PERIPH_TO_MEMORY;
    ADC3_DMAx_Handler.Init.PeriphInc           = DMA_PINC_DISABLE;
    ADC3_DMAx_Handler.Init.MemInc              = DMA_MINC_ENABLE;
    ADC3_DMAx_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;       /* Transfer from ADC by word to match with ADC configuration: Dual mode, ADC master contains conversion results on data register (32 bits) of ADC master and ADC slave  */
    ADC3_DMAx_Handler.Init.MemDataAlignment    = DMA_PDATAALIGN_WORD;       /* Transfer to memory by word to match with buffer variable type: word */
    ADC3_DMAx_Handler.Init.Mode                = DMA_CIRCULAR;              /* DMA in circular mode to match with ADC configuration: DMA continuous requests */
    ADC3_DMAx_Handler.Init.Priority            = DMA_PRIORITY_HIGH;
  
			//
    ADC3_DMAx_Handler.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;    /* 禁止FIFO*/
    ADC3_DMAx_Handler.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
    ADC3_DMAx_Handler.Init.MemBurst            = DMA_MBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于存储器突发 */
    ADC3_DMAx_Handler.Init.PeriphBurst         = DMA_PBURST_SINGLE;       /* 禁止FIFO此位不起作用,用于外设突发 */
    // Deinitialize  & Initialize the DMA for new transfer
    HAL_DMA_DeInit(&ADC3_DMAx_Handler);
    HAL_DMA_Init(&ADC3_DMAx_Handler);

    // Associate the initialized DMA handle to the ADC handle
    __HAL_LINKDMA(hadc, DMA_Handle, ADC3_DMAx_Handler);
     
    // NVIC configuration for DMA interrupt (transfer completion or error)
    // Priority: high-priority
   //HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 1, 1);
   // HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
	}

  /* NVIC configuration for ADC interrupt */
  /* Priority: high-priority */
//  HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
//  HAL_NVIC_EnableIRQ(ADC_IRQn);
}


void ADC__BasClass::ADC_RegularChnConfig_M4(ADC_HandleTypeDef *hadc, u32 Chn, u32 Rank, u32 SamplingTime)
{
	ADC_ChannelConfTypeDef sConfig;
	
	sConfig.Channel				=	Chn;                  //通道
	sConfig.Rank					=	Rank;           			//第n个序列
	sConfig.SamplingTime	=	SamplingTime;    			//采样时间       
	sConfig.SingleDiff		=	ADC_SINGLE_ENDED;  		//单边采集          		
	sConfig.OffsetNumber	=	ADC_OFFSET_NONE;             	
	sConfig.Offset				=	0; 
  sConfig.OffsetRightShift       = DISABLE;           /* 禁止右移 */
   sConfig.OffsetSignedSaturation = DISABLE;           /* 禁止有符号饱和 */
	HAL_ADC_ConfigChannel(hadc,&sConfig);        	//通道配置
}

用C++写和C来写,对我来说,最大的区别就是更工整了。变量名不会很乱,其余的C++的优越性,我都没展现出来。

就好像我写的C++就是C的一个结构体。只不过结构体的函数指针,就变成了C++类的成员函数。
就比我结构体多了一个构造函数可以帮我初始化类成员变量的值。
这些都是C都可以实现的。。。。

5.C++在STM32中使用new和delete的方法。

new在C++中是创建一个内存空间,和malloc一样
delete是释放已经创建的一个内存空间,和free一样。

直接上代码

void * operator new(size_t size)
{
	void *res;
	if(size==0)
		 size=1;
	  res =malloc(size);
	   while(1)
		 {
			if(res)
			{
				break;
			 
			}
	   }
		// printf("%d\r\n",size);
		// printf("%x\r\n",res);
	return res;
}
void  operator delete(void * p)
{
	 free(p);
 //  printf("%x\r\n",p);
}

下面是new和delete深入理解
实验:
不delete的话,打印的地址是不会一样。关于STM32的C++使用的那些事,(C工程变C++工程),new和delete的实现_第3张图片

delete的话:

说明delete并不是清空内存,而是把该内存的标志位清0,该标志位表示该内存是被使用的。不能继续分配。把标志位清0了,就说明能再被分配,但是里面的内存的内容是不确定的。

关于STM32的C++使用的那些事,(C工程变C++工程),new和delete的实现_第4张图片

说明,重载是成功的,这些地址是对应M7的heap范围内的地址。

关于STM32的C++使用的那些事,(C工程变C++工程),new和delete的实现_第5张图片

你可能感兴趣的:(STM32H745IIT,stm32)