OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4277|回复: 21

【请教】关于ADCSTM32F103R8T6的ADC采样

[复制链接]

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
发表于 2017-10-11 16:01:05 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 d779708957ddd 于 2017-10-11 16:25 编辑

编写的程序使用的是ADC+DMA,但是我采样得到的数据都是0引脚是没问题的,我尝试把引脚用作读取高低电平,是能够读取的。
程序里面是用的PA6脚做ADC采样
PC8 PC9我是用作输出脚,来观察是否有采集到数据
劳烦大神花时间帮小弟看一下写的程序哪里有问题,谢谢了。
再附上程序压缩包


下面是adc.c里面的程序

#include "stm32f10x.h"
#include "adc.h"
#include "delay.h"
                                                                                                                                    
void  Adc_Init(u32 cpar,u32 cmar)
{         DMA_InitTypeDef DMA_InitStructure;   
        
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC1        , ENABLE );          //使能ADC1通道时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_8 ;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOC,&GPIO_InitStructure);
        GPIO_SetBits(GPIOC,GPIO_Pin_8);
  GPIO_SetBits(GPIOC,GPIO_Pin_9);        
        
        //PA1 作为模拟通道输入引脚                        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
        GPIO_Init(GPIOA, &GPIO_InitStructure);        
        


        ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
        ADC_StructInit(&ADC_InitStructure);
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;        //模数转换工作在单通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;        //模数转换工作在单次转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不是外部触发启动
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

          ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_55Cycles5 );

        ADC_GetCalibrationStatus(ADC1);
        ADC_DMACmd(ADC1, ENABLE);
        ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1        //使能指定的ADC1的软件转换启动功能
  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
        
         DMA_DeInit(DMA1_Channel1);   //将DMA的通道1寄存器重设为缺省值
    DMA_InitStructure.DMA_PeripheralBaseAddr =  cpar;  //DMA外设ADC基地址
    DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //内存作为数据传输的目的地
    DMA_InitStructure.DMA_BufferSize = 1;  //DMA通道的DMA缓存的数据单元大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //数据宽度为16位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //循环工作模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道
}               

下面是main.c里面的程序
#include "delay.h"
#include "sys.h"
#include "adc.h"
#define ADC1_DR_Address    ((uint32_t)0x4001244C)


u16 AD_Value[1];   
  u16 volta[1];
  u8 i;

