|
使用Freertos,但是只有一个任务每秒调用一次ADC,所以不存在重入的问题。
定义:
typedef uint16_t adcval_t;
typedef struct adc_t
{
ADC_HandleTypeDef *hadc;
uint32_t chs; // AD采样的通道数
volatile int adc_st; // -1:failed, 0:running, 1:completed
uint32_t timeout_ns; // 超时
sram_block_t dma_buf; // DMA buffer, 预先分配在D2/D3区
} adc_t;
函数:
void RunAdc(adc_t *adc)
{
adc->adc_st = 0; // 清标志
int rtv = 0;
if (HAL_OK != HAL_ADC_Start_DMA(adc->hadc, (uint32_t *)(adc->dma_buf.pData), adc->chs)) // 启动ADC
{
rtv = -1;//启动失败
}
else
{
nsTmr_t ns;
SetNsTmr(&ns, adc->timeout_ns); // 使用定时器做超时判断
while (adc->adc_st == 0) // 等完成标志
{
if (IsNsTmrExpired(&ns))
{
rtv = -2; // 超时
break;
}
}
if (HAL_OK != HAL_ADC_Stop_DMA(adc->hadc))
{
rtv = -3;//停止失败
}
}
if (rtv != 0)
{//有错,写标志,清除数据
adc->adc_st = rtv;
memset(adc->dma_buf.pData, 0, adc->dma_buf.size);
}
}
中断中完成调用:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if (hadc == adc2.hadc)
{
adc2.adc_st = 1;//完成
}
else if (hadc == adc3.hadc)
{
adc3.adc_st = 1;//完成
}
}
ADC时钟24M,6个通道,16倍超采样。那么做一次AD需要(2.5+7.5)*16*6个ADC时钟周期=40uS,我给了1ms+3*40us的timeout。
偶尔发生超时的情况,在“rtv = -2;”,短的时候间隔几分钟,长的间隔有3天。
调试方式下,在HAL_ADC_ErrorCallback下断点,超时发生的时候也没有触发。
实在无法理解为什么AD会无法完成,请各位大侠指导一下。谢谢
|
|