野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 17224|回复: 6

ADC 8路测量 DMA

[复制链接]
发表于 2014-12-9 17:26:51 | 显示全部楼层 |阅读模式
谁能帮我看一下程序,如何测量8路 AD电压值,然后在野火mini板上的液晶屏上显示啊?我的设置如下,可是一路都测不了,全是0.
ADC和DMA配置:
#include "bsp_adc.h"
#define ADC1_DR_Address    ((u32)0x40012400+0x4c)

__IO uint16_t ADC_ConvertedValue;
//__IO u16 ADC_ConvertedValueLocal;

/**
  * @brief  ê1ÄüADC1oíDMA1μÄê±Öó£¬3õê¼»ˉPC.0
  * @param  ÎT
  * @retval ÎT
  */
static void ADC1_GPIO_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
       
        /* Enable DMA clock */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
       
        /* Enable ADC1 and GPIOC clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
       
        /* Configure PC.0  as analog input */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_Init(GPIOC, &GPIO_InitStructure);                                // PC0,êäèëê±2»óÃéèÖÃËùÂê
       
        /* Enable ADC1 and GPIOC clock */
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
       
        /* Configure PC.0  as analog input */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_Init(GPIOA, &GPIO_InitStructure);                                // PC0,êäèëê±2»óÃéèÖÃËùÂê
}

/**
  * @brief  ÅäÖÃADC1μÄ1¤×÷Ä£ê½ÎaMDAÄ£ê½
  * @param  ÎT
  * @retval ÎT
  */
static void ADC1_Mode_Config(void)  
{
        DMA_InitTypeDef DMA_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;
       
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
       
        /* DMA channel1 configuration */
        DMA_DeInit(DMA1_Channel1);    //½«DMAμÄí¨μàÖμéèÖÃÎaè±ê¡Öμ
       
        DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;                                 //ADCμØÖ·
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;        //Äú′æμØÖ·
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //íaéè×÷Îaêy¾Y′«êäμÄà′Ô′
        DMA_InitStructure.DMA_BufferSize = 400;//  £¨1£©êy¾Y»o′æμÄ′óD¡
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //íaéèμØÖ·1춨
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                  //(2) éèÖÃDMAμÄÄú′æμYÔöÄ£ê½
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;        //°ë×Ö
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                                                                //Ñ-»·′«êä
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);
       
        /* Enable DMA channel1 */
        DMA_Cmd(DMA1_Channel1, ENABLE);
       
        /* ADC1 configuration */       
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                        //¶àá¢ADCÄ£ê½
        ADC_InitStructure.ADC_ScanConvMode = ENABLE ;                                          //(3)  ¶àí¨μàê±é¨ÃèÄ£ê½
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                        //¿aÆôá¬Dø×a»»Ä£ê½£¬¼′2»í£μؽøDDADC×a»»
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //2»ê1óÃía2¿′¥·¢×a»»
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;         //2é¼ˉêy¾Yóò¶ÔÆë
        ADC_InitStructure.ADC_NbrOfChannel = 8;                                                                         // (4) òa×a»»μÄí¨μàêyÄ¿
        ADC_Init(ADC1, &ADC_InitStructure);
       
        /*ÅäÖÃADCê±Öó£¬ÎaPCLK2μÄ8·ÖÆ죬¼′9MHz*/
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);
        /*ÅäÖÃADC1μÄí¨μà11Îa55.        5¸ö2éÑùÖüÆú£¬DòáDÎa1 */
        ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_28Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_28Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 3, ADC_SampleTime_28Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 4, ADC_SampleTime_28Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_12 ,5, ADC_SampleTime_28Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 6, ADC_SampleTime_28Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 7, ADC_SampleTime_28Cycles5);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 8, ADC_SampleTime_28Cycles5);
       
        /* Enable ADC1 DMA */
        ADC_DMACmd(ADC1, ENABLE);
       
        /* Enable ADC1 */
        ADC_Cmd(ADC1, ENABLE);
       
        /*¸′λD£×¼¼Ä′æÆ÷ */   
        ADC_ResetCalibration(ADC1);
        /*μè′yD£×¼¼Ä′æÆ÷¸′λíê3é */
        while(ADC_GetResetCalibrationStatus(ADC1));
       
        /* ADCD£×¼ */
        ADC_StartCalibration(ADC1);
        /* μè′yD£×¼íê3é*/
        while(ADC_GetCalibrationStatus(ADC1));
       
        /* óéóúûóD2éóÃía2¿′¥·¢£¬ËùòÔê1óÃèí¼t′¥·¢ADC×a»» */
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

