提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
一、ADC是什么?
ADC名为模数转换,也是单片机最基础的东西。尤其是做电压电流采样这样项目。
二、ADC配置
1.单通道ADC配置
ADC.h
#ifndef __ADC_H
#define __ADC_H
#include "CH58x_common.h"
#include "USART.h"
#define ADC_IN0 GPIO_Pin_4
void ADC_Init(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga);
uint16_t ADC_OUTPUT_Dat(void);
#endif
ADC.c
#include "ADC.h"
signed short RoughCalib_Value = 0; // ADC粗调偏差值
uint16_t abcBuff[8];
uint16_t adc_sum;
uint16_t adc_average;
static void ADC_GPIO_Init(void){
GPIOA_ModeCfg(ADC_IN0, GPIO_ModeIN_Floating);
}
void ADC_Init(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga){ //单通道采样
ADC_GPIO_Init();
ADC_ExtSingleChSampInit(sp, ga);
RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中
printf("RoughCalib_Value =%d \n", RoughCalib_Value);
ADC_ChannelCfg(0);
}
uint16_t ADC_OUTPUT_Dat(void){
ADC_ChannelCfg(0);
adc_sum=0;
for(int i=0;i<8;i++){
RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中
abcBuff[i] = ADC_ExcutSingleConver()+ RoughCalib_Value; // 连续采样20次
adc_sum+=abcBuff[i];
}
adc_average=adc_sum/8;
printf("%d\n", adc_average); // 注意:由于ADC内部偏差的存在,当采样电压在所选增益范围极限附近的时候,可能会出现数据溢出的现象
printf("RoughCalib_Value->%d\n", RoughCalib_Value);
return adc_average;
}
手上没有什么ADC的模块,直接两个电阻搞一个分压电路。
2.ADC+DMA
ADC.h
#ifndef __ADC_H
#define __ADC_H
#include "CH58x_common.h"
#include "USART.h"
#define ADC_IN0 GPIO_Pin_4
void ADC_Init(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga);
uint16_t ADC_OUTPUT_Dat(void);
void ADC_DMA_Init(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga);
uint16_t ADC_DMA_OUTPUT_Dat(void);
#endif
ADC.c
#include "ADC.h"
signed short RoughCalib_Value = 0; // ADC粗调偏差值
uint16_t abcBuff[8];
uint16_t adc_sum;
uint16_t adc_average;
volatile uint8_t DMA_end = 0;
volatile uint8_t adclen;
static void ADC_GPIO_Init(void){
GPIOA_ModeCfg(ADC_IN0, GPIO_ModeIN_Floating);
}
void ADC_Init(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga){ //单通道采样
ADC_GPIO_Init();
ADC_ExtSingleChSampInit(sp, ga);
RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中
printf("RoughCalib_Value =%d \n", RoughCalib_Value);
ADC_ChannelCfg(0);
}
void ADC_DMA_Init(ADC_SampClkTypeDef sp, ADC_SignalPGATypeDef ga){
/* DMA单通道采样:选择adc通道0做采样,对应 PA4引脚 */
ADC_GPIO_Init();
ADC_ExtSingleChSampInit(sp, ga);
ADC_ChannelCfg(0);
ADC_AutoConverCycle(192); // 采样周期 为 (256-192)*16个系统时钟
ADC_DMACfg(ENABLE, (uint16_t)(uint32_t)&abcBuff[0], (uint16_t)(uint32_t)&abcBuff[40], ADC_Mode_LOOP);
PFIC_EnableIRQ(ADC_IRQn);
ADC_StartDMA();
while(!DMA_end);
DMA_end = 0;
printf("ADC DMA end \n");
// for(i = 0; i < 40; i++)
// {
// PRINT("%d \n", abcBuff[i]);
// }
}
uint16_t ADC_DMA_OUTPUT_Dat(void){
ADC_StartDMA();
while(!DMA_end);
DMA_end = 0;
printf("%d \n", abcBuff[0]);
return abcBuff[0];
}
/*********************************************************************
* @fn ADC_IRQHandler
*
* @brief ADC中断函数
*
* @return none
*/
__INTERRUPT
__HIGH_CODE
void ADC_IRQHandler(void) //adc中断服务程序
{
if(ADC_GetDMAStatus())
{
ADC_ClearDMAFlag();
ADC_StopDMA();
R16_ADC_DMA_BEG = (uint16_t)(uint32_t)&abcBuff[0];
DMA_end = 1;
}
// if(ADC_GetITStatus()) //ADC中断
// {
// ADC_ClearITFlag();
// if(adclen < 20)
// {
// abcBuff[adclen] = ADC_ReadConverValue();
// ADC_StartUp(); // 作用清除中断标志并开启新一轮采样
// }
//
// adclen++;
// }
}
uint16_t ADC_OUTPUT_Dat(void){
ADC_ChannelCfg(0);
adc_sum=0;
for(int i=0;i<8;i++){
RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中
abcBuff[i] = ADC_ExcutSingleConver()+ RoughCalib_Value; // 连续采样20次
adc_sum+=abcBuff[i];
}
adc_average=adc_sum/8;
printf("%d\n", adc_average); // 注意:由于ADC内部偏差的存在,当采样电压在所选增益范围极限附近的时候,可能会出现数据溢出的现象
printf("RoughCalib_Value->%d\n", RoughCalib_Value);
return adc_average;
}
最后是MounRiver Studio软件串口打印浮点数,看下图
最终效果图:
总结
这就是CH582M的ADC的一些基本配置。对比STM32来说配置还是很简单的