GD32+ADC+DMA定时采集+acs712霍尔电流传感器

GD32+ADC+DMA定时采集+acs712霍尔电流传感器

目的:本文使用定时器定时触发adc采样,并且通过dma搬运数据。

环境:KEIL

GD32F107vct6+ADC01_IN5(PA5)+TIMER3 CH3

时钟初始化

  rcu_periph_clock_enable(RCU_ADC0);
  rcu_periph_clock_enable(RCU_DMA0);
  rcu_periph_clock_enable(RCU_TIMER3);
  rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);

通过GD32F450+TIM定时器(1)可知,芯片使用外部晶振,时钟频率是108MHz。
在这里插入图片描述
在这里插入图片描述
APB2的频率= 108Mhz。

rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8) 初始化adc的时钟频率为13Mhz。

io初始化

 rcu_periph_clock_enable(RCU_GPIOA);
 rcu_periph_clock_enable(RCU_AF);//打开复用时钟
 gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ, GPIO_PIN_5);  

定时器初始化

  timer_parameter_struct initpara;
  timer_oc_parameter_struct ocpara;
  
  timer_deinit(TIMER3);
  initpara.alignedmode = TIMER_COUNTER_EDGE;
  initpara.clockdivision = TIMER_CKDIV_DIV1;
  initpara.counterdirection = TIMER_COUNTER_UP;
  initpara.period = SAMPLE_TIME;
  initpara.prescaler = 107;
  initpara.repetitioncounter = 0;
  timer_init(TIMER3,&initpara);
  
  ocpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
  ocpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
  ocpara.ocnpolarity = TIMER_OCN_POLARITY_LOW;
  ocpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
  ocpara.outputnstate = TIMER_CCXN_DISABLE;
  ocpara.outputstate = TIMER_CCX_ENABLE;//通道使能
  timer_channel_output_config(TIMER3,TIMER_CH_3,&ocpara);
  timer_channel_output_mode_config(TIMER3,TIMER_CH_3,TIMER_OC_MODE_PWM0);//pwm模式
  timer_channel_output_pulse_value_config(TIMER3,TIMER_CH_3,50);
  timer_auto_reload_shadow_enable(TIMER3);

SAMPLE_TIME:ADC采集数据间隔

ADC初始化

  adc_deinit(ADC0);
  adc_mode_config(ADC_MODE_FREE);//ADC独立工作
  adc_special_function_config(ADC0,ADC_CONTINUOUS_MODE,DISABLE);//不连续转换  
  adc_special_function_config(ADC0,ADC_SCAN_MODE,DISABLE);//不扫描 
  adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);//右对齐
  adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,1);//1个通道转换  
  adc_regular_channel_config(ADC0,0,ADC_CHANNEL_5,ADC_SAMPLETIME_13POINT5);//第0个序列,采样时间
  adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,ENABLE);//规则组外部触发使能
  adc_external_trigger_source_config(ADC0,ADC_REGULAR_CHANNEL,ADC0_1_EXTTRIG_REGULAR_T3_CH3);
  adc_enable(ADC0);
  DelayMicroSeconds(1);
  adc_calibration_enable(ADC0);//复位并校准
  adc_dma_mode_enable(ADC0);
  adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);//规则组转换开始 

因为是用定时器定时触发采样,所以采用不连续模式。只有一个ADC通道,所以不扫描。

注意:adc_enable(ADC0)和adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL)的顺序不能颠倒。
在这里插入图片描述
在这里插入图片描述
从手册里可知,adc_enable()只是唤醒ADC,并不是开启转换。adc_software_trigger_enable()是开启规则组转换。

ADC_SAMPLETIME_13POINT5:采样时间

总转换时间=采样时间+12.5 个 ADCCLK 周期 = 26个ADCCLK周期= 26/13000000s = 2us。

定时器采集间隔一定要大于转换时间。

DMA初始化

  uint16_t rev_data[PER_NUM] = {0};
  dma_deinit(DMA0,DMA_CH0);
  init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;//外设到寄存器
  init_struct.memory_addr = (uint32_t)(&rev_data);//存储器地址 
  init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//地址自增
  init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;//16位
  init_struct.number = PER_NUM;//1个通道 PER_NUM个数据
  init_struct.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));//外设地址
  init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//外设不增
  init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;//16位  取决于存储数据的类型
  init_struct.priority = DMA_PRIORITY_HIGH;//优先级
  dma_init(DMA0,DMA_CH0,&init_struct);
  dma_circulation_enable(DMA0,DMA_CH0);//循环模式
  nvic_irq_enable(DMA0_Channel0_IRQn, 1, 1);
  dma_interrupt_enable(DMA0,DMA_CH0,DMA_INT_FTF);//全部数据转换完成中断
  dma_channel_enable(DMA0,DMA_CH0);
  timer_enable(TIMER3);//放到底下

在这里插入图片描述
PER_NUM :每次采集数据数目。

通过手册可知ADC0对应DMA0_CH0。

数据处理

通过DMA中断可以知道是否转换完成。所用器件是acs712霍尔电流传感器。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
公式为:Vout (V)= 0.5Vcc+IP*0.1。通过ADC采集电压就能知道电流了。

总结:

以上仅为个人理解,如果有误,请大家多多指正,谢谢!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值