極海APM32E030是工業級基礎拓展型MCU,在APM32F030性能基礎上,實現了更高主頻、更低功耗、以及更先進的模擬與通信接口。同時配置豐富的片上資源,可滿足多行業的應用升級需求,特別是成本敏感型應用??蓮V泛應用于工業控制、智能家居、儀器儀表、可穿戴設備、醫療及手持設備、小家電、照明燈等領域。

下面我們來看看這顆小小的芯片ADC采樣如何使用。
極海APM32E030——ADC單通道,實現ADC的采樣與讀取
目標:使用APM32E030芯片實現阻塞式讀取ADC數值
程序中使用ADC1的通道2進行ADC的讀取,初始化程序如下
void AD_Init(void)
{
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
GPIO_Config_T GPIO_InitStructure;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_InitStructure.pin = GPIO_PIN_2;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_Config(GPIOA, &GPIO_InitStructure);
ADC_Reset();
ADC_Config_T ADC_InitStructure;
ADC_InitStructure.resolution = ADC_RESOLUTION_12B; //ADC數據分辨率
ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD; //ADC掃描序列方向
ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS; //連續掃描
ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT; //右對齊
ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE; //禁用外部觸發轉換模式
ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0; //ADC外部觸發轉換定時器1 TRG0
ADC_Config(&ADC_InitStructure);
ADC_ConfigChannel(ADC_CHANNEL_2, ADC_SAMPLE_TIME_239_5);
ADC_ReadCalibrationFactor(); //ADC 讀取校準系數
ADC_Enable();
ADC_StartConversion(); //開始轉換
}
uint16_t AD_getvalue(void)
{
while(ADC_ReadStatusFlag(ADC_FLAG_CC)==RESET); //轉換結束標志
return ADC_ReadConversionValue();
}
此方式的ADC數值讀取使用阻塞的方式,可能會阻塞主循環的其它函數,使用滑動電阻求連接ADC引腳,通過串口將采集的數據打印出來,查看是否正確
uint16_t ADvalue;
float v;
int main (void)
{
LED_init();
AD_Init();
Serial_Init(115200);
printf("APM32E030\r\n");
while(1)
{
ADvalue=AD_getvalue();
v=(float)ADvalue/4095*3.3;
printf("ADC:%f\n",v);
LED1_turn();
Delay_ms(1000);
rx_test(); //串口接收
}
}
ADC單通道+中斷,實現ADC采樣的與讀取
目標:使用APM32E030芯片實現中斷讀取ADC數值
程序中使用ADC1的通道2進行ADC的讀取,初始化程序如下
void AD_Init(void)
{
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
GPIO_Config_T GPIO_InitStructure;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_InitStructure.pin = GPIO_PIN_2;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_Config(GPIOA, &GPIO_InitStructure);
ADC_Reset();
ADC_Config_T ADC_InitStructure;
ADC_InitStructure.resolution = ADC_RESOLUTION_12B; //ADC數據分辨率
ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD; //ADC掃描序列方向
ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS; //連續掃描
ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT; //右對齊
ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE; //禁用外部觸發轉換模式
ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0; //ADC外部觸發轉換定時器1 TRG0
ADC_Config(&ADC_InitStructure);
ADC_ConfigChannel(ADC_CHANNEL_2, ADC_SAMPLE_TIME_239_5);
/* Enable Interrupt*/
ADC_EnableInterrupt(ADC_INT_CS);
NVIC_EnableIRQRequest(ADC1_IRQn, 2);
ADC_ReadCalibrationFactor(); //ADC 讀取校準系數
ADC_Enable();
/* Wait until ADC is ready */
while (!ADC_ReadStatusFlag(ADC_FLAG_ADRDY));
ADC_StartConversion(); //開始轉換
}
只有ADC采集結束才會進入中斷,將數據進行保存,此方式不阻塞主循環的其它函數,主循環通過串口將采集的數據進行打印,查看是否正確采集
uint16_t ADvalue;
float v;
int main (void)
{
LED_init();
Serial_Init(115200);
AD_Init();
printf("APM32E030\r\n");
while(1)
{
v=(float)ADvalue/4095*3.3;
printf("ADC:%f\n",v);
LED1_turn();
Delay_ms(1000);
rx_test(); //串口接收
}
}
void ADC1_IRQHandler(void)
{
if (ADC_ReadIntFlag(ADC_INT_FLAG_CS) == SET)
{
ADC_ClearIntFlag(ADC_INT_FLAG_CS);
ADvalue = ADC_ReadConversionValue();
}
}
ADC多通道+DMA,實現ADC采樣的與讀取
目標:使用APM32E030芯片實現DMA讀取ADC數值
程序中使用ADC1的通道0、1、2、3進行ADC的讀取,初始化程序如下
#define ADC_CH_SIZE 4
uint16_t adcData[ADC_CH_SIZE];
void DMA_Init(void)
{
DMA_Config_T dmaConfig;
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);
dmaConfig.peripheralAddress = ((uint32_t)ADC_BASE + 0x40);
dmaConfig.memoryAddress = (uint32_t)&adcData;
dmaConfig.direction = DMA_DIR_PERIPHERAL;
dmaConfig.bufferSize = ADC_CH_SIZE;
dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;
dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_HALFWORD;
dmaConfig.memoryDataSize = DMA_MEMORY_DATASIZE_HALFWORD;
dmaConfig.circular = DMA_CIRCULAR_ENABLE;
dmaConfig.memoryTomemory = DMA_M2M_DISABLE;
dmaConfig.priority = DMA_PRIORITY_LEVEL_HIGHT;
DMA_Config(DMA1_CHANNEL_1, &dmaConfig);
DMA_Enable(DMA1_CHANNEL_1);
}
void AD_Init(void)
{
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
GPIO_Config_T GPIO_InitStructure;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_InitStructure.pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_Config(GPIOA, &GPIO_InitStructure);
ADC_Reset();
ADC_Config_T ADC_InitStructure;
ADC_InitStructure.resolution = ADC_RESOLUTION_12B;
ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD;
ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS; //連續掃描
ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT; //右對齊
ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE;
ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0;
ADC_Config(&ADC_InitStructure);
ADC_ConfigChannel(ADC_CHANNEL_0, ADC_SAMPLE_TIME_239_5);
ADC_ConfigChannel(ADC_CHANNEL_1, ADC_SAMPLE_TIME_239_5);
ADC_ConfigChannel(ADC_CHANNEL_2, ADC_SAMPLE_TIME_239_5);
ADC_ConfigChannel(ADC_CHANNEL_3, ADC_SAMPLE_TIME_239_5);
DMA_Init();
ADC_ReadCalibrationFactor();
ADC_EnableDMA();
ADC_DMARequestMode(ADC_DMA_MODE_CIRCULAR);
ADC_Enable();
ADC_StartConversion();
}
uint16_t AD_getvalue(uint8_t index)
{
return adcData[index];
}
配置DMA進行ADC數據的搬運,我們只需要在必要的時候讀取buff中的數據即可得到ADC采集的數據,主循環中通過串口將采集的數據進行打印,查看數據是否正確
uint16_t ADvalue;
float v;
int main (void)
{
LED_init();
Serial_Init(115200);
AD_Init();
printf("APM32E030\r\n");
while(1)
{
ADvalue=AD_getvalue(0);
v=(float)ADvalue/4095*3.3;
printf("PA0ADC:%f\n",v);
ADvalue=AD_getvalue(1);
v=(float)ADvalue/4095*3.3;
printf("PA1ADC:%f\n",v);
ADvalue=AD_getvalue(2);
v=(float)ADvalue/4095*3.3;
printf("PA2ADC:%f\n",v);
ADvalue=AD_getvalue(3);
v=(float)ADvalue/4095*3.3;
printf("PA3ADC:%f\r\n",v);
LED1_turn();
Delay_ms(1000);
rx_test(); //串口接收
}
}
ADC單通道+參考電壓/溫度,實現ADC采樣的與讀取
程序中使用ADC1的通道16/17進行ADC的讀取參考電壓,初始化程序如下
#include "ad.h" // Device header
void AD_Init(void)
{
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
ADC_Reset();
// ADC_EnableTempSensor(); //溫度初始化
ADC_EnableVrefint(); //參考電壓初始化
ADC_Config_T ADC_InitStructure;
ADC_InitStructure.resolution = ADC_RESOLUTION_12B; //ADC數據分辨率
ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD; //ADC掃描序列方向
ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS; //連續掃描
ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT; //右對齊
ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE; //禁用外部觸發轉換模式
ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0; //ADC外部觸發轉換定時器1 TRG0
ADC_Config(&ADC_InitStructure);
// ADC_ConfigChannel(ADC_CHANNEL_16, ADC_SAMPLE_TIME_239_5);
ADC_ConfigChannel(ADC_CHANNEL_17, ADC_SAMPLE_TIME_239_5);
ADC_ReadCalibrationFactor(); //ADC 讀取校準系數
ADC_Enable();
ADC_StartConversion(); //開始轉換
}
void AD_getvalue(void)
{
uint32_t reference_adc_value = 0, tsen_adc_value = 0;
ADC_DisableTempSensor();
// ADC_ConfigChannel(ADC_CHANNEL_16, ADC_SAMPLE_TIME_239_5);
// ADC_StartConversion();
// while(ADC_ReadStatusFlag(ADC_FLAG_CC)==RESET); //轉換結束標志
// tsen_adc_value = ADC_ReadConversionValue();
// printf("tsen_adc_value: %d\n", tsen_adc_value);
ADC_StopConversion();
ADC_ConfigChannel(ADC_CHANNEL_17, ADC_SAMPLE_TIME_239_5);
ADC_StartConversion();
while(ADC_ReadStatusFlag(ADC_FLAG_CC)==RESET); //轉換結束標志
reference_adc_value = ADC_ReadConversionValue();
printf("reference_adc_value: %d\n", reference_adc_value);
}
但是讀取的結果與手冊寫的1.2v有出入,我讀到的是1.5V,不知道哪里出了問題,中斷與DMA的流程和之前的一樣,都可以進行讀取
ADC多通道+參考電壓/溫度,實現ADC采樣的與讀取
目標:使用APM32E030芯片實現DMA讀取ADC數值
程序中使用ADC1的通道進行ADC的讀取,初始化程序如下
#include "ad.h" // Device header
#define ADC_CH_SIZE 6
uint16_t adcData[ADC_CH_SIZE];
void DMA_Init(void)
{
DMA_Config_T dmaConfig;
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);
dmaConfig.peripheralAddress = ((uint32_t)ADC_BASE + 0x40);
dmaConfig.memoryAddress = (uint32_t)&adcData;
dmaConfig.direction = DMA_DIR_PERIPHERAL;
dmaConfig.bufferSize = ADC_CH_SIZE;
dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;
dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_HALFWORD;
dmaConfig.memoryDataSize = DMA_MEMORY_DATASIZE_HALFWORD;
dmaConfig.circular = DMA_CIRCULAR_ENABLE;
dmaConfig.memoryTomemory = DMA_M2M_DISABLE;
dmaConfig.priority = DMA_PRIORITY_LEVEL_HIGHT;
DMA_Config(DMA1_CHANNEL_1, &dmaConfig);
DMA_Enable(DMA1_CHANNEL_1);
}
void AD_Init(void)
{
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
GPIO_Config_T GPIO_InitStructure;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_InitStructure.pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_Config(GPIOA, &GPIO_InitStructure);
ADC_Reset();
ADC_EnableTempSensor();
ADC_EnableVrefint();
ADC_Config_T ADC_InitStructure;
ADC_InitStructure.resolution = ADC_RESOLUTION_12B;
ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD;
ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS; //連續掃描
ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT; //右對齊
ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE;
ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0;
ADC_Config(&ADC_InitStructure);
ADC_ConfigChannel(ADC_CHANNEL_0, ADC_SAMPLE_TIME_239_5);
ADC_ConfigChannel(ADC_CHANNEL_1, ADC_SAMPLE_TIME_239_5);
ADC_ConfigChannel(ADC_CHANNEL_2, ADC_SAMPLE_TIME_239_5);
ADC_ConfigChannel(ADC_CHANNEL_3, ADC_SAMPLE_TIME_239_5);
ADC_ConfigChannel(ADC_CHANNEL_16, ADC_SAMPLE_TIME_239_5);
ADC_ConfigChannel(ADC_CHANNEL_17, ADC_SAMPLE_TIME_239_5);
DMA_Init();
ADC_ReadCalibrationFactor();
ADC_EnableDMA();
ADC_DMARequestMode(ADC_DMA_MODE_CIRCULAR);
ADC_Enable();
ADC_StartConversion();
}
uint16_t AD_getvalue(uint8_t index)
{
return adcData[index];
}
將每個通道保存到buff中,進行讀取即可
uint16_t ADvalue;
float v;
int main (void)
{
LED_init();
Serial_Init(115200);
AD_Init();
printf("APM32E030\r\n");
while(1)
{
ADvalue=AD_getvalue(0);
v=(float)ADvalue/4095*3.3;
printf("PA0ADC:%f\n",v);
ADvalue=AD_getvalue(1);
v=(float)ADvalue/4095*3.3;
printf("PA1ADC:%f\n",v);
ADvalue=AD_getvalue(2);
v=(float)ADvalue/4095*3.3;
printf("PA2ADC:%f\n",v);
ADvalue=AD_getvalue(3);
v=(float)ADvalue/4095*3.3;
printf("PA3ADC:%f\r\n",v);
ADvalue=AD_getvalue(4);
printf("TempSensor:%d\r\n",ADvalue);
ADvalue=AD_getvalue(5);
printf("Vref:%d\r\n",ADvalue);
LED1_turn();
Delay_ms(1000);
rx_test(); //串口接收
}
}
以上關于極海APM32E030芯片ADC的使用介紹就這些,對于基準電壓的采集,后續再同步更新。如需了解極海APM32E030芯片相關資源,可聯系極海代理商-聯科芯微電子,聯系電話:15994707769,LEO WANG。