/**
  * @brief  ADC13õê¼»ˉ
  * @param  ÎT
  * @retval ÎT
  */
void ADC1_Init(void)
{
        ADC1_GPIO_Config();
        ADC1_Mode_Config();
}


主函数配置如下:
#include "stm32f10x.h"
#include "bsp_usart1.h"
#include "bsp_adc.h"
#include "bsp_ili9341_lcd.h"

#define N 50 //è¡50′Îƽ¾ùÖμ.Nò»Ö±μèóú50
#define M 8 //15·AD
u8 value[N][M];
u8 i=0,j=0;

//ADC1×a»»μÄμçÑ1Öμí¨1yMDA·½ê½′«μ½SRAM
extern __IO uint16_t ADC_ConvertedValue[M];

// ¾Ö2¿±äá¿£¬óÃóú±£′æ×a»»¼ÆËãoóμÄμçÑ1Öμ          
float ADC_ConvertedValueLocal[M];  

void filter(void)
{
        int sum = 0;  
        u8 count; //u8êÇunsigned char£¬u16êÇunsigned short£¬u32êÇunsigned int
        for(i=0;i<M;i++)
        {
                for(count=0;count<N;count++)
                {
                         sum+=value[count][i];  //a+=3μè&#188;&#219;óúa=a+3
    }
    ADC_ConvertedValue[i]=sum/N;
    sum=0;
  }
}

void Delay(__IO uint32_t nCount)
{
  for(; nCount != 0; nCount--);
}


/**
  * @brief  &#214;÷oˉêy
  * @param  &#206;T
  * @retval &#206;T
  */
int main(void)
{
        //uint32_t ge,dian;

  LCD_Init();       

        LCD_Clear(0, 0, 240, 320, BACKGROUND);       
       
        /* USART1 config */
        USART1_Config();
       
        /* enable adc1 and config adc1 to dma mode */
        ADC1_Init();
       
        //printf("\r\n ----????ADC??(DMA??)----\r\n");
        LCD_Clear(0, 0, 240, 320, BACKGROUND);   
        LCD_DispStr(10, 10, (uint8_t *)"AD1", YELLOW);
        LCD_DispStr(10, 30, (uint8_t *)"AD2", YELLOW);       
        LCD_DispStr(10, 50, (uint8_t *)"AD3 ", YELLOW);
        LCD_DispStr(10, 70, (uint8_t *)"AD4", RED);
        LCD_DispStr(10, 90, (uint8_t *)"AD5", RED);
        LCD_DispStr(10, 110, (uint8_t *)"AD6", RED);
        LCD_DispStr(10, 130, (uint8_t *)"AD7", RED);
        LCD_DispStr(10, 150, (uint8_t *)"AD8", RED);
       
        LCD_DispStr(50, 10, (uint8_t *)"0.000 V", RED);
        LCD_DispStr(50, 30, (uint8_t *)"0.000 V", RED);
        LCD_DispStr(50, 50, (uint8_t *)"0.000 V", RED);
        LCD_DispStr(50, 70, (uint8_t *)"0.000 V", RED);
        LCD_DispStr(50, 90, (uint8_t *)"0.000 V", RED);
        LCD_DispStr(50, 110, (uint8_t *)"0.000 V", RED);
        LCD_DispStr(50, 130, (uint8_t *)"0.000 V", RED);
        LCD_DispStr(50, 150, (uint8_t *)"0.000 V", RED);
       
        while (1)
        {
                //while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);  //·à&#214;1μúò&#187;&#184;&#246;×&#214;&#189;ú±&#187;&#182;aê§
                filter();
               
                for(i=0;i<M;i++)
                {
       ADC_ConvertedValue[M]=(float)ADC_ConvertedValueLocal[M]*(3.3/4096);   //&#182;áè&#161;×a&#187;&#187;μ&#196;AD&#214;μ
                         ADC_ConvertedValueLocal[i]=ADC_ConvertedValueLocal[i];
    }
          
                LCD_DisNum(150, 70, (uint32_t)ADC_ConvertedValueLocal[0], RED);       
                LCD_DisNum(150, 70, (uint32_t)ADC_ConvertedValueLocal[1], RED);
                LCD_DisNum(150, 70, (uint32_t)ADC_ConvertedValueLocal[2], RED);
                LCD_DisNum(150, 70, (uint32_t)ADC_ConvertedValueLocal[3], RED);
                LCD_DisNum(150, 70, (uint32_t)ADC_ConvertedValueLocal[4], RED);
                LCD_DisNum(150, 70, (uint32_t)ADC_ConvertedValueLocal[5], RED);
                LCD_DisNum(150, 70, (uint32_t)ADC_ConvertedValueLocal[6], RED);
                LCD_DisNum(150, 70, (uint32_t)ADC_ConvertedValueLocal[7], RED);
                LCD_DisNum(150, 70, (uint32_t)ADC_ConvertedValueLocal[8], RED);
               
                for(i=0;i<M;i++)
                {
       ADC_ConvertedValue[i]-=ADC_ConvertedValueLocal[i];
                         ADC_ConvertedValue[i]*=1000;
    }
                LCD_DisNum(150, 130, (uint32_t)ADC_ConvertedValue[0], RED);
                LCD_DisNum(150, 130, (uint32_t)ADC_ConvertedValue[1], RED);
                LCD_DisNum(150, 130, (uint32_t)ADC_ConvertedValue[2], RED);
                LCD_DisNum(150, 130, (uint32_t)ADC_ConvertedValue[3], RED);
                LCD_DisNum(150, 130, (uint32_t)ADC_ConvertedValue[4], RED);
                LCD_DisNum(150, 130, (uint32_t)ADC_ConvertedValue[5], RED);
                LCD_DisNum(150, 130, (uint32_t)ADC_ConvertedValue[6], RED);
                LCD_DisNum(150, 130, (uint32_t)ADC_ConvertedValue[7], RED);
                LCD_DisNum(150, 130, (uint32_t)ADC_ConvertedValue[8], RED);
                Delay(200);               
        }
       
}

