GD32F470 ADC常规并行+过采样+DMA传输开发,使用梁山派开发板开发
特性
- 高性能:
– ADC采样分辨率: 采样分辨率: 采样分辨率: 12位、 10位、 8位、或者 位、或者 6位分辨率; 位分辨率; 位分辨率;
– ADC采样率: 采样率: 12位分辨率为 位分辨率为 位分辨率为 2.6 MSPs,10位分辨率为 位分辨率为 3.0 MSPs。分辨率越低,转 。分辨率越低,转 。分辨率越低,转 。分辨率越低,转 换越快;
– 自校准时间 自校准时间 :131个ADC时钟周期 时钟周期 ;
– 可编程采样时间; 可编程采样时间; 可编程采样时间;
– 数据 存储模式:最高有效位对齐和低; 存储模式:最高有效位对齐和低; 存储模式:最高有效位对齐和低; 存储模式:最高有效位对齐和低; 存储模式:最高有效位对齐和低; 存储模式:最高有效位对齐和低; 存储模式:最高有效位对齐和低; 存储模式:最高有效位对齐和低;
– DMA请求。 - 模拟输入通道:
– 16个外部模拟输入通道; 个外部模拟输入通道; 个外部模拟输入通道; 个外部模拟输入通道;
– 1个内部温度传感通道 个内部温度传感通道 个内部温度传感通道 (VSENSE);
– 1个内部参考电压输入通道 个内部参考电压输入通道 个内部参考电压输入通道 个内部参考电压输入通道 (VREFINT);
– 1个外部监测电池 个外部监测电池 个外部监测电池 VBAT供电引脚输入通道。 供电引脚输入通道。 供电引脚输入通道。 - 转换开始的发起:
– 软件触发; 软件触发;
– 硬件触发。 硬件触发。 - 运行模式:
– 转换单个通道,或者扫描一序列的; 转换单个通道,或者扫描一序列的; 转换单个通道,或者扫描一序列的; 转换单个通道,或者扫描一序列的; 转换单个通道,或者扫描一序列的; 转换单个通道,或者扫描一序列的;
– 单次 运行模式,每次触发转换一选择的输入通道; 模式,每次触发转换一选择的输入通道; 模式,每次触发转换一选择的输入通道; 模式,每次触发转换一选择的输入通道; 模式,每次触发转换一选择的输入通道; 模式,每次触发转换一选择的输入通道; 模式,每次触发转换一选择的输入通道;
– 连续 运行模式,连续转换所选择的输入通道; 模式,连续转换所选择的输入通道; 模式,连续转换所选择的输入通道; 模式,连续转换所选择的输入通道; 模式,连续转换所选择的输入通道; 模式,连续转换所选择的输入通道;
– 间断 运行模式;
– 同步模式(适用于具有两个 或多同步模式(适用于具有两个 或多同步模式(适用于具有两个 或多同步模式(适用于具有两个 或多同步模式(适用于具有两个 或多ADC的设备)。 的设备)。 的设备)。 的设备)。 - 转换结果阈值监测器功能:模拟看门狗。
- 中断产生:
– 常规 转换结束 转换结束 ;
– 模拟看门狗事件; 模拟看门狗事件; 模拟看门狗事件;
– 溢出事件。 溢出事件。 - 过采样:
– 16位的数据寄存器; 位的数据寄存器; 位的数据寄存器;
– 可调整的过采样率,从 可调整的过采样率,从 可调整的过采样率,从 2x到256x;
– 高达 8位的可编程数据移。 位的可编程数据移。 位的可编程数据移。 位的可编程数据移。 位的可编程数据移。 - 模块供电要求:2.6V到3.6V,一般电源电压为3.3V。
- 通道输入范围:VREFN ≤VIN ≤VREFP。
结构图
ADC时钟配置
配置为HCLK的10分频。系统频率设置为HCLK=200MHZ,则ADC_CLK=20MHZ。
使用扫描模式
使用不连续的扫描运行模式,框图如下:
数据模式
分辨率12位,数据左对齐。
片上硬件过采样
过采样到14bit,同时有一定滤波作用。过采样率N=64,,左移4位,即M=4.。此时采样的最大值为0x3FFC。
ADC同步模式
配置为常规并行模式,ADC0、ADC1并行,ADC2独立。
DMA模式使用ADC同步 DMA模式 1。传输宽度32bit。
驱动代码
/*
* Dasen - 2023/5/8
* adc.h
*/
#ifndef USER_INC_ADC_H_
#define USER_INC_ADC_H_
#include "gd32f4xx.h"
#include "M4systick.h"
#define I_GAIN ((3.3/0x3ffc)*10.0)
#define I_OFFSET ((3.3/2)*10.0)
#define V_GAIN ((3.3/0x3ffc)*11.0)
#define V_gain (3.3/0x3ffc)
extern uint32_t FOC_CURR_AB;
void ADC_gpioInit(void);
void ADC_init(void);
void ADC_DMA_init(void);
#endif
/*
* Dasen - 2023/5/8
* adc.c
*/
#include "adc.h"
void ADC_gpioInit(void)
{
RCU_AHB1EN |=(1<<0);//GPIOA时钟使能
gpio_mode_set(GPIOA,GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO_PIN_0|GPIO_PIN_1);
}
/*
* 扫描运行、常规并行模式
* ADC0: ADC-CH0(Ia)
* ADC1: ADC-CH1(Ib)
* 总转换时间=采样时间+12.5 个CK_ADC 周期。
*/
void ADC_init(void)
{
ADC_gpioInit();
ADC_DMA_init();
RCU_APB2EN |=(1<<8);//ADC0时钟使能
RCU_APB2EN |=(1<<9);//ADC1时钟使能
ADC_CTL1(ADC0) &=~(1<<0);//0:禁止ADC关闭电源;1:使能ADC
ADC_CTL1(ADC1) &=~(1<<0);//0:禁止ADC关闭电源;1:使能ADC
//ADC时钟配置
ADC_SYNCCTL=0;
ADC_SYNCCTL |=(6<<16);//ADCCK: 这些位配置所有ADC的时钟 ADC_CLK_MAX <= 40MHZ
//100:HCLK 5分频 ADC_CLK=HCLK/5=200MHZ/5=40MHZ
//101:HCLK 6分频
//110:HCLK 10分频 ADC_CLK=HCLK/10=200MHZ/10=20MHZ
/*************************** ADC0 SATRT****************************/
ADC_STAT(ADC0) =0;//状态寄存器清零
ADC_CTL0(ADC0) =0;//控制寄存器0清零
ADC_CTL0(ADC0) |=(0<<24);//ADC数据分辨率: 00: 12位;01: 10位;10: 8位;11: 6位
ADC_CTL0(ADC0) |=(0<<23);//0:常规序列看门狗禁止;1:常规序列看门狗使能
ADC_CTL0(ADC0) |=(0<<11);//常规序列间断模式:0:间断运行模式禁止;1:间断运行模式使能
ADC_CTL0(ADC0) |=(1<<8);//扫描模式:0:扫描运行模式禁止;1:扫描运行模式使能
ADC_CTL1(ADC0) =0;//控制寄存器1清零
ADC_CTL1(ADC0) |=(0<<28);//常规序列外部触发模式:
//00:常规序列外部触发失能
//01:常规序列外部触发上升沿使能
//01:常规序列外部触发下降沿使能
//11:常规序列外部触发双边沿使能
ADC_CTL1(ADC0) |=(13<<24);//常规序列外部触发选择:1101: 定时器7通道0 ; 1110: 定时器7 TRGO
ADC_CTL1(ADC0) |=(0<<11);//数据对齐:0:最低有效位对齐;1:最高有效位对齐
ADC_CTL1(ADC0) |=(1<<9);//DMA失能模式
//0:DMA机制在DMA控制器的传输结束信号之后失能。
//1:当DMA=1,在每个常规转换结束时DMA机制产生一个DMA请求。
ADC_CTL1(ADC0) |=(1<<8);//0:DMA请求禁止;1:DMA请求使能
ADC_CTL1(ADC0) |=(0<<1);//0:禁止连续运行模式;1:使能连续运行模式
ADC_SAMPT1(ADC0) =0;//采样时间寄存器清零
ADC_SAMPT1(ADC0) |=(3<<0);//规则转换通道0采样时间:4-84周期,3-56,2-28
ADC_RSQ0(ADC0) &=~(0X0F<<20);
ADC_RSQ0(ADC0) |=(0<<20);//常规序列长度:常规通道转换序列中的总的通道数目为RL[3:0]+1。
ADC_RSQ2(ADC0) =0;
ADC_RSQ2(ADC0) |=(0<<0);//规则转换通道0 ->ADC_CH0
// ADC_RDATA(ADC0);
ADC_OVSAMPCTL(ADC0)=0;
ADC_OVSAMPCTL(ADC0) |=(4<<5);//移位4位, 14bit-0x3ffc
ADC_OVSAMPCTL(ADC0) |=(5<<2);//过采样率:64x
ADC_OVSAMPCTL(ADC0) |=(1<<0);//过采样使能
ADC_SYNCCTL |=(2<<14);//ADC同步DMA模式选择
//00:ADC同步DMA失能:
//01:ADC同步DMA模式0
//10:ADC同步DMA模式1
//11:保留
ADC_SYNCCTL |=(1<<13); //ADC同步DMA使能模式
//0:当检测到来自DMA控制器的传输结束信号后,DMA机制失能
//1:当SYNCDMA不为00时,根据SYNCDMA位来产生DMA请求。
ADC_SYNCCTL |=(6<<0);//ADC同步模式
//00110:ADC0和ADC1工作在常规并行模式。ADC2 独立工作。
//10110:所有的ADC都工作在常规并行模式。
/*************************** ADC0 END****************************/
/*************************** ADC1 SATRT****************************/
ADC_STAT(ADC1) =0;//状态寄存器清零
ADC_CTL0(ADC1) =0;//控制寄存器0清零
ADC_CTL0(ADC1) |=(0<<24);//ADC数据分辨率: 00: 12位;01: 10位;10: 8位;11: 6位
ADC_CTL0(ADC1) |=(0<<23);//0:常规序列看门狗禁止;1:常规序列看门狗使能
ADC_CTL0(ADC1) |=(0<<11);//常规序列间断模式:0:间断运行模式禁止;1:间断运行模式使能
ADC_CTL0(ADC1) |=(1<<8);//扫描模式:0:扫描运行模式禁止;1:扫描运行模式使能
ADC_CTL1(ADC1) =0;//控制寄存器1清零
ADC_CTL1(ADC1) |=(0<<28);//常规序列外部触发模式:
//00:常规序列外部触发失能
//01:常规序列外部触发上升沿使能
//01:常规序列外部触发下降沿使能
//11:常规序列外部触发双边沿使能
ADC_CTL1(ADC1) |=(13<<24);//常规序列外部触发选择:1101: 定时器7通道0 ; 1110: 定时器7 TRGO
ADC_CTL1(ADC1) |=(0<<11);//数据对齐:0:最低有效位对齐;1:最高有效位对齐
ADC_CTL1(ADC1) |=(1<<9);//DMA失能模式
//0:DMA机制在DMA控制器的传输结束信号之后失能。
//1:当DMA=1,在每个常规转换结束时DMA机制产生一个DMA请求。
ADC_CTL1(ADC1) |=(1<<8);//0:DMA请求禁止;1:DMA请求使能
ADC_CTL1(ADC1) |=(0<<1);//0:禁止连续运行模式;1:使能连续运行模式
ADC_SAMPT1(ADC1) =0;//采样时间寄存器清零
ADC_SAMPT1(ADC1) |=(3<<0);//规则转换通道0采样时间:4-84周期,3-56,2-28
ADC_RSQ0(ADC1) &=~(0X0F<<20);
ADC_RSQ0(ADC1) |=(0<<20);//常规序列长度:常规通道转换序列中的总的通道数目为RL[3:0]+1。
ADC_RSQ2(ADC1) =0;
ADC_RSQ2(ADC1) |=(1<<0);//规则转换通道0 ->ADC_CH1
ADC_OVSAMPCTL(ADC1)=0;
ADC_OVSAMPCTL(ADC1) |=(4<<5);//移位4位, 14bit-0x3ffc
ADC_OVSAMPCTL(ADC1) |=(5<<2);//过采样率:64x
ADC_OVSAMPCTL(ADC1) |=(1<<0);//过采样使能
/*************************** ADC1 END****************************/
/*****************ADC开启及校准*******************/
//ADC0
//enable adc0
ADC_CTL1(ADC0) |=(1<<0);//0:禁止ADC关闭电源;1:使能ADC
DS_M4delay_us(500);
ADC_CTL1(ADC0) |=(1<<3);//校准复位:0:校准寄存器初始化结束.;1:校准寄存器初始化开始
ADC_CTL1(ADC0) |=(1<<2);//ADC校准:0:校准结束;1:校准开始
while((ADC_CTL1(ADC0)&(1<<2))!=0);//等待校准完成
//ADC1
//enable adc1
ADC_CTL1(ADC1) |=(1<<0);//0:禁止ADC关闭电源;1:使能ADC
DS_M4delay_us(500);
ADC_CTL1(ADC1) |=(1<<3);//校准复位:0:校准寄存器初始化结束.;1:校准寄存器初始化开始
ADC_CTL1(ADC1) |=(1<<2);//ADC校准:0:校准结束;1:校准开始
while((ADC_CTL1(ADC1)&(1<<2))!=0);//等待校准完成
DS_M4delay_us(500);
}
uint32_t FOC_CURR_AB;
void ADC_DMA_init(void)
{
RCU_AHB1EN |=(1<<22);//使能DMA1
DMA_INTC0(DMA1) |=0X3D;//清除DMA1 CH0中断标志位
DMA_CH0CTL(DMA1)=0;//(CHEN位为1时,其他位不能被配置,先清CHEN)。
DMA_CH0CTL(DMA1) |=(0<<25);//PERIEN[2:0]-外设使能, 000:使能外设0
DMA_CH0CTL(DMA1) |=(2<<16);//软件优先级:00:低;01:中;10:高;11:极高
DMA_CH0CTL(DMA1) |=(2<<13);//存储器的传输数据宽度:00:8-bit;01:16-bit;10:32-bit;11:保留
DMA_CH0CTL(DMA1) |=(2<<11);//外设的传输数据宽度:00:8-bit;01:16-bit;10:32-bit;11:保留
DMA_CH0CTL(DMA1) |=(1<<10);//存储器的地址生成算法:0:固定地址模式;1:增量地址模式
DMA_CH0CTL(DMA1) |=(0<<9);//外设的地址生成算法:0:固定地址模式;1:增量地址模式
DMA_CH0CTL(DMA1) |=(1<<8);//0:禁止循环模式;1:使能循环模式(DMA作为传输控制器时有效)
DMA_CH0CTL(DMA1) |=(0<<6);//传输方向:0:从外设读出并写入存储器;1:从存储器读出并写入外设
DMA_CH0CTL(DMA1) |=(0<<5);//TFCS:传输控制器选择
//0:DMA作为传输控制器
//1:外设作为传输控制器
DMA_CH0CTL(DMA1) |=(0<<18);//SBMEN:存储切换模式使能
//0:关闭存储切换模式
//1:打开存储切换模式
DMA_CH0CTL(DMA1) |=(0<<19);//MBS:存储器缓冲选择
//0:存储器0作为存储器传输区域
//1:存储器1作为存储器传输区域
DMA_CH0CTL(DMA1) |=(0<<2);//0:禁止通道错误中断
DMA_CH0CTL(DMA1) |=(0<<3);//0:禁止通道半传输完成中断
DMA_CH0CTL(DMA1) |=(0<<4);//0:禁止通道传输完成中断
DMA_CH0CNT(DMA1) =0;
DMA_CH0CNT(DMA1) |=(0X01<<0);//传输计数: 该寄存器表明还有多少数据等待被传输。一旦通道使能,该寄存器为只读的,并在每个DMA传输之后值减1。如果该寄存器的值为0,无论通道开启与否,都不会有数据传输。如果该通道工作在循环模式下,一旦通道的传输任务完成,该寄存器会被自动重装载为初始设置值。
DMA_CH0PADDR(DMA1) = (uint32_t)(&ADC_SYNCDATA);//外设基地址
DMA_CH0M0ADDR(DMA1) = (uint32_t)(&FOC_CURR_AB);//存储器基地址
DMA_CH0CTL(DMA1) |=(1<<0);//0:禁止该通道;1:使能该通道
}
调用步骤如下:
float ia,ib;
/*adc采样**********/
ADC_CTL1(ADC0)|=(1<<30);//SWRCST-常规序列软件启动转换
while((DMA_INTF0(DMA1)&(1<<5))==0);//等待转换完成
DMA_INTC0(DMA1) |=0X3D;//清除DMA1 CH0中断标志位
ia=(float)((FOC_CURR_AB&0x3fff)*I_GAIN - I_OFFSET);
ib=(float)((FOC_CURR_AB>>16)*I_GAIN - I_OFFSET);
/***********/
printf("i:%0.5f,%0.5f\n",ia,ib);