栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

AT32F403A/STM32F103 采用DMA方式多路ADC采集

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

AT32F403A/STM32F103 采用DMA方式多路ADC采集

AT32F403A/STM32F103 采用DMA方式多路ADC采集

` 提示:采用DMA方式进行ADC采样,用到端口PA0到PA3, PC0到PC3,共8路ADC同时进行采样,用定时器控制100ms刷新一次采样结果并通过串口打印出来,带软件滤波和电压转换,串口初始化这里就不作介绍了

–

文章目录
  • AT32F403A/STM32F103 采用DMA方式多路ADC采集
  • 前言
    • 1. 头文件 adc.h
    • 2. 源文件adc.c
    • 3. 软件滤波程序
    • 4. 主函数main.c


前言

stm32f103有多路12位ADC,外部参考电压一般使用3.3V, 理论上STM32F103是在CPU频率为56MHz时,ADC的最大采样转换频率达到1MHz。但是当CPU频率为72MHz时,ADC的最大采样转换频率变为854.7kHz,即1.17us,比1MHz慢。而AT32F403A主频可达240MHZ, 3组2M采样速率12位A/D转换器(21通道)
最小采样周期为1.5个周期+12.5周期=14周期。
最大采样频率为:12MHZ/14周期=851.142KHZ≈851KHZ
也就是1s可以采样851K个数据,这个采样率已经可以满足很多应用需要了。


其中PA0~PA3 分别对应ADC_CHANNEL_0到ADC_CHANNEL_3

其中PC0~PC3 分别对应ADC_CHANNEL_10到ADC_CHANNEL_13

1. 头文件 adc.h

代码使用的是 AT32F403A_407_Firmware_Library_V2.0.8版本库进行编写,也可以通过JLINK烧录到STM32F103上使用:

#ifndef __ADC_H
#define __ADC_H




#include "sys.h"



#define	FIRL_N	8
#define	AD_NUM   8



typedef enum
{
  AD_INPUT                   = 0x00, 
  DAT_INPUT                  = 0x01, 
} Sysctrl_Input_select_type;


extern __IO uint32_t dma1_trans_complete_flag;
extern __IO uint16_t vmor_flag_index;
extern __IO uint16_t 	ADValue[FIRL_N][AD_NUM];
void Get_ADValue(u16* value);
void App_MutiAdcCfg(void);
void PilotAnalogToBuf(uint8_t *rptr, uint8_t *wptr,uint16_t *buf,uint8_t cnt);


extern __IO double  fatualvot[AD_NUM];
#endif
2. 源文件adc.c

程序配置了PA0到PA3, PC0到PC3 八路ADC进行采集,采用DMA方式进行存储,ADValue[FIRL_N][AD_NUM] 用来存放ADC转换结果,也是DMA的目标地址,每完成一次转换,DMA将数据依次存放到数组

#include "adc.h"
#include "at32f403a_407_board.h"

__IO uint16_t 	ADValue[FIRL_N][AD_NUM];
__IO uint16_t		ADValFilter[AD_NUM];
__IO uint32_t dma1_trans_complete_flag = 0;

static void adc_gpio_config(void);
static void dma_config(void);
static void adc_config(void);


static void adc_gpio_config(void)
{
  gpio_init_type gpio_initstructure;
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);

  gpio_default_para_init(&gpio_initstructure);
  gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
  gpio_initstructure.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_2 | GPIO_PINS_3;
  gpio_init(GPIOA, &gpio_initstructure);

   gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
  gpio_initstructure.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_2 | GPIO_PINS_3;
  gpio_init(GPIOC, &gpio_initstructure);
}


static void dma_config(void)
{
  dma_init_type dma_init_struct;
  crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
//  nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
  dma_reset(DMA1_CHANNEL1);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.buffer_size = FIRL_N*AD_NUM;
  dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  dma_init_struct.memory_base_addr = (uint32_t)ADValue;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_HIGH;
  dma_init_struct.loop_mode_enable = TRUE;
  dma_init(DMA1_CHANNEL1, &dma_init_struct);

//  dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
  dma_channel_enable(DMA1_CHANNEL1, TRUE);
}


static void adc_config(void)
{
  adc_base_config_type adc_base_struct;
  crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
  crm_adc_clock_div_set(CRM_ADC_DIV_6);

  
  adc_combine_mode_select(ADC_INDEPENDENT_MODE);
  adc_base_default_para_init(&adc_base_struct);
  adc_base_struct.sequence_mode = TRUE;
  adc_base_struct.repeat_mode = TRUE;
  adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
  adc_base_struct.ordinary_channel_length = AD_NUM;
  adc_base_config(ADC1, &adc_base_struct);
  adc_ordinary_channel_set(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_239_5);
  adc_ordinary_channel_set(ADC1, ADC_CHANNEL_1, 2, ADC_SAMPLETIME_239_5);
  adc_ordinary_channel_set(ADC1, ADC_CHANNEL_2, 3, ADC_SAMPLETIME_239_5);
  adc_ordinary_channel_set(ADC1, ADC_CHANNEL_3, 4, ADC_SAMPLETIME_239_5);
    
  adc_ordinary_channel_set(ADC1, ADC_CHANNEL_10, 5, ADC_SAMPLETIME_239_5);
  adc_ordinary_channel_set(ADC1, ADC_CHANNEL_11, 6, ADC_SAMPLETIME_239_5);
  adc_ordinary_channel_set(ADC1, ADC_CHANNEL_12, 7, ADC_SAMPLETIME_239_5);
  adc_ordinary_channel_set(ADC1, ADC_CHANNEL_13, 8, ADC_SAMPLETIME_239_5);
  adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
  adc_dma_mode_enable(ADC1, TRUE);

  adc_enable(ADC1, TRUE);
  adc_calibration_init(ADC1);
  while(adc_calibration_init_status_get(ADC1));
  adc_calibration_start(ADC1);
  while(adc_calibration_status_get(ADC1));
}

void App_MutiAdcCfg(void)
{
    adc_gpio_config();
    dma_config();
    adc_config();
   
}

3. 软件滤波程序
void Get_ADValue(u16* value)
{
	u8 i,chnl;
    
    for (i=0;i
		ADValFilter[i]=0;
	}	
	
    for(chnl=0; chnl
        for(i=0;i
            ADValFilter[chnl]+=ADValue[i][chnl];
        }
        ADValFilter[chnl]>>=3;
        if(ADValFilter[chnl]<9)ADValFilter[chnl] = 9;
        ADValFilter[chnl] -= 9;
        *value++ = ADValFilter[chnl];
    }    
}
4. 主函数main.c
void TMR1_OVF_TMR10_IRQHandler(void)
{
  if(tmr_flag_get(TMR1, TMR_OVF_FLAG) != RESET)
  {
        
        timer100ms_updateflag = 1;
        tmr_flag_clear(TMR1, TMR_OVF_FLAG);
   }
}

crm_clocks_freq_type crm_clocks_freq_struct = {0};
void TIM1_TimeBaseInit(void)
{
    
    crm_clocks_freq_get(&crm_clocks_freq_struct);
     
    crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);

    
    
    tmr_base_init(TMR1, 999, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
    tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);

    
    tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);

    
    nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 1, 0);

    
    tmr_counter_enable(TMR1, TRUE);
//    clkout_config();
}


__IO double  fatualvot[AD_NUM];  
int  main(void)
{
    u32 chnl;
	u16 ADvolt[AD_NUM];
    system_clock_config();
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);   
    TIM1_TimeBaseInit();   
	App_MutiAdcCfg();
    adc_ordinary_software_trigger_enable(ADC1, TRUE);
    
    while(1)
    {
    	if (timer100ms_updateflag) 
        {
            timer100ms_updateflag = 0;
     		Get_ADValue(ADvolt);
	        for (chnl=0; chnl
	            fatualvot[chnl] = AD_SCALE * ADvolt[chnl];
	            printf("vtmp[%d]=%drn", chnl,(u16)fatualvot[chnl]);
	        }
        }
	}
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/932364.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号