打印
[STM32F1]

STM32做2路信号的ADC和DMA,发现采样值一直为0?

[复制链接]
2535|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yxw21yxw21|  楼主 | 2014-4-28 22:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序主要部分是这样的:


#include "stm32f10x.h"
#include <stdio.h>
#include "delay.h"
#include "ad.h"
#include "lcd.h"
#include <math.h>
float ad1,ad2;
u8 gototime = 0;
#define N 128 //每通道采128次
#define M 2 //为2个通道
u16 ADCDataTab[N][M] ;   //内存地址
#define ADC1_DR_Address    ((u32)0x4001244C)

************************************管脚、ADC 和 DMA 配置部分******************************************
        GPIO_InitTypeDef GPIO_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;
        DMA_InitTypeDef DMA_InitStructure;

    /* 使能 ADC1 and GPIOC clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);              //72M/6=12M最大时间不能超过14M

        /* 配置PA1为模拟输入 */
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 ;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

    DMA_DeInit(DMA1_Channel1);
    DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;//外设地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADCDataTab;//内存地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//dma传输方向单向
    DMA_InitStructure.DMA_BufferSize = N*M;//设置DMA在传输时缓冲区的大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//设置DMA的外设递增模式,一个外设
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//设置DMA的内存递增模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据字长
    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的2个memory中的变量互相访问
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);

        /* 配置ADC1, 不用DMA, 用软件自己触发 */
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                 //ADC1工作模式:独立模式
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;                         //多通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                 //连续转换
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;          //转换由软件触发启动
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;         //ADC1数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 2;           //顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC1, &ADC_InitStructure);                   //根据ADC_InitStruct中指定的参数,初始化外设ADC1的寄存器


        ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);        //ADC1,ADC通道1,规则采样顺序值为1,采样时间为239.5周期
        ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 2, ADC_SampleTime_239Cycles5);
       
    /* Enable ADC1 DMA [使能ADC1 DMA]*/
    ADC_DMACmd(ADC1, ENABLE);

        /* Enable ADC1 */
        ADC_Cmd(ADC1, ENABLE);                  //使能ADC1

        /* Enable ADC1 reset calibaration register */
        ADC_ResetCalibration(ADC1);                                                //重置ADC1的校准寄存器
        /* Check the end of ADC1 reset calibration register */
        while(ADC_GetResetCalibrationStatus(ADC1));                //获取ADC1重置校准寄存器的状态,设置状态则等待

        /* Start ADC1 calibaration */
        ADC_StartCalibration(ADC1);                                        //开始ADC1的校准状态
        /* Check the end of ADC1 calibration */
        while(ADC_GetCalibrationStatus(ADC1));                //等待校准完成

        /* Start ADC1 Software Conversion */
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能ADC1的软件转换启动功能

************************************主函数部分******************************************

int main(void)
{
  u16 i;

  RCC_Configuration();
  ADC_Configuration();            //配置PC0 为ADC1_IN10
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE);
  LCD_Init();
  LCD_Clear(0X01CF        );

   while(1)
  {                     
      ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //软件启动ADC转换
          DMA_Cmd(DMA1_Channel1, ENABLE);                    
      for(i = 0;i < 128;i++)                    
          {
            
                ad1+= ADCDataTab[0];
                ad2+= ADCDataTab[1];                      
          }
                 
      ad1 = ad1 / 128;
          ad2 = ad2 / 128;
          ad1=ad2*330/4096;
          ad1=ad2*330/4096;
          LCD_ShowBigNum4(100,120,ad2);
          LCD_ShowBigNum4(100,190,ad1);                  
      ad1=ad2=0;                                                         
  }

}
沙发
weiyuliang| | 2014-4-29 08:43 | 只看该作者
你把外部信号接在3.3V上测试一下。

使用特权

评论回复
板凳
jjjkkk00| | 2014-4-29 09:11 | 只看该作者
本帖最后由 jjjkkk00 于 2014-4-29 09:17 编辑

貌似DMA时钟没有使能。
贴出的代码中没看到:RCC_AHBPeriph_DMA1

使用特权

评论回复
地板
mmuuss586| | 2014-4-29 10:39 | 只看该作者
本帖最后由 mmuuss586 于 2014-4-29 10:40 编辑

DMA和ADC时钟好像未使能。
  
/* Enable peripheral clocks ------------------------------------------------*/
  /* Enable DMA1 clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  /* Enable ADC1 and GPIOC clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);

main.rar

2.05 KB

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
yxw21yxw21 + 1 很给力!
5
yxw21yxw21|  楼主 | 2014-4-30 11:07 | 只看该作者
mmuuss586 发表于 2014-4-29 10:39
DMA和ADC时钟好像未使能。
  
/* Enable peripheral clocks -------------------------------------------- ...

嗯,昨天自己已经发现这个问题并解决了。不过还是要谢谢

使用特权

评论回复
6
yxw21yxw21|  楼主 | 2014-4-30 11:13 | 只看该作者
本帖最后由 yxw21yxw21 于 2014-4-30 11:15 编辑
jjjkkk00 发表于 2014-4-29 09:11
貌似DMA时钟没有使能。
贴出的代码中没看到:RCC_AHBPeriph_DMA1

嗯,谢谢了。就是没有使能的原因。
还有一个问题啊,你帮我看看我的main.c。我的想法是ad1是PA1口的信号值,ad2是PA4口信号值,但实际显示结果恰好相反。

main.c.rar

3.52 KB

使用特权

评论回复
7
yxw21yxw21|  楼主 | 2014-4-30 11:17 | 只看该作者
mmuuss586 发表于 2014-4-29 10:39
DMA和ADC时钟好像未使能。
  
/* Enable peripheral clocks -------------------------------------------- ...

还有一个问题啊,你帮我看看我的main.c。我的想法是ad1是PA1口的信号值,ad2是PA4口信号值,但实际显示结果恰好相反。 main.c.rar (3.52 KB)


使用特权

评论回复
8
jjjkkk00| | 2014-4-30 13:29 | 只看该作者
yxw21yxw21 发表于 2014-4-30 11:17
还有一个问题啊,你帮我看看我的main.c。我的想法是ad1是PA1口的信号值,ad2是PA4口信号值,但实际显示结 ...

应该是“数据大小端”的问题。
直接仿真调试,看一下二维数组的地址分配就能找到原因了。

使用特权

评论回复
9
cdshkf| | 2014-5-8 14:58 | 只看该作者
如果楼猪定义内存地址为一维数组的话,一般不会出现ADC采集通道数据错位的问题,可能16位的二维数组被强制转换成32位后,地址分配和楼猪理解的正好相反。其实这个问题也没必要深究,楼猪想要把显示结果再反过来就把:
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 2, ADC_SampleTime_239Cycles5);
改成:
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
就OK了。
如果一定要寻根究底,就像楼上说的,仿真一下就知道了。

使用特权

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

本版积分规则

3

主题

8

帖子

0

粉丝