回复

使用道具 举报

发表于 2014-12-18 21:38:44 | 显示全部楼层

我用的是STM32F103VET6
我建议你 每一路设置一个void ADC1_Init(void),   这样 不会搞混
比如  void ADC1_Iniit_1(void)
        void ADC1_Init_2(void)
   然后显示 就只需要提取数据就可以了
我搞了14路ADC 转换, 现在就是想看下精度怎么好调整,
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-19 16:25:52 | 显示全部楼层
侯希白 发表于 2014-12-18 21:38
我用的是STM32F103VET6
我建议你 每一路设置一个void ADC1_Init(void),   这样 不会搞混
比如  void  ...

好的,谢谢。你做的是项目吗?你做的14路AD,代码可以发给我参考一下吗?我用的也是是stm32f103vet6.如果不能,就算了吧。我用你说的方法试试。
回复 支持 反对

使用道具 举报

发表于 2014-12-19 17:55:43 | 显示全部楼层
代码  不在我这个电脑  
下次我上图片
回复 支持 反对

使用道具 举报

发表于 2015-4-12 19:18:22 | 显示全部楼层
侯希白 发表于 2014-12-18 21:38
我用的是STM32F103VET6
我建议你 每一路设置一个void ADC1_Init(void),   这样 不会搞混
比如  void  ...

我也在这方面卡住了,能不能求一下代码,谢谢了
回复 支持 反对

使用道具 举报

发表于 2015-4-18 16:06:01 | 显示全部楼层
楼主解决了的话给我说一下
回复 支持 反对

使用道具 举报

发表于 2015-4-19 11:16:23 | 显示全部楼层
话说我测得是四路,也出了问题i,大概是以下几个楼主可以参考下:
1. DMA传输时半字; 2.  外设到内存地址一个是disable,一个是enable ;   3. 多通道的话可以考虑下用数组,通过DMA把每个通道的数值传到对应数组。   
    希望有用~~~
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-9-23 11:20 , Processed in 0.040402 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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