开始考虑的是判断AD状态转换位while (ADCON0bits.GO_nDONE),这种方式可以正常读取转换结果,但是隐隐觉得这种方式不可靠,然后就考虑用定时器,结果不能正常读取。程序设计思路:1ms定时执行AdcPro,读取A通道结果,通道索引切换到B通道启动转换,读取B通道结果,通道索引切换到C通道启动转换,读取C通道结果,通道索引切换到A通道启动转换,一个循环后采样次数++。
FOSC = 32Mhz
ADC初始化
/*
*********************************************************************************************************
* 函 数 名: ADC_Init
* 功能说明: ADC初始化
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void ADC_Init()
{
VBAT_SEN_EN_SetDigitalOutput();
VHALL_SEN_EN_SetDigitalOutput();
TRISA = 0xFF; //PORTA as input
ANCON0 = 0X0F; //引脚配置为模拟通道
ADCON1 = 0x00; // 外部正参考电压,AVdd为负电压,模拟反相通道为AVss
ADCON2 = 0xA9; // FOSC/8 as conversion clock, Result is right justified,Aquisition time of 12 TAD
ADC_StartConversion(ADC_CHS_VBAT);
}
ADC处理
/*
*********************************************************************************************************
* 函 数 名: AdcPro
* 功能说明: ADC滤波处理
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void AdcPro(void)
{
static uint16_t buf[ADC_SAMP_CNT][ADC_CHS_NUM];// ADC_SAMP_CNT = 3,ADC_CHS_NUM = 3
static uint8_t write = 0;
static uint8_t index = ADC_CHS_VBAT;
uint16_t sum;
uint8_t i;
if(index == ADC_CHS_VBAT)//电池电压采集
{
buf[write][ADC_CHS_VBAT] = ADC_GetConversionValue();
/* 下面这段代码采用求平均值的方法进行滤波
也可以改善下,选择去掉最大和最下2个值,使数据更加精确
*/
sum = 0;
for (i = 0; i < ADC_SAMP_CNT; i++)
{
sum += buf[i][ADC_CHS_VBAT];
}
SysRunData.ADC_Buf[ADC_CHS_VBAT] = sum / ADC_SAMP_CNT; /* ADC采样值由若干次采样值平均 */
index = ADC_CHS_CURRENT_R;
ADC_StartConversion(ADC_CHS_CURRENT_R); /* 软件启动下次ADC转换 */
}
else if(index = ADC_CHS_CURRENT_R)//右边踏板堵转电流采集
{
buf[write][ADC_CHS_CURRENT_R] = ADC_GetConversionValue();
/* 下面这段代码采用求平均值的方法进行滤波
也可以改善下,选择去掉最大和最下2个值,使数据更加精确
*/
sum = 0;
for (i = 0; i < ADC_SAMP_CNT; i++)
{
sum += buf[i][ADC_CHS_CURRENT_R];
}
SysRunData.ADC_Buf[ADC_CHS_CURRENT_R] = sum / ADC_SAMP_CNT; /* ADC采样值由若干次采样值平均 */
index = ADC_CHS_CURRENT_L;
ADC_StartConversion(ADC_CHS_CURRENT_L); /* 软件启动下次ADC转换 */
}
else if(index == ADC_CHS_CURRENT_L)//左边踏板堵转电流采集
{
buf[write][ADC_CHS_CURRENT_L] = ADC_GetConversionValue();
if (++write >= ADC_SAMP_CNT)
{
write = 0;
}
/* 下面这段代码采用求平均值的方法进行滤波
也可以改善下,选择去掉最大和最下2个值,使数据更加精确
*/
sum = 0;
for (i = 0; i < ADC_SAMP_CNT; i++)
{
sum += buf[i][ADC_CHS_CURRENT_L];
}
SysRunData.ADC_Buf[ADC_CHS_CURRENT_L] = sum / ADC_SAMP_CNT; /* ADC采样值由若干次采样值平均 */
index = ADC_CHS_VBAT;
ADC_StartConversion(ADC_CHS_VBAT); /* 软件启动下次ADC转换 */
}
}
读取转换结果函数
uint16_t ADC_GetConversionValue()
{
// Conversion finished, return the result
return ((ADRESH << 8) + ADRESL);
}
启动ADC转换
void ADC_StartConversion(uint8_t channel)
{
// select the A/D channel
ADCON0bits.CHS = channel;
// Turn on the ADC module
ADCON0bits.ADON = 1;
// Acquisition time delay
// __delay_us(ACQ_US_DELAY);
// Start the conversion
ADCON0bits.GO_NOT_DONE = 1;
}
|