功能目标
每隔 10 秒 采集一次电池电压(单通道)
使用 Timer 触发 ADC
通过 DMA 自动搬运数据到内存
连续记录(不做 Flash 写入,主存储在 RAM)
示例代码框架(基于 MM32F103)
1. 全局定义
c
复制
编辑
#define SAMPLE_COUNT 720 // 2小时,每10秒一次
uint16_t adc_buffer[SAMPLE_COUNT];
volatile uint16_t sample_index = 0;
2. 配置定时器(TIM2)每10秒触发一次
c
复制
编辑
void TIM2_Init_10s(void) {
RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM2EN, ENABLE);
TIM_TimeBaseInitTypeDef TIM_Init;
TIM_Init.TIM_Prescaler = 7200 - 1; // 72MHz / 7200 = 10kHz
TIM_Init.TIM_Period = 100000 - 1; // 10kHz / 100000 = 0.1Hz = 10s
TIM_Init.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_Init);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // TRGO on update
TIM_Cmd(TIM2, ENABLE);
}
3. 配置 ADC + DMA
c
复制
编辑
void ADC_DMA_Init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_IOPAEN, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1EN, ENABLE);
// ADC引脚配置(如 PA1)
GPIO_InitTypeDef GPIO_InitStructure = {
.GPIO_Pin = GPIO_Pin_1,
.GPIO_Mode = GPIO_Mode_AIN
};
GPIO_Init(GPIOA, &GPIO_InitStructure);
// DMA 配置
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&adc_buffer[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = SAMPLE_COUNT;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
// ADC配置
ADC_InitTypeDef ADC_InitStructure = {
.ADC_Mode = ADC_Mode_Independent,
.ADC_ScanConvMode = DISABLE,
.ADC_ContinuousConvMode = DISABLE,
.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO,
.ADC_DataAlign = ADC_DataAlign_Right,
.ADC_NbrOfChannel = 1
};
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
// ADC校准
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
}
4. 主函数初始化
c
复制
编辑
int main(void) {
TIM2_Init_10s();
ADC_DMA_Init();
while (1) {
// 可以定期检查 sample_index 或使用 DMA 完成中断
}
}
可拓展方向
使用 DMA 完成中断更新 sample_index,记录采样点
加入 Flash 写入逻辑实现断电保存
添加中值/滑动平均滤波,提高稳定性
多通道采样(扫描模式)
|