最近要用到C++来写keil工程,要把之前的C工程变成C++工程,好家伙。
学习一下keil怎么建立一个C++工程,还有STM32在C++语言下怎么兼容C。
1.keil工程的魔法棒设置
我这里选择的是版本5,我看网上说要版本6,不是很理解。
然后选择不要使用微库,C++不支持MicroLIB
2.选择编译的方法
把C99Mode选项去掉,然后改成–cpp11
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的话,打印的地址是不会一样。
delete的话:
说明delete并不是清空内存,而是把该内存的标志位清0,该标志位表示该内存是被使用的。不能继续分配。把标志位清0了,就说明能再被分配,但是里面的内存的内容是不确定的。
说明,重载是成功的,这些地址是对应M7的heap范围内的地址。