stm32l151 ADC通过DMA通道定时采样电池电量
最近在使用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通道定时采样电池电量相关推荐
- STM32F407 ADC+DMA+定时器 定时采样模拟量
STM32F407 ADC+DMA+定时器 定时采样模拟量 文章目录 STM32F407 ADC+DMA+定时器 定时采样模拟量 前言 一.硬件原理 1.1 ADC 1.2 定时器 3. DMA 二. ...
- STM32HAL ADC+TIM+DMA采集交流信号 基于cubemx
ADC+TIM+DMA采集交流 前言 本文主要讲解定时器触发ADC去采集交流信号,DMA把数据搬移到内存. 所需工具: 开发板:STM32F103C8T6 STM32CubeMX IDE: Keil- ...
- STM32cubeHAL ADC+TIM+DMA (二)
ADC+TIM+DMA采集交流(二) 前言 本文是<STM32HAL ADC+TIM+DMA采集交流信号>的续篇,这一篇我们将让ADC以1M的速度去采集.过程中会学习到ADC时钟,采样率控 ...
- 基于STM32HAL库ADC+DMA模式,高精度采集电池电量与芯片内部温度方法 (48脚 使用内部参考电压方案)
目录 概述 1.原理图 2.在这先普及一下概念 3.通过查看STM32L0中文数据手册中301页,第14.10 小节 ,DataSheet 4.ADC通道转换模式的理解 5.STM32CubeMx工具 ...
- STM32F404的ADC之DMA的单通道
这里是接前面的文章 PA3 ADC1的通道3 下面是完整的程序 __IO uint16_t AdcValue =0; /**************************************** ...
- STM32 H7系列ADC DMA模式过采样设置详解 cubeMX
最近做项目需要用H743的ADC采样,发现和M3及M4的差别还是蛮多的,MPU的配置对DMA读取数据的影响.过采样机制等,其中H7的硬件过采样是个很实用的东西,硬汉大佬也进行了测试: STM32H7的 ...
- 如何使用S32K1的PDB模块触发多个ADC通道连续采样
文章目录 1. 外设模块介绍 1.1 PDB模块简介 1.2 ADC通道 1.3 ADC触发源 1.4 PDB触发多个ADC通道的两种方式 2. 例程 2.1 例程功能介绍 2.2 例程编写 2.2. ...
- 基于DMA通道的连续ADC扫描读取
ADC ADC即是模数转换器,将电压信号转换为数字信号. 以stm32f407为例,其拥有18个12位ADC转换通道,其中16个外部通道以及俩个内部通道. ADC有单次,连续,扫描或间断模式执行转换, ...
- STM32CUBEIDE(10)----ADC在DMA模式下扫描多个通道
STM32CUBEIDE.10----ADC在DMA模式下扫描多个通道 概述 样品申请 视频教学 csdn课程 代码下载 生成例程 STM32CUBEIDE配置 串口重定向 代码 测试结果 概述 本章 ...
最新文章
- 刚刚Sci-Hub和特朗普一样被永久封禁,Twitter官方:不得上诉
- 20180917-1每周例行报告
- python金字塔图绘制_如何用R或Python绘制3d(4变量)三元(金字塔)图?
- Java多线程之CyclicBarrier用法
- 自定义view实现水波纹效果
- 邻接矩阵存储图的深度优先遍历
- 海南省月降水量分布数据
- Nexus下载安装及对接
- 使用按键精灵编写云顶之奕挂机脚本
- 最基础内网ip地址配置
- 纯css动画效果--animate的应用
- 心电信号系统GUI系统
- fs.readFileSync 引入路径错误
- 大数据学习第一课:虚拟机安装配置
- 关于HTML中a标签的重大安全性漏洞!!!
- 买了一台美版ThinkPad T460s
- [转载]【实拍】:绿色灾难中的我们|浒苔带来的启示
- scala-MLlib官方文档---spark.ml package--ML Pipelines+Collaborative Filtering+Frequent Pattern Mining
- POP和PUSH指令
- 以transformer为基础的Bert和GPT
热门文章
- Redis6客户端工具——Jedis
- 数控车椭圆编程实例带图_简析数控车床上椭圆加工的编程方法
- wordpress配置菜单栏
- amqp协议java_amqp协议链接陷阱-An unexpected connection driver error occured
- 在线PS把图片背景变成透明(灰白格子)
- 以太坊Solidity之Truffle的使用流程与集成指南
- 消防应急灯锂电池供电2.5V-30V升压恒流驱动IC方案
- 2022-2028年全球与中国饲料核苷酸行业市场需求预测分析
- 单片机控制秒表C语言程序,89C51单片机秒表的设计(全文完整版)
- 一文搞懂TCP/IP,入门计算机网络必看!