CH58x芯片ADC
电池电压采集参考:
默认配置为-12db增益模式,计算时需要选择对应的计算公式
ADC_InterBATSampInit();
for(i = 0; i < 20; i++)
{
abcBuff[i] = ADC_ExcutSingleConver(); // 连续采样20次
}
for(i = 0; i < 20; i++)
{
CountBat += abcBuff[i];
if(i == 0)
{
min_number = abcBuff[i];
max_number = abcBuff[i];
}
min_number = ((min_number > abcBuff[i]) ? abcBuff[i] : min_number); //软件滤波
max_number = ((max_number < abcBuff[i]) ? abcBuff[i] : max_number);
}
printf("min_number = %d, max_number = %d\n", min_number, max_number);
CountBat = (CountBat - min_number - max_number) / 18; //删除最小与最大值
printf("AverageCountBat = %d\n", CountBat);
while(1);
计算公式:
如果仅仅使用ADC功能,同时为了降低功耗,可以将引脚的数字输入功能关闭。
即配置该寄存器:
PA9ADC采集+浮点计算:
测试PA9作为ADC的话,在置为浮空之后,过300ms左右再进行ADC的采集。不然初次烧录的时候boot是串口功能开启的,PA9是输出高电平。切换为浮空会需要时间的。
int main()
{
uint8_t i;
signed short RoughCalib_Value = 0; // ADC粗调偏差值
uint32_t countadc = 0;
uint16_t min_number = 0;
uint16_t max_number = 0;
double voltage = 0;
SetSysClock(CLK_SOURCE_PLL_60MHz);
/* 配置串口调试 */
DebugInit();
PRINT("\nStart @ChipID=%02X\n", R8_CHIP_ID);
/* 单通道采样:选择adc通道0做采样,对应 PA4引脚, 带数据校准功能 */
GPIOA_ModeCfg(1 << 9 | GPIO_Pin_15, GPIO_ModeIN_Floating);
mDelaymS(300);
ADC_ExtSingleChSampInit(SampleFreq_3_2, ADC_PGA_0);
RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中
PRINT("RoughCalib_Value =%d \n", RoughCalib_Value);
printf("PA9:::::\n");
ADC_ChannelCfg(13);
for(i = 0; i < 20; i++)
{
adcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
}
printf("original: ");
for(i = 0; i < 20; i++)
{
PRINT("%d ", adcBuff[i]); // 注意:由于ADC内部偏差的存在,当采样电压在所选增益范围极限附近的时候,可能会出现数据溢出的现象
}printf("\n");
for(i = 0; i < 20; i++)
{
countadc += adcBuff[i];
if(i == 0){
min_number = adcBuff[i];
max_number = adcBuff[i];
}
min_number = ((min_number > adcBuff[i]) ? adcBuff[i] : min_number); //软件滤波
max_number = ((max_number < adcBuff[i]) ? adcBuff[i] : max_number);
}
printf("min=%d, max=%d, diff=%d\n", min_number, max_number, (max_number-min_number));
countadc = (countadc - min_number - max_number) / 18; //删除最小与最大值
printf("countaveradc = %d\n", countadc);
voltage = (double)countadc/2048*1.05;
printf("voltage=%1.3lfv\n", voltage);
while(1);
}
ADC_DMA采样
#include "CH57x_common.h"
uint16_t abcBuff[40];
volatile uint8_t adclen;
volatile uint8_t DMA_end = 0;
volatile uint8_t DMA_endFlag = 0;
void DebugInit(void){
GPIOA_SetBits(GPIO_Pin_9);
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
UART1_DefInit();
}
int main(){
uint8_t i = 0;
signed short RoughCalib_Value = 0; // ADC粗调偏差值
SetSysClock(CLK_SOURCE_PLL_60MHz);
/* 配置串口调试 */
DebugInit();
PRINT("Start @ChipID=%02X\n", R8_CHIP_ID);
/* DMA单通道采样:选择adc通道0做采样,对应 PA4引脚 */
while(1){
GPIOA_ModeCfg(GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12 | GPIO_Pin_13, GPIO_ModeIN_Floating);
ADC_ExtSingleChSampInit(SampleFreq_3_2, ADC_PGA_0);
ADC_ChannelCfg(DMA_endFlag);
ADC_AutoConverCycle(192); // 采样周期为 (256-192)*16个系统时钟
ADC_DMACfg(ENABLE, (uint16_t)(uint32_t)&abcBuff[0], (uint16_t)(uint32_t)&abcBuff[40], ADC_Mode_Single);
PFIC_EnableIRQ(ADC_IRQn);
ADC_StartDMA();
while(!DMA_end);
DMA_end = 0;
PRINT("ADC DMA end \n");
for(i = 0; i < 40; i++){
abcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
}
for(i = 0; i < 40; i++){
PRINT("Channel %d = %d \n", (DMA_endFlag - 1), abcBuff[i]);
}
if(DMA_endFlag == 4){
break;
}
}
while(1);
}
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void ADC_IRQHandler(void)
{
if(ADC_GetDMAStatus()) {
printf("R8_ADC_DMA_IF = %x\n", R8_ADC_DMA_IF);
ADC_ClearDMAFlag();
ADC_StopDMA();
PFIC_DisableIRQ(ADC_IRQn);
R16_ADC_DMA_BEG = (uint16_t)(uint32_t)&abcBuff[0];
// R8_ADC_DMA_IF |= RB_ADC_IF_END_ADC | RB_ADC_IF_DMA_END;
DMA_end = 1;
DMA_endFlag++;
}
if(ADC_GetITStatus()){
ADC_ClearITFlag();
if(adclen < 20){
abcBuff[adclen] = ADC_ReadConverValue();
ADC_StartUp(); // 作用清除中断标志并开启新一轮采样
}
adclen++;
}
}