最近在使用stm32l151开发一个项目,我的项目需求是ADC采集电池电量,通过DMA通道传送出来。然而我并不是得到了电池电量数据后就立马连续输出,而是通过tim4定时器每1s访问一次采样得到的电池数据,并显示出来。本来网上关于stm32通过adc通道采集电池电量的代码很多,但要找到和我的需求一样的,还真没有。于是在借鉴其他人代码的基础上,根据我的特殊需求,写了一份这样功能的代码。

  因为我的需求涉及到了tim4定时器,adc和dma,所以在最终配置的时候也分为几个部分:
  1.首先是定时器tim4。
   a)初始化

void vTim4_Init(void)
{TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);/* Time base configuration */TIM_TimeBaseStructure.TIM_Period = TIMER4_PERIOD_TIMING;TIM_TimeBaseStructure.TIM_Prescaler = u32Tim4PrescalerValue;TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); /* TIM IT enable */TIM_ITConfig(TIM4, TIM_IT_Update |TIM_IT_Trigger, ENABLE); /* TIM14 disable */TIM_Cmd(TIM4, DISABLE);
}

   b)NVIC中断设置

/* Enable the TIMER4 Interrupt */NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 10;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;            NVIC_Init(&NVIC_InitStructure);
}

   c)Tim4中断函数书写,我这里是通过给任务一个信号量longtimerTaskSemaphoreHandler,唤醒获取电量的任务来获取电量数据并显示。

void vTimer4_Interrupt(void)
{BaseType_t xHigherPriorityTaskWoken;if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET){xSemaphoreGiveFromISR(longtimerTaskSemaphoreHandler,&xHigherPriorityTaskWoken);if(xHigherPriorityTaskWoken == pdTRUE)portYIELD_FROM_ISR(xHigherPriorityTaskWoken);TIM_ClearITPendingBit(TIM4, TIM_IT_Update);}
}

  2.其次是adc。
   a)adc的GPIO口初始化

void ADC_GPIO_INIT()
{GPIO_InitTypeDef GPIO_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  //打开对应GPIO的时钟GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOA, &GPIO_InitStructure);
}

   b)adc通道的初始化设置

void ADC_INIT()
{ADC_InitTypeDef ADC_InitStructure;RCC_HSICmd(ENABLE);                    //开启HSI时钟,非常重要,stm32l151的时钟由HSI提供while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);          RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);             //使能ADC1时钟ADC_InitStructure.ADC_ScanConvMode             = DISABLE;        //关闭扫描模式,因为多ADC通道同时使用时才打开ADC_InitStructure.ADC_ContinuousConvMode       = ENABLE;        //连续转换模式,因为我需要连续取十次数据ADC_InitStructure.ADC_ExternalTrigConvEdge     = ADC_ExternalTrigConvEdge_None;        //不适用外部触发转换ADC_InitStructure.ADC_DataAlign                = ADC_DataAlign_Right;                 //采集数据右对齐ADC_InitStructure.ADC_Resolution               = ADC_Resolution_12b;       //分辨率是12位ADC_InitStructure.ADC_NbrOfConversion          = 1;                  //要转换的通道数目1ADC_Init(ADC1, &ADC_InitStructure);ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_48Cycles);     //设置adc1的通道0的转换周期为48个采样周期ADC_DMACmd(ADC1, ENABLE);                                                 //启动DMA搬运ADC数值ADC_Cmd(ADC1, ENABLE);                                                    //打开ADCwhile(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);    //等待ADC1转换完成,必须返回值是SET  ADC_SoftwareStartConv(ADC1);                            //打开软件触发}

  3.dma的设置。
   a)dma初始化设置

