打印
[MM32硬件]

以 MM32F103C8T6 为例每隔 10 秒 采集一次电池电压

[复制链接]
533|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
丢丢手绢666|  楼主 | 2025-4-30 09:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
功能目标
每隔 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 写入逻辑实现断电保存

添加中值/滑动平均滤波,提高稳定性

多通道采样(扫描模式)


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

474

帖子

0

粉丝