int main(void)
{
         SystemInit();
          delay_init();             //延时初始化
          Adc_Init((u32)ADC1_DR_Address,(u32)&AD_Value);
          DMA_Cmd(DMA1_Channel1, ENABLE);      //启动DMA通道
   ADC_SoftwareStartConvCmd(ADC1, ENABLE);          //软件启动AD转换

         GPIO_ResetBits(GPIOC,GPIO_Pin_9);
////////////////////////////////////////////////
     这个脚在我自己设计的硬件板上是接一个LED灯的,加这个是因为我之前用正点原子教程里面那个ADC单通道采样程序修改,但是发现采样不了,然后加了几个GPIO_ResetBits,发现在下面这个程序的while里面卡死了
        ADC_ResetCalibration(ADC1);        //使能复位校准  
        while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
        ADC_StartCalibration(ADC1);         //开启AD校准
        while(ADC_GetCalibrationStatus(ADC1));         //等待校准结

//////////////////////////////////////////////
        delay_ms(50);

while(1)
{      volta =AD_Value/4095*3300;
                        
                if (volta[0]==0)         GPIO_ResetBits(GPIOC,GPIO_Pin_8|GPIO_Pin_9);
          else GPIO_SetBits(GPIOC,GPIO_Pin_8|GPIO_Pin_9);

        delay_ms(50);
}
听二楼的建议我将
u16 volta[1];改成了 float volta[1];
volta =AD_Value/4095*3300; 改成了volta =(float)AD_Value*(3300/4095);
但是还是不行,采样得到的值还是0










DMA ADC采样.rar

2.99 MB, 下载次数: 353

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

808

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3888
金钱
3888
注册时间
2017-3-7
在线时间
1694 小时
发表于 2017-10-11 16:05:55 | 显示全部楼层
AD_Value[i]/4095*3300,你AD_Value为int 型,应该大不过4095,所以除以4095为0,再乘任何数都是0,你可以设置成float或者先乘再除
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-11 16:19:49 | 显示全部楼层
a5820736 发表于 2017-10-11 16:05
AD_Value/4095*3300,你AD_Value为int 型,应该大不过4095,所以除以4095为0,再乘任何数都是0,你可以设置 ...

我试了先乘后除,还试了改成float
float volta[1];
volta =(float)AD_Value*(3300/4095);
但是还是为0
回复

使用道具 举报

3

主题

808

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3888
金钱
3888
注册时间
2017-3-7
在线时间
1694 小时
发表于 2017-10-11 16:30:46 | 显示全部楼层
那你就需要debug下到底有没有采集到数据了
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-11 16:44:05 | 显示全部楼层
a5820736 发表于 2017-10-11 16:30
那你就需要debug下到底有没有采集到数据了

可是我debug应该看哪个数据才知道是否采集到了呢,是那个AD_Value还是说看那个ADC1_DR_Address    ((uint32_t)0x4001244C)
回复

使用道具 举报

0

主题

37

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
389
金钱
389
注册时间
2017-9-27
在线时间
133 小时
发表于 2017-10-11 16:45:55 | 显示全部楼层
AD_Value 加个打印,看看有没有值
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-11 16:54:51 | 显示全部楼层
一战到底 发表于 2017-10-11 16:45
AD_Value 加个打印,看看有没有值

打印是什么
我程序里面的AD_Value后面还有【1】复制发出就没了,不知道你说的是不是这个
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-11 16:57:58 | 显示全部楼层
d779708957ddd 发表于 2017-10-11 16:44
可是我debug应该看哪个数据才知道是否采集到了呢,是那个AD_Value还是说看那个ADC1_DR_Address    ((uint ...

是去看Peripherals里面的ADC1吗,那个点开来看不太懂,DEBUG还不太会用,请见谅
回复

使用道具 举报

0

主题

37

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
389
金钱
389
注册时间
2017-9-27
在线时间
133 小时
发表于 2017-10-11 17:04:34 | 显示全部楼层
printf(),看看AD_Value是否有值。
ADC的配置,除了校准之外,没看出问题。
DMA的配置,看着还行
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-11 17:06:46 | 显示全部楼层
一战到底 发表于 2017-10-11 17:04
printf(),看看AD_Value是否有值。
ADC的配置,除了校准之外,没看出问题。
DMA的配置,看着还行

校验那个,我用过正点原子的单通道ADC采样的例程修改试过,会卡死在校验,我也不知道是为什么
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-11 17:11:15 | 显示全部楼层
一战到底 发表于 2017-10-11 17:04
printf(),看看AD_Value是否有值。
ADC的配置,除了校准之外,没看出问题。
DMA的配置,看着还行

我直接把程序改成  
if (AD_Value【0】==0)         GPIO_ResetBits(GPIOC,GPIO_Pin_8|GPIO_Pin_9);
灯还是亮的,应该AD_Value【0】值为0
回复

使用道具 举报

0

主题

37

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
389
金钱
389
注册时间
2017-9-27
在线时间
133 小时
发表于 2017-10-11 17:12:30 | 显示全部楼层
d779708957ddd 发表于 2017-10-11 17:06
校验那个,我用过正点原子的单通道ADC采样的例程修改试过,会卡死在校验,我也不知道是为什么

不应该卡死才对,校准的那部分是没问题的
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-11 17:16:44 | 显示全部楼层
一战到底 发表于 2017-10-11 17:12
不应该卡死才对,校准的那部分是没问题的

void  Adc_Init(void)
{         
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC1        , ENABLE );          //使能ADC1通道时钟


        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        //PA1 作为模拟通道输入引脚                        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
        GPIO_Init(GPIOC, &GPIO_InitStructure);        

        ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在单次转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不是外部触发启动
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  
        ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1
        
        ADC_ResetCalibration(ADC1);        //使能复位校准  
         
        while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
        
        ADC_StartCalibration(ADC1);         //开启AD校准

        while(ADC_GetCalibrationStatus(ADC1));         //等待校准结束

        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能

}                                 
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{
          //设置指定ADC的规则组通道,一个序列,采样时间
        ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );        //ADC1,ADC通道,采样时间为239.5周期                                      
  
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能        
         
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

        return ADC_GetConversionValue(ADC1);        //返回最近一次ADC1规则组的转换结果
}

u16 Get_Adc_Average(u8 ch,u8 times)
{
        u32 temp_val=0;
        u8 t;
        for(t=0;t<times;t++)
        {
                temp_val+=Get_Adc(ch);
                delay_ms(5);
        }
        return temp_val/times;
}         

这个是正点原子的那个程序,我试过在这个基础上修改通道,虽然他的事ZET6我的是R8T6可是应该是可以用的,但是就是会卡死在校验的while中,我再main函数的adc初始化下面加一个led灯的输出,我把那个while改成延时之后那个灯才能够亮起来,说明是while卡死了

但是我用他的开发板程序是可以实现的
回复

使用道具 举报

0

主题

37

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
389
金钱
389
注册时间
2017-9-27
在线时间
133 小时
发表于 2017-10-12 11:39:29 | 显示全部楼层
d779708957ddd 发表于 2017-10-11 17:16
void  Adc_Init(void)
{         
        ADC_InitTypeDef ADC_InitStructure;

ADC+DMA的例程很多,而且你的配置,我看着没啥问题。是不是板子有问题?
回复

使用道具 举报

4

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1046
金钱
1046
注册时间
2017-5-19
在线时间
335 小时
发表于 2017-10-12 14:40:10 | 显示全部楼层
首先单用ADC能不能采到值,然后再考虑用DMA
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-12 17:45:54 | 显示全部楼层
wxjhby 发表于 2017-10-12 14:40
首先单用ADC能不能采到值,然后再考虑用DMA

最开始,我用正点原子的那个单用ADC程序改动,但是到我的板子上之后,程序会死在下面那个while,我也不知道为什么
ADC_ResetCalibration(ADC1);        //使能复位校准           
        while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束        
        ADC_StartCalibration(ADC1);         //开启AD校准
        while(ADC_GetCalibrationStatus(ADC1));         //等待校准结束
回复

使用道具 举报

4

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1046
金钱
1046
注册时间
2017-5-19
在线时间
335 小时
发表于 2017-10-13 09:00:13 | 显示全部楼层
看看工程里的芯片型号对不对吧,可能会有影响
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-13 14:31:08 | 显示全部楼层
wxjhby 发表于 2017-10-13 09:00
看看工程里的芯片型号对不对吧,可能会有影响

工程里面的芯片类型设置是正确的,而且板子其他部分的功能程序编写好了,调试成功了,现在就是ADC这块出不来,我用那个ADC采样的那个引脚做GPIO输入口调试了一下,是能够辨别高低电平的,说明那个引脚是没有问题的
回复

使用道具 举报

2

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2017-9-28
在线时间
19 小时
发表于 2017-10-13 15:11:42 | 显示全部楼层
volta =AD_Value/4095*3300; 你定义AD_Value[1],数组名为数组的首地址,你这不就是用一个地址作运算了?还有建议楼主使用Jlink的在线调试功能,在watch窗口下查看AD_Value的值是否有变化
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-10-16
在线时间
5 小时
发表于 2017-10-17 14:28:26 | 显示全部楼层
楼主的问题解决了吗?我用了一款f3的芯片,情况跟你类似,我照着官方的ADC例程修改的,也是卡死在adc校准的while循环里面出不来,用一个小小的延时代替这个while的话运行正常,但是读到的AD值是0,也就是说校验或者初始化没成功。
回复

使用道具 举报

4

主题

16

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-9-2
在线时间
11 小时
 楼主| 发表于 2017-10-20 15:46:42 | 显示全部楼层
HZL123456 发表于 2017-10-17 14:28
楼主的问题解决了吗?我用了一款f3的芯片,情况跟你类似,我照着官方的ADC例程修改的,也是卡死在adc校准的 ...

还没解决,可能是硬件上的问题,我今天看了一下寄存器的那个案例程序,这个程序的while那个注释就比较清楚了,写着是该位由软件设置,硬件清除,硬件不是很懂。所以我现在正打算去问下正点原子的淘宝店那边的技术支持
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
2
金钱
2
注册时间
2018-8-29
在线时间
0 小时
发表于 2018-8-29 09:24:42 | 显示全部楼层
请问楼主问题解决了吗?我的F103板子也卡在校验的while循环里面,不知道是什么原因
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-11 02:58

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表