void DMA_CONFIG()
{DMA_InitTypeDef DMA_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                       //开启DMA时钟DMA_DeInit(DMA1_Channel1);                                             //DMA复位DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));             //ADC地址DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)&ADC_ConvertedValue;     //存储地址DMA_InitStructure.DMA_DIR                        = DMA_DIR_PeripheralSRC;     //DMA传输方向为设备到内存DMA_InitStructure.DMA_BufferSize               = 10;                   //存储大小,所以前面的ADC我设置的是连续转换DMA_InitStructure.DMA_PeripheralInc          = DMA_PeripheralInc_Disable;                //外存地址固定                 DMA_InitStructure.DMA_MemoryInc            = DMA_MemoryInc_Enable;                 //内存地址递增,这样从ADC转换过来的数据才能依次传到目标地址上,否则的话就是固定写在一个地址上,并且前面的数据把后面的覆盖了                                                                             DMA_InitStructure.DMA_PeripheralDataSize  = DMA_PeripheralDataSize_HalfWord;     //每次发送是半字,即16位DMA_InitStructure.DMA_MemoryDataSize    = DMA_MemoryDataSize_HalfWord;           //每次存储数据单位为半字,即16位DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;                     //循环ADDMA_InitStructure.DMA_Priority                  = DMA_Priority_High;      //DMA优先级高DMA_InitStructure.DMA_M2M                      = DMA_M2M_Disable;         //DMA禁止内存到内存DMA_Init(DMA1_Channel1, &DMA_InitStructure);                              //DMA初始化DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);                           //使能DMA发送完中断DMA_ClearITPendingBit(DMA1_IT_TC1);                                       //清除中断位DMA_Cmd(DMA1_Channel1, ENABLE);                                           //启动DMA通道1
}

   b)dma的中断设置

void DMA_CONFIG()
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}

   c)dma中断函数书写。

