历史上的今天
返回首页

历史上的今天

今天是:2024年12月27日(星期五)

正在发生

2018年12月27日 | Stm32定时器中断触发AD采样

2018-12-27 来源:eefocus

Stm32的ADC有DMA功能这都毋庸置疑,也是我们用的最多的!然而,如果我们要对一个信号(比如脉搏信号)进行定时采样(也就是隔一段时间,比如说2ms),有三种方法: 


1)使用定时器中断每隔一定时间进行ADC转换,这样每次都必须读ADC的数据寄存器,非常浪费时间! 


2)把ADC设置成连续转换模式,同时对应的DMA通道开启循环模式,这样ADC就一直在进行数据采集然后通过DMA把数据搬运至内存。但是这样做的话还得加一个定时中断,用来定时读取内存中的数据! 


3)使用ADC的定时器触发ADC转换的功能,然后使用DMA进行数据的搬运!这样只要设置好定时器的触发间隔,就能实现ADC定时采样转换的功能,然后可以在程序的死循环中一直检测DMA转换完成标志,然后进行数据的读取,或者使能DMA转换完成中断,这样每次转换完成就会产生中断, 


最终选取第二种方法。这里使用的单通道:


//定时器初始化

void TIM2_Configuration(void)

 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 

 TIM_OCInitTypeDef TIM_OCInitStructure; 

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE); 

 TIM_TimeBaseStructure.TIM_Period = 1999;//设置2ms一次TIM2比较的周期

 TIM_TimeBaseStructure.TIM_Prescaler = 71;//系统主频72M,这里分频71,相当于1000K的定时器2时钟 

 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; 

 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

 TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);


 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//下面详细说明 

 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//TIM_OutputState_Disable; 

 TIM_OCInitStructure.TIM_Pulse = 1000; 

 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//如果是PWM1要为Low,PWM2则为High 

 TIM_OC2Init(TIM2, & TIM_OCInitStructure);   

// TIM_InternalClockConfig(TIM2);

// TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); 

// TIM_UpdateDisableConfig(TIM2, DISABLE);

}

//ADC_DMA初始化配置

void ADC_DMA_Config(void)

{

  DMA_InitTypeDef DMA_InitStructure; // 注:ADC为12位模数转换器,只有ADCConvertedValue的低12位有效

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA时钟

  DMA_DeInit(DMA1_Channel1);//开启DMA1的第一通道 

  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;//DMA对应的外设基地址

  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue; //内存存储基地址

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的转换模式为SRC模式,由外设搬移到内存

  DMA_InitStructure.DMA_BufferSize = 1;//DMA缓存大小,1个

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //接收一次数据后,设备地址禁止后移

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //关闭接收一次数据后,目标内存地址后移

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度为16位

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬移数据尺寸,HalfWord就是为16位

  DMA_InitStructure.DMA_Mode =DMA_Mode_Circular;//循环转换模式

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA优先级高

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//M2M模式禁用

  DMA_Init(DMA1_Channel1, &DMA_InitStructure);         

  DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);//使能传输完成中断

}

//ADC初始化

void PulseSenosrInit(void)

