我在工作中会用到5V,12V等常见的电压输出,由于使用开关电源做输出比较麻烦,所以设置一个四路的降压模块,现在将其分享出来给大家参考一下。
降压电路部分:采用XL4015左右电压芯片,选用该芯片的考虑点是宽电压输入 8V-36V范围,这个范围基本上在工作中比较容易找到,效率也比较高,具体参数如下图:
设计的电路图如下:
由于单片机采用3.3V工作电压,所以固定一路输出为5V输出,该输出电压也可以为其他负载提供电压输出,在PCB布局时,将5V和3.3V输出引出外部提供电压输出。
二:屏幕显示使用的IIC接口的OLED屏幕:资料如下:
采用i2C接口的1.3寸的12864 OLED模块显示,采用该屏幕主要是接线方便,对屏幕的刷新速度要求不高,只是用作显示电压使用;缺点是单色的,看起来并不是很友好。
软件控制部分:硬件设计资料:采用STM32的定时器4的PWM输出功能,为了使输出的电压恒定,输出电压经过了两次RC电路,然后 进入运放LM358,这个运放工作时,不需要负电压就可以,而且价格便宜,图纸如下
电压采集部分:将XL4015输出端的电压经过电阻分压进入单片机的ADC采样口,设置分压电路时,需要注意下,输出电压最大时,不能超过单片IO口最高的承受电压的能力。这里需要将输出电压进入单片机内部进行采集,用于检测PWM输出是否正常。
实物测试图片如下:
实物测试图片如下:
主要软件代码如下:
利用ADC检测电压输出是否正常:
view plaincopy to clipboardprint?
//单通道 DMA adc数据
volatile u16 adc_values;
volatile u16 adc_buf[400];
//-------------单通道 ADC读取----------------
void Adc_Init(void) {
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12MHz
//ADC1通道11的转换时间为T=(239.5+12.5) x 1/12=21us。
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1);//复位ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC 独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//单次扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//单次转换模式
ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;//ADC1 和ADC2 工作在同步规则模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1 ;//进行规则转换的ADC通道数量
ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC1
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);//开启复位校准
while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准成功
ADC_StartCalibration(ADC1);//开始校验ADC1
while(ADC_GetCalibrationStatus(ADC1));//等待校验成功
}
u16 get_ADC_Values(u8 ch, u8 rank) {
//设置指定ADC规则通道,设置转换时间
ADC_RegularChannelConfig(ADC1, ch, rank, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //开启软件转换
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); //等待转换结束
return ADC_GetConversionValue(ADC1);
}
//返回ADC平均值
u16 get_ADC_Average(u8 ch, u8 rank, u8 count) {
u32 temp_val = 0;
u8 i;
for(i = 0; i < count; i++) {
temp_val += get_ADC_Values(ch, rank);
delay_ms(5);
}
return temp_val / count;
}
//-------------单通道 ADC DMA读取----------------
void ADC_DMA_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
//使能DMA1时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
//初始化IO
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//复位DMA1 通道1 ADC
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//ADC内存基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&adc_values;//变量基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设到内存
DMA_InitStructure.DMA_BufferSize = 1;//数据宽度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设内存地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//变量内存地址不变
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16字节 12位ADC
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16字节
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//关闭内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA1 通道1
DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA 通道1
ADC_DeInit(ADC1);//复位ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //关闭扫描
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换 触发一次 持续转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1;//转换一个通道
ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC
//ADC时钟 不能大于14MHz
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12MHz
//设置指定ADC规则通道,设置转换时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
//使能ADC DMA
ADC_DMACmd(ADC1, ENABLE);
//使能ADC
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);//复位校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器复位完成
ADC_StartCalibration(ADC1);//ADC校准
while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//由于没有采用外部触发,所以使用软件触发ADC转换
}
//返回ADC平均值
u16 get_ADC_DMA_Average(u8 count) {
u32 temp_val = 0;
u8 i;
for(i = 0; i < count; i++) {
temp_val += adc_values;
delay_ms(5);
}
return temp_val / count;
}
//-------------多通道 ADC DMA读取----------------
void ADC_DMA_Multichannel_Init(uint16_t *ADC_Buff) {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
//使能DMA1时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
//初始化IO
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//复位DMA1 通道1 ADC
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//ADC内存基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_Buff;//变量基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设到内存
DMA_InitStructure.DMA_BufferSize = 400;//数据宽度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设内存地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//变量内存地址增长
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16字节 12位ADC
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16字节
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//关闭内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA1 通道1
DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA 通道1
ADC_DeInit(ADC1);//复位ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //开启扫描 多通道读取
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换 触发一次 持续转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 4;//转换3个通道
ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC
//ADC时钟 不能大于14MHz
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12MHz
//设置指定ADC规则通道,设置转换时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_13Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_13Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_13Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_13Cycles5);
//使能ADC DMA
ADC_DMACmd(ADC1, ENABLE);
//使能ADC
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);//复位校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器复位完成
ADC_StartCalibration(ADC1);//ADC校准
while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//由于没有采用外部触发,所以使用软件触发ADC转换
}