void DMA1_Channel1_IRQHandler(void)
{  u32 i;u32 After_Buff=0;if (DMA_GetITStatus(DMA_IT_TC) != RESET){DMA_ClearITPendingBit(DMA1_IT_TC1);        //清除DMA中断标志位            ADC_DMACmd(ADC1, DISABLE);                //停止DMA搬运ADC数值ADC_Cmd(ADC1,DISABLE);                    //停止ADC转换,我是通过Tim4定时器产生的中断来开关DMA和ADC。for(i = 0;i < buff_size;i++){After_Buff = After_Buff+ADC_ConvertedValue[i];} After_Filter=After_Buff/10;   //强制转换后电量显示正常After_Buff=0;}}

   最后回到mian()函数部分了,通过Tim4定时触发读取电池电量的任务,读取并显示。

void AdcTransfer(void)
{u32 powervalue;ADC_DMACmd(ADC1, ENABLE);                 //开启DMA搬运数据ADC_Cmd(ADC1, ENABLE);                    //开启ADC转换 while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET) {};     //如果ADC允许使用ADC_SoftwareStartConv(ADC1);                                 //开启ADCwhile(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));                 //如果ADC转换结束  powervalue = (uint16_t)((After_Filter*3300*3)>>12);
}

至此,读取ADC电量步骤圆满完成!

stm32l151 ADC通过DMA通道定时采样电池电量相关推荐

  1. STM32F407 ADC+DMA+定时器 定时采样模拟量

    STM32F407 ADC+DMA+定时器 定时采样模拟量 文章目录 STM32F407 ADC+DMA+定时器 定时采样模拟量 前言 一.硬件原理 1.1 ADC 1.2 定时器 3. DMA 二. ...

  2. STM32HAL ADC+TIM+DMA采集交流信号 基于cubemx

    ADC+TIM+DMA采集交流 前言 本文主要讲解定时器触发ADC去采集交流信号,DMA把数据搬移到内存. 所需工具: 开发板:STM32F103C8T6 STM32CubeMX IDE: Keil- ...

  3. STM32cubeHAL ADC+TIM+DMA (二)

    ADC+TIM+DMA采集交流(二) 前言 本文是<STM32HAL ADC+TIM+DMA采集交流信号>的续篇,这一篇我们将让ADC以1M的速度去采集.过程中会学习到ADC时钟,采样率控 ...

  4. 基于STM32HAL库ADC+DMA模式,高精度采集电池电量与芯片内部温度方法 (48脚 使用内部参考电压方案)

    目录 概述 1.原理图 2.在这先普及一下概念 3.通过查看STM32L0中文数据手册中301页,第14.10 小节 ,DataSheet 4.ADC通道转换模式的理解 5.STM32CubeMx工具 ...

  5. STM32F404的ADC之DMA的单通道

    这里是接前面的文章 PA3 ADC1的通道3 下面是完整的程序 __IO uint16_t AdcValue =0; /**************************************** ...

  6. STM32 H7系列ADC DMA模式过采样设置详解 cubeMX

    最近做项目需要用H743的ADC采样,发现和M3及M4的差别还是蛮多的,MPU的配置对DMA读取数据的影响.过采样机制等,其中H7的硬件过采样是个很实用的东西,硬汉大佬也进行了测试: STM32H7的 ...

  7. 如何使用S32K1的PDB模块触发多个ADC通道连续采样

    文章目录 1. 外设模块介绍 1.1 PDB模块简介 1.2 ADC通道 1.3 ADC触发源 1.4 PDB触发多个ADC通道的两种方式 2. 例程 2.1 例程功能介绍 2.2 例程编写 2.2. ...

  8. 基于DMA通道的连续ADC扫描读取

    ADC ADC即是模数转换器,将电压信号转换为数字信号. 以stm32f407为例,其拥有18个12位ADC转换通道,其中16个外部通道以及俩个内部通道. ADC有单次,连续,扫描或间断模式执行转换, ...

  9. STM32CUBEIDE(10)----ADC在DMA模式下扫描多个通道

    STM32CUBEIDE.10----ADC在DMA模式下扫描多个通道 概述 样品申请 视频教学 csdn课程 代码下载 生成例程 STM32CUBEIDE配置 串口重定向 代码 测试结果 概述 本章 ...

最新文章

  1. 刚刚Sci-Hub和特朗普一样被永久封禁,Twitter官方:不得上诉
  2. 20180917-1每周例行报告
  3. python金字塔图绘制_如何用R或Python绘制3d(4变量)三元(金字塔)图?
  4. Java多线程之CyclicBarrier用法
  5. 自定义view实现水波纹效果
  6. 邻接矩阵存储图的深度优先遍历
  7. 海南省月降水量分布数据
  8. Nexus下载安装及对接
  9. 使用按键精灵编写云顶之奕挂机脚本
  10. 最基础内网ip地址配置
  11. 纯css动画效果--animate的应用
  12. 心电信号系统GUI系统
  13. fs.readFileSync 引入路径错误
  14. 大数据学习第一课:虚拟机安装配置
  15. 关于HTML中a标签的重大安全性漏洞!!!
  16. 买了一台美版ThinkPad T460s
  17. [转载]【实拍】:绿色灾难中的我们|浒苔带来的启示
  18. scala-MLlib官方文档---spark.ml package--ML Pipelines+Collaborative Filtering+Frequent Pattern Mining
  19. POP和PUSH指令
  20. 以transformer为基础的Bert和GPT

热门文章

  1. Redis6客户端工具——Jedis
  2. 数控车椭圆编程实例带图_简析数控车床上椭圆加工的编程方法
  3. wordpress配置菜单栏
  4. amqp协议java_amqp协议链接陷阱-An unexpected connection driver error occured
  5. 在线PS把图片背景变成透明(灰白格子)
  6. 以太坊Solidity之Truffle的使用流程与集成指南
  7. 消防应急灯锂电池供电2.5V-30V升压恒流驱动IC方案
  8. 2022-2028年全球与中国饲料核苷酸行业市场需求预测分析
  9. 单片机控制秒表C语言程序,89C51单片机秒表的设计(全文完整版)
  10. 一文搞懂TCP/IP,入门计算机网络必看!