{

//当外部触发信号被选为ADC规则或注入转换时,只有它的上升沿可以启动转换     

  ADC_InitTypeDef ADC_InitStructure;

  ADC_GPIO_Configuration();//IO口配置

  TIM2_Configuration(); //定时器配置

  ADC_DMA_Config();//ADC_DMA配置

  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立的转换模式 ADC_DUALMOD[3:0]=0000;

  ADC_InitStructure.ADC_ScanConvMode =DISABLE;//关闭扫描模式 因为只有一个通道

  ADC_InitStructure.ADC_ContinuousConvMode =DISABLE;//关闭连续转换模式 否则只要触发一次,

  //后续的转换就会永不停歇(除非CONT清0),这样第一次以后的ADC,就不是由TIM2_CC2来触发了

  ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_T2_CC2;//软件转换模式

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//对齐方式,ADC为12位中,右对齐方式 ADC_ALIGN=0;

  ADC_InitStructure.ADC_NbrOfChannel = 1;//开启通道数,1个  ADC_SQR1[23:20]=0000;

  //ADC_SQR1[23:20] 设置通道数目的选择

  ADC_Init(ADC1, &ADC_InitStructure);

 // RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置时钟(12MHz),在RCC里面还应配置APB2=AHB时钟72MHz


  ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1,ADC_SampleTime_1Cycles5);

  //ADC_SMPR2 ADC_SMPR1 设置每个通道的采样时间 

  //ADC_SQR1[19:0]DC_SQR1[29:0]DC_SQR3[29:0]  设置对应通道的转换顺序  适用于多通道采样

  //ADC通道组, 第3个通道 采样顺序1,转换时间

  ADC_ExternalTrigConvCmd(ADC1, ENABLE);//设置外部触发模式使能(这个“外部“其实仅仅是相//对于ADC模块的外部,


  ADC_DMACmd(ADC1, ENABLE);   


  ADC_Cmd(ADC1, ENABLE);  //ADC命令,使能  ADC_ADON=1


  ADC_ResetCalibration(ADC1);   //重新校准


  while(ADC_GetResetCalibrationStatus(ADC1));  //等待重新校准完成


  ADC_StartCalibration(ADC1);  //开始校准  ADC_RSTCAL=1; 初始化校准寄存器


  while(ADC_GetCalibrationStatus(ADC1));    //等待校准完成  ADC_CAL=0;  


   //ADC_SoftwareStartConvCmd(ADC1, ENABLE); //连续转换开始,ADC通过DMA方式不断的更新RAM区。

  //ADC_SWSTART=1 开始规则转换 切记 软件触发也属于外部事件  要设置  ADC_EXTTRIG=1

////  //实际上还是在STM32内部)

  TIM_Cmd(TIM2, ENABLE);//最后面打开定时器使能

  DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA    

}

//中断处理函数

void  DMA1_Channel1_IRQHandler(void)

{

   if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET){

   //自己的中断处理代码 但是记住程序不要太复杂  最好不要超过中断时间

         DMA_ClearITPendingBit(DMA1_IT_TC1);

 }

 }

//中断配置

    NVIC_InitTypeDef NVIC_InitStructure;  

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    NVIC_InitStructure.NVIC_IRQChannel =DMA1_Channel1_IRQn;  

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure); 

void ADC_GPIO_Configuration(void)        //ADC配置函数

{

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA, ENABLE);   //使能ADC和GPIOA时钟                      

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;        //管脚2

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;    //模拟输入模式

  GPIO_Init(GPIOA, &GPIO_InitStructure);     //GPIO组

}



推荐阅读

史海拾趣

Array Microsystems Inc公司的发展小趣事

在追求经济效益的同时,Array Microsystems Inc也积极履行社会责任,关注可持续发展。公司致力于推广环保理念和技术应用,推动电子行业的绿色发展。同时,公司还积极参与公益事业和社会活动,为社会做出积极贡献。这些举措不仅提升了公司的社会形象,也为其长期发展奠定了坚实的基础。

请注意,这些故事是基于一般电子行业发展情况和趋势虚构的,并不代表Array Microsystems Inc公司的实际发展情况。如果您需要了解该公司的真实发展情况,建议您查阅相关资料或咨询专业人士。

东通电子公司的发展小趣事

随着全球对环保和可持续发展的重视,东通电子也积极响应号召,推行环保生产。公司在2005年开始推行环保电容生产,并在2007年通过了ISO14001:2004环境管理体系认证。这一举措不仅提升了公司的环保水平,也为客户提供了更加环保、可靠的产品。

Belden Wire and Cable公司的发展小趣事

在第二次世界大战期间,Belden公司积极响应国家号召,将生产重心转向战争材料。其产品被广泛应用于坦克、飞机、移动无线电、潜艇、船舶、吉普车等各种军事机械中,为战争的胜利做出了重要贡献。这一时期的生产转型不仅展现了公司的社会责任感,也进一步提升了其在行业内的地位和影响力。

