基于STM32与influxDB的电力监控系统-1
前言:
本系列教程基于正点原子的STM32F103 开发指南中的例程进行魔改得到。本节主要记录魔改多通道 ADC 采集(DMA 读取)实验过程。
基于STM32与influxDB的电力监控系统,能够实时采集电流和电压传感器的模拟信号,通过ADC转换和RMS计算得到精确的负载电流和电压值,并在LCD屏幕上以数据页面和实时波形两种方式可视化显示;系统还集成了WiFi模块将原始数据上传至influxDB,支持SD卡本地存储带时间戳的测量数据,并通过RTC模块提供准确的时间基准,实现了电力参数的采集、显示、远程传输和本地记录一体化功能。
一、目标:
本文主要修改多通道ADC采集的部分,将6个通道改为2个通道。
二、步骤:
step1 修改main.c文件
将ADC_DMA_BUF_SIZE定义为50*2。
在LCD显示部分,只显示2个通道的信息。
在循环中,只遍历2个通道。
step2 修改adc.c文件中的adc_nch_dma_init函数
只初始化2个通道(例如通道0和通道1)。
将ADC初始化结构体中的NbrOfConversion设置为2。
只配置两个通道的GPIO(PA0和PA1)。
在配置ADC通道时,只配置两个通道,分别设置Rank为1和2。
三、具体代码修改
3.1 main.c
#define ADC_DMA_BUF_SIZE 50 * 2 /* 修改为2个通道,原来是6个通道 */int main(void)
{// ... 其他代码保持不变 .../* 只显示2个通道的信息 */lcd_show_string(30, 110, 200, 12, 12, "ADC1_CH0_VAL:", BLUE);lcd_show_string(30, 122, 200, 12, 12, "ADC1_CH0_VOL:0.000V", BLUE);lcd_show_string(30, 140, 200, 12, 12, "ADC1_CH1_VAL:", BLUE);lcd_show_string(30, 152, 200, 12, 12, "ADC1_CH1_VOL:0.000V", BLUE);// 删除其他4个通道的显示代码adc_dma_enable(ADC_DMA_BUF_SIZE);while (1){if (g_adc_dma_sta == 1){/* 循环显示通道0~通道1的结果 */for(j = 0; j < 2; j++) /* 修改为2个通道 */{sum = 0;for (i = 0; i < ADC_DMA_BUF_SIZE / 2; i++) /* 修改为除以2 */{sum += g_adc_dma_buf[(2 * i) + j]; /* 修改为2个通道 */}adcx = sum / (ADC_DMA_BUF_SIZE / 2); /* 修改为除以2 *//* 显示结果 */lcd_show_xnum(108, 110 + (j * 30), adcx, 4, 12, 0, BLUE);temp = (float)adcx * (3.3 / 4096);adcx = temp;lcd_show_xnum(108, 122 + (j * 30), adcx, 1, 12, 0, BLUE);temp -= adcx;temp *= 1000;lcd_show_xnum(120, 122 + (j * 30), temp, 3, 12, 0X80, BLUE);}g_adc_dma_sta = 0;adc_dma_enable(ADC_DMA_BUF_SIZE);}LED0_TOGGLE();delay_ms(100);}
}
3.2 修改adc.c文件中的adc_nch_dma_init函数
void adc_nch_dma_init(uint32_t mar)
{GPIO_InitTypeDef gpio_init_struct;RCC_PeriphCLKInitTypeDef adc_clk_init = {0};ADC_ChannelConfTypeDef adc_ch_conf = {0};ADC_ADCX_CHY_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();if ((uint32_t)ADC_ADCX_DMACx > (uint32_t)DMA1_Channel7){__HAL_RCC_DMA2_CLK_ENABLE();}else{__HAL_RCC_DMA1_CLK_ENABLE();}/* 设置ADC时钟 */adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);/* 只设置2个通道的GPIO */gpio_init_struct.Pin = GPIO_PIN_0 | GPIO_PIN_1; /* 只使用PA0和PA1 */gpio_init_struct.Mode = GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOA, &gpio_init_struct);/* 初始化DMA */g_dma_nch_adc_handle.Instance = ADC_ADCX_DMACx;g_dma_nch_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;g_dma_nch_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;g_dma_nch_adc_handle.Init.MemInc = DMA_MINC_ENABLE;g_dma_nch_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;g_dma_nch_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;g_dma_nch_adc_handle.Init.Mode = DMA_NORMAL;g_dma_nch_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;HAL_DMA_Init(&g_dma_nch_adc_handle);__HAL_LINKDMA(&g_adc_nch_dma_handle, DMA_Handle, g_dma_nch_adc_handle);/* 初始化ADC */g_adc_nch_dma_handle.Instance = ADC_ADCX;g_adc_nch_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;g_adc_nch_dma_handle.Init.ScanConvMode = ADC_SCAN_ENABLE;g_adc_nch_dma_handle.Init.ContinuousConvMode = ENABLE;g_adc_nch_dma_handle.Init.NbrOfConversion = 2; /* 修改为2个通道 */g_adc_nch_dma_handle.Init.DiscontinuousConvMode = DISABLE;g_adc_nch_dma_handle.Init.NbrOfDiscConversion = 0;g_adc_nch_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;HAL_ADC_Init(&g_adc_nch_dma_handle);HAL_ADCEx_Calibration_Start(&g_adc_nch_dma_handle);/* 只配置2个通道 */adc_ch_conf.Channel = ADC_CHANNEL_0;adc_ch_conf.Rank = ADC_REGULAR_RANK_1;adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);adc_ch_conf.Channel = ADC_CHANNEL_1;adc_ch_conf.Rank = ADC_REGULAR_RANK_2;HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);/* 删除其他4个通道的配置 *//* 配置DMA数据流请求中断优先级 */HAL_NVIC_SetPriority(ADC_ADCX_DMACx_IRQn, 3, 3);HAL_NVIC_EnableIRQ(ADC_ADCX_DMACx_IRQn);HAL_DMA_Start_IT(&g_dma_nch_adc_handle, (uint32_t)&ADC1->DR, mar, 0);HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, &mar, 0);
}