打印
[STM32F1]

STM32F103多通道转换问题

[复制链接]
1684|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
pofu007|  楼主 | 2014-8-1 12:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 pofu007 于 2014-8-1 13:00 编辑

ADC_InitStructure.ADC_ScanConvMode = ENABLE;                // 扫描一个通道组
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        // 模数转换工作在单次转换模式
ADC_InitStructure.ADC_NbrOfChannel = 10;
如此配置,我理解的意思是这样的,regular group中含10个通道,启动转换信号发生后,采用扫描方式对regular group中的10个通道完成转换一次。
但是我试图用while(RESET == ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));去判断转换是否完成的时候,发现无法跳出循环,也就是EOC位不会置位。
另外采用扫描方式需要配置DMA我已设置好,调试发现启动转换后DMA对应的内存中确实有数据,难道启用的DMA后,扫描方式不需要去查询转换是否完成?
为了说明问题,我把配置的代码都贴一下。
u16 AD_Value[10] = {0};

//=============================================================================
// 入口参数:
// 返    回:
// 函数功能:ADC模块初始化配置
//=============================================================================
void ADC_Config(void)
{         
        ADC_InitTypeDef ADC_InitStructure;
        
        //使能ADC1通道时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );         

        //设置ADC模块时钟分频系数为6,64M/8=8M,ADC最大工作时钟频率不能超过14M
        RCC_ADCCLKConfig(RCC_PCLK2_Div8);   
        
        //复位ADC1,将外设ADC1的全部寄存器重设为缺省值
        ADC_DeInit(ADC1);  

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        // ADC工作模式:ADC1和ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;                // 扫描一个通道组
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        // 模数转换工作在单次转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        // 转换由软件而不是外部触发启动
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        // ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 10;        // 顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC1, &ADC_InitStructure);                        // 根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   
        
        // 设置指定ADC的规则组通道,电池电压检测端口为AIN2,转换10,去除最大最小值,取剩余8个有效值的均值
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_55Cycles5 );        //ADC1,ADC通道,采样时间为55.5周期
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 4, ADC_SampleTime_55Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 5, ADC_SampleTime_55Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 6, ADC_SampleTime_55Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 7, ADC_SampleTime_55Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 8, ADC_SampleTime_55Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 9, ADC_SampleTime_55Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 10, ADC_SampleTime_55Cycles5 );

        // 开启ADC1的DMA支持
        ADC_DMACmd(ADC1, ENABLE);
        
        //使能ADC1
        ADC_Cmd(ADC1, ENABLE);        
        
        //使能复位校准
        ADC_ResetCalibration(ADC1);  
        
        //等待复位校准结束
        while(ADC_GetResetCalibrationStatus(ADC1));        
        
         //开启AD校准
        ADC_StartCalibration(ADC1);        
        
        //等待校准结束
        while(ADC_GetCalibrationStatus(ADC1));         
}


//=============================================================================
// 入口参数:
// 返    回:
// 函数功能:DMA模块初始化配置
//=============================================================================
void DMA_Config(void)
{
        DMA_InitTypeDef DMA_InitStructure;
        
        // 使能DMA1时钟
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        
        DMA_DeInit(DMA1_Channel1);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;        // DMA外设ADC基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)AD_Value;                // DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;        // 内存作为数据传输目的地
        DMA_InitStructure.DMA_BufferSize = 10;        // DMA通道的缓存大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        // 外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;        // 内存地址寄存器递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;        // 数据位宽为16bit
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        // DMA工作在循环缓存模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道拥有最高优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;        // DMA通道不设置内存到内存传输
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);
        
        DMA_Cmd(DMA1_Channel1, ENABLE);
}


u16 GetResultValue(void)
{
        u16 ResultValue = 0;
        u16 MinValue = (u16)0xffff;
        u16 MaxValue = 0;
        u8 i = 0;
        
        // 软件启动ADC1转换
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
        
        // 等待转换完成
        while(RESET == ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
        
        for(i = 0; i < 10; i++)
        {
                ResultValue += AD_Value;
               
                if(AD_Value < MinValue)
                {
                        MinValue = AD_Value;
                }
               
                if(AD_Value > MaxValue)
                {
                        MaxValue = AD_Value;
                }
               
                AD_Value = 0;
        }
        
        ResultValue -= MinValue + MaxValue;
        return ResultValue >>= 3;
}
沙发
香水城| | 2014-8-1 13:10 | 只看该作者
ADC_InitStructure.ADC_ScanConvMode = ENABLE;                // 扫描一个通道组
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        // 模数转换工作在单次转换模式
ADC_InitStructure.ADC_NbrOfChannel = 10;
如此配置,我理解的意思是这样的,regular group中含10个通道,启动转换信号发生后,采用扫描方式对regular group中的10个通道完成转换一次。


你的理解没错。

软件查询EOC的时候,调试窗口不要打开:因为EOC这个标志是rc_w0属性,即读取就清零了。

另外,F1的标准外设固件库中有使用DMA的ADC转换例程,可以参考
STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\ADC\ADC1_DMA

使用特权

评论回复
板凳
pofu007|  楼主 | 2014-8-1 13:45 | 只看该作者
香水城 发表于 2014-8-1 13:10
ADC_InitStructure.ADC_ScanConvMode = ENABLE;                // 扫描一个通道组
ADC_InitStructure.ADC_ ...

例程中的转换模式都是continuous mode,而且都是单通道转换,所以我看了以后也仍然是没明白的。
我看参考手册有这么一段话Only the end of conversion of a regular channel generates a DMA request, which allows the transfer of its converted data from the ADC_DR register to the destination location selected by the user.
对于regular group每个通道转换完成都会产生一次DMA请求,是不是说每个通道转换结束都会产生一个EOC信号,而不是一个组内的所有通道都完成了才产生一次EOC供用户软件查询,然后可以去读取DMA指向的内存中的数据了。

使用特权

评论回复
地板
21ID| | 2014-8-1 14:56 | 只看该作者
可以用DMA发送完成中断,另外我的理解是一组中的通道全部转换完成以后才产生中断的

使用特权

评论回复
5
picasso101| | 2014-9-25 16:19 | 只看该作者
正在学习这个

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

60

帖子

1

粉丝