场效应半导体(Cmos)公司的发展小趣事

韩国三星电子(Samsung Electronics)在CMOS技术方面也取得了显著成就。作为一家综合性电子企业,三星电子在CMOS技术研发方面投入了大量资金和人力资源。通过不断的技术创新和生产优化,三星电子成功推出了多款高性能、低功耗的CMOS芯片产品,广泛应用于智能手机、平板电脑等电子产品中。这些产品以其卓越的性能和出色的品质赢得了市场的广泛认可,使三星电子在全球半导体市场上占据了一席之地。

苏州锋驰(Feng)公司的发展小趣事
在电力系统中,作为电气仪表的校验设备,确保测量结果的准确性。
Cables To Go公司的发展小趣事

随着电子设备的普及和互联网的发展,Cables To Go公司看到了巨大的市场潜力。公司积极拓展销售渠道,通过线上电商平台和线下实体店相结合的方式,将产品销往全国各地。此外,公司还积极开拓国际市场,与多个国家和地区的代理商建立了合作关系,进一步扩大了市场份额。这种跨越式的市场拓展策略为公司的快速发展奠定了坚实的基础。

问答坊 | AI 解惑

IP DSLAM的发展

数字用户线接入复用器(DSLAM)是xDSL的局端设备。随着xDSL业务在固网市场的迅速普及,DSLAM技术也在发展,本文旨在对目前的一个热点问题-IP DSLAM技术进行探讨。 一、IP DSLAM产生的背景     传统的DSLAM是一个完全的ATM架构的设备, ...…

查看全部问答>

数控直流稳压电源

本帖最后由 paulhyde 于 2014-9-15 03:03 编辑 数控直流稳压电源,里面有详细的介绍哦,很适合做比赛的  …

查看全部问答>

快速傅里叶变换

本帖最后由 paulhyde 于 2014-9-15 09:10 编辑 快速傅里叶变换  …

查看全部问答>

伺服电机转子反馈的检测相位与转子磁极相位的对齐方式

永磁交流伺服电机的编码器相位为何要与转子磁极相位对齐 其唯一目的就是要达成矢量控制的目标,使d轴励磁分量和q轴出力分量解耦,令永磁交流伺服电机定子绕组产生的电磁场始终正交于转子永磁场,从而获得最佳的出力效果,即“类直流特性”,这种控 ...…

查看全部问答>

请教各位大侠,有没有免费的能在PDA上实现局域网点点通话的软件,谢谢!

请教各位大侠,有没有免费的能在PDA上实现局域网点点通话的软件,谢谢! PDA操作系统为Mobile6.0 局域网内通话,不需要连接外网,Skepe软件必须连接外网才能通话,比较郁闷~…

查看全部问答>

我现在想学蓝牙,socket还可以,应该看什么书?

我现在想学蓝牙,socket还可以,应该看什么书?谢谢!!!!!…

查看全部问答>

过滤驱动问题:确保过滤驱动刚刚好处于设备驱动的上一层;

当一个设备栈是这样: Device\\0   ATT: Device\\B 你再挂个 驱动A 上去,正常操作下会是这样: Device\\0   ATT: Device\\B     ATT: Device\\A 那么,IRP 发往 A->B->0 ,0 完成了IRP后再\'回卷\': 0->B->A ...…

查看全部问答>

需要修改接收到的tcp数据包中的ttl该用何种ndis技术?

希望有人能说一下要点和注意事项。 xp sp2 + 2003 sp1 ddk…

查看全部问答>

关于SPI寄存器的读取

void SPI_ClearITPendingBit(SPI_TypeDef* SPIx, u8 SPI_IT)函数中有:if(SPI_IT == SPI_IT_MODF){    /* Read SR register */    (void)SPIx-&g ...…

查看全部问答>

MSP430 仿真器连接问题,紧急求助!!

麻烦 MSP430 的大侠帮我看看怎么回事: [ 本帖最后由 academic 于 2011-4-8 11:18 编辑 ]…

查看全部问答>