1. 时钟配置:
1.1 Crystal/Ceramic Resonator(晶体/陶瓷晶振)
1.2 BYPASS Clock Source(旁路时钟)
YPASS Clock Source(旁路时钟源),选择该项,仅RCC_OSC_IN被使能,若你有一个外部时钟源的话可以采用该项。比如采用有源晶振,当用有源晶振作为时钟源,该选择哪种工作模式呢?
有源晶振一般是四脚封装,电源、地线、振荡输出和一个控制端【或者悬空端】。相比无源晶体,有源晶振本身就是个完整的振荡器件,只需要供给适当的电源就能输出时钟,无须额外的振荡驱动匹配电路。其时钟输出不依赖于外部器件振荡电路,相对更不容易受外部线路不稳定性的影响。自然其价格往往要高于无源晶体,不过其输出电平幅度往往不能像无源晶体那样随着应用电路的变化而变化。不难看出,如果使用有源晶振作为外部时钟源的话,我们应该配置为HSE旁路模式,而不是HSE晶体模式,将有源晶振的输出脚接到MCU的OSC_IN脚。
2. 配置电流检测ADC(定时器中断方式)
2.1 电路设计
采用的电流传感器是ACS711,3.3V供电,当电流为0时理论电压为1.65V,每升高电流,电压上升90mV,但是实际测量时发现每上升1A实际上升电压为83mV。
2.2 单通道ADC配置
ADC最大12位显示为0x0FFF,左对齐是0xFFF0,右对齐是0x0FFF,为了方便,右对齐数据保持不变而左对齐还要进行移位处理。
2.3 TIM1定时器配置
72 000 000 / 72 / 10 000 = 10ms执行一次,更新中断。
2.4 就此生成程序
基本方法就是:
让定时器去计时,到时间后,开启ADC中断去获取ADC值,然后在ADC中断里面关闭ADC,TIM,处理完后再跳出,启动定时器,再由定时器循环驱动ADC中断
这样就不会碰到超时时间的问题了,因为是转换完了才再次进的ADC中断,然后再关闭,由定时器决定开关。
该功能主要用到以下函数:
• HAL_ADC_Start_IT(&hadcx); //中断轮询模式开启ADC
• HAL_ADC_Stop_IT() //中断轮询模式停止ADC
• HAL_ADC_GetValue() //读取ADC转换值
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //定时器中断回调
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) //ADC转换完成回调
2.4.1 初始化
void ADC2_Init(void)
{
MX_ADC2_Init();
HAL_ADCEx_Calibration_Start(&hadc2); //AD校准
}
int TIM1_Init(void)
{
MX_TIM1_Init();
HAL_TIM_Base_Start_IT(&htim1); /* 在中断模式下启动定时器 */
return 0;
}
void main_setup(void)
{
ADC2_Init();
TIM1_Init();
}
2.4.2 定时器回调中断开启ADC中断处理
建立自己的私有定时器回调函数
/* 私有变量 ---------------------------------------------------------------------------------------------*/
uint32_t CountTimer_1 = 0;
/* 私有函数原形 -----------------------------------------------------------------------------------------*/
extern int TIM1_PeriodCallback(TIM_HandleTypeDef *htim);
__weak int TIM1_PeriodCallback(TIM_HandleTypeDef *htim)//隐式调用虚函数
{
return 0;
}
在真正的定时器回调函数中去调用它。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1)
{
CountTimer_1++;
TIM1_PeriodCallback(htim);
}
}
int TIM1_PeriodCallback(TIM_HandleTypeDef *htim)
{
HAL_ADC_Start_IT(&hadc2);
return 0;
}
2.4.3 ADC回调中断处理函数
float BusCurrent = 0; //声明母线电流值
ADC采样值处理函数,转化为电流值。
void ADC2_Check(void)
{
HAL_ADC_Stop_IT(&hadc2); //关闭ADC
HAL_TIM_Base_Stop_IT(&htim1); //关闭定时器
uint8_t i;
for(i=0; i<10; i++)
{
BusCurrent+= HAL_ADC_GetValue(&hadc2);
}
BusCurrent = BusCurrent/10;
BusCurrent = (((float)BusCurrent/4096*3300)-1632)/83;
HAL_TIM_Base_Start_IT(&htim1); //开启定时器
}
回调处理函数:
int ADC2_ConvCallback(ADC_HandleTypeDef* hadc)//调用虚函数
{
ADC2_Check();
return 0;
}