STM32笔记记录5,捕捉

发布者:温馨小筑最新更新时间:2016-12-30 来源: eefocus关键字:STM32  捕捉 手机看文章 扫描二维码
随时随地手机看文章

给等待入门的人一点点建议 : 


入门必须阅读的相关文档


1、 几个重要官方文档的功能:


a) Datasheet——芯片基本数据,功能参数封装管脚定义和性能规范。


b) 固件函数库用户手册——函数库功能,库函数的定义、功能和用法。


c) 参考手册——各种功能的具体描述,使用方法,原理,相关寄存器。


d) STM32F10xxx硬件开发:使用入门——相关基础硬件设计


e) STM32F10XXX的使用限制:芯片内部未解决的硬件设计bug,开发需要注意绕开。


f) 一本简单的C语言书,相信我,不用太复杂。


2、 其他的有用文档,对初学帮助很大


a) 如何使用STM32的软件库在IAR的EWARM下进行应用开发——IAR基础设置。


b) 轻松进入STM32+Cortex-M3世界.ppt——开发板和最小系统设计需求。


c) 如何选择STM32开发板.pdf——各种开发板介绍和功能比较。


d) MXCHIP的系列视频教程——全部芯片基础及其外设的教程,使用函数库编程的话就不用看每个视频后半段的关于寄存器的介绍了。


e) STM32_Technical_Slide(常见问题)——一些优化设计方案。


3、 关于参考书,买了两本但是基本对学习没什么帮助,如果凑齐以上资料,建议慎重买书,不如留着那n个几十块钱,攒到一起买开发板。


我自己的学习过程


1、 一共24个库,不可能都学,都学也没用。按照我的工作需求必须学的有16个,这16个也不是全学。主要学习来源是各种例程代码、“固件函数库用户手册”和“参考手册”。


具体学习方法是通读不同来源的程序,在程序中找到相关的函数库的应用,然后再阅读相关文档,有条件的实验。对于内容的选择方面,根据入门内容和未来应用,将所涉及的范围精简到最低,但是对所选择的部分的学习则力求明确。以下是我按照自己的需求对程序库函数排列的学习顺序:


a) 绝大部分程序都要涉及到的库——flash,lib,nvic,rcc,只学基础的跟最简单应用相关必用的部分,其他部分后期再返回头学。


b) 各种程序通用但不必用的库——exti,MDA,systic,只通读理解其作用。


c) DEMO板拥有的外设库——gpio,usart,编写代码实验。


d) 未来需要用到的外设的库——tim,tim1,adc,i2c,spi,先理解等待有条件后实验。


e) 开发可靠性相关库——bkp,iwdg,wwdg,pwr,参考其他例程的做法。


f) 其他,根据兴趣来学。


这些代码大家都用得到  


2、 阅读flash: 芯片内部存储器flash操作函数


 


我的理解——对芯片内部flash进行操作的函数,包括读取,状态,擦除,写入等等,可以允许程序去操作flash上的数据。


 


基础应用1,FLASH时序延迟几个周期,等待总线同步操作。推荐按照单片机系统运行频率,0—24MHz时,取Latency=0;24—48MHz时,取Latency=1;48~72MHz时,取Latency=2。所有程序中必须的


 


用法:FLASH_SetLatency(FLASH_Latency_2);


 


位置:RCC初始化子函数里面,时钟起振之后。


 


基础应用2,开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的


 


用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


 


位置:RCC初始化子函数里面,时钟起振之后。


 


3、 阅读lib:调试所有外设初始化的函数。


 


我的理解——不理解,也不需要理解。只要知道所有外设在调试的时候,EWRAM需要从这个函数里面获得调试所需信息的地址或者指针之类的信息。


 


基础应用1,只有一个函数debug。所有程序中必须的。


 


用法: #ifdef DEBUG


 


    debug();


 


#endif


 


位置:main函数开头,声明变量之后。


 


4、 阅读nvic:系统中断管理。


 


我的理解——管理系统内部的中断,负责打开和关闭中断。


 


基础应用1,中断的初始化函数,包括设置中断向量表位置,和开启所需的中断两部分。所有程序中必须的。


 


用法: void NVIC_Configuration(void)


 


{


 


NVIC_InitTypeDef NVIC_InitStructure;//中断管理恢复默认参数


 


#ifdef  VECT_TAB_RAM   


 


//如果C/C++ Compiler\Preprocessor\Defined symbols中的定义了VECT_TAB_RAM(见程序库更改内容的表格)


 


NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //则在RAM调试


 


#else        //如果没有定义VECT_TAB_RAM


 


NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//则在Flash里调试


 


#endif        //结束判断语句


 


//以下为中断的开启过程,不是所有程序必须的。


 


//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  


 


//设置NVIC优先级分组,方式。


 


//注:一共16个优先级,分为抢占式和响应式。两种优先级所占的数量由此代码确定,NVIC_PriorityGroup_x可以是0、1、2、3、4,分别代表抢占优先级有1、2、4、8、16个和响应优先级有16、8、4、2、1个。规定两种优先级的数量后,所有的中断级别必须在其中选择,抢占级别高的会打断其他中断优先执行,而响应级别高的会在其他中断执行完优先执行。


 


//NVIC_InitStructure.NVIC_IRQChannel = 中断通道名;


 


//开中断,中断名称见函数库


 


//NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;


 


//抢占优先级


 


//NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  


 


//响应优先级


 


//NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//启动此通道的中断


 


//NVIC_Init(&NVIC_InitStructure);     //中断初始化


 


}


 


5、 阅读rcc:单片机时钟管理。


 


我的理解——管理外部、内部和外设的时钟,设置、打开和关闭这些时钟。


 


基础应用1:时钟的初始化函数过程——


 


用法:void RCC_Configuration(void)    //时钟初始化函数


 


{


 


  ErrorStatus HSEStartUpStatus;     //等待时钟的稳定


 


  RCC_DeInit();         //时钟管理重置


 


  RCC_HSEConfig(RCC_HSE_ON);      //打开外部晶振


 


  HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部晶振就绪


 


  if (HSEStartUpStatus == SUCCESS)


 


  {


 


FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


 


//flash读取缓冲,加速


 


    FLASH_SetLatency(FLASH_Latency_2); //flash操作的延时


 


    RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB使用系统时钟


 


    RCC_PCLK2Config(RCC_HCLK_Div2);  //APB2(高速)为HCLK的一半


 


    RCC_PCLK1Config(RCC_HCLK_Div2);  //APB1(低速)为HCLK的一半


 


//注:AHB主要负责外部存储器时钟。PB2负责AD,I/O,高级TIM,串口1。APB1负责DA,USB,SPI,I2C,CAN,串口2345,普通TIM。


 


    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);


 


//PLLCLK = 8MHz * 9 = 72 MHz


 


    RCC_PLLCmd(ENABLE);     //启动PLL


 


while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}


 


//等待PLL启动


 


RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);


 


//将PLL设置为系统时钟源


 


while (RCC_GetSYSCLKSource() != 0x08){}


 


          //等待系统时钟源的启动


 


  }


 


  //RCC_AHBPeriphClockCmd(ABP2设备1 | ABP2设备2 |, ENABLE);


 


  //启动AHP设备


 


  //RCC_APB2PeriphClockCmd(ABP2设备1 | ABP2设备2 |, ENABLE);


 


  //启动ABP2设备


 


  //RCC_APB1PeriphClockCmd(ABP2设备1 | ABP2设备2 |, ENABLE);


 


  //启动ABP1设备


 


}


 


1、阅读exti:外部设备中断函数


 


我的理解——外部设备通过引脚给出的硬件中断,也可以产生软件中断,19个上升、下降或都触发。EXTI0~EXTI15连接到管脚,EXTI线16连接到PVD(VDD监视),EXTI线17连接到RTC(闹钟),EXTI线18连接到USB(唤醒)。


 


    基础应用1,设定外部中断初始化函数。按需求,不是必须代码。


 


    用法: void EXTI_Configuration(void)


 


{


 


EXTI_InitTypeDef EXTI_InitStructure; //外部设备中断恢复默认参数


 


EXTI_InitStructure.EXTI_Line = 通道1|通道2;  


 


//设定所需产生外部中断的通道,一共19个。


 


EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //产生中断


 


EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;


 


//上升下降沿都触发  


 


EXTI_InitStructure.EXTI_LineCmd = ENABLE; //启动中断的接收  


 


EXTI_Init(&EXTI_InitStructure);           //外部设备中断启动


 


}


 


2、阅读dma:通过总线而越过CPU读取外设数据


 


我的理解——通过DMA应用可以加速单片机外设、存储器之间的数据传输,并在传输期间不影响CPU进行其他事情。这对于入门开发基本功能来说没有太大必要,这个内容先行跳过。


 


3、阅读systic:系统定时器


 


我的理解——可以输出和利用系统时钟的计数、状态。


 


基础应用1,精确计时的延时子函数。推荐使用的代码。


 


    用法:


 


static vu32 TimingDelay;//全局变量声明


 


void SysTick_Config(void)//systick初始化函数


 


{


 


    SysTick_CounterCmd(SysTick_Counter_Disable);//停止系统定时器


 


    SysTick_ITConfig(DISABLE);                //停止systick中断


 


    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);


 


    //systick使用HCLK作为时钟源,频率值除以8。


 


    SysTick_SetReload(9000);//重置时间1毫秒(以72MHz为基础计算)


 


    SysTick_ITConfig(ENABLE);//开启systic中断


 


}


 


void Delay (u32 nTime) //延迟一毫秒的函数


 


{


 


    SysTick_CounterCmd(SysTick_Counter_Enable);   //systic开始计时


 


    TimingDelay = nTime;               //计时长度赋值给递减变量


 


    while(TimingDelay != 0);           //检测是否计时完成


 


SysTick_CounterCmd(SysTick_Counter_Disable);  //关闭计数器


 


    SysTick_CounterCmd(SysTick_Counter_Clear);    //清除计数值


 


}


 


void TimingDelay_Decrement(void)


 


//递减变量函数,函数名由“stm32f10x_it.c”中的中断响应函数定义好了。


 


{


 


    if (TimingDelay != 0x00)               //检测计数变量是否达到0


 


       {  


 


      TimingDelay--;                     //计数变量递减


 


       }


 


}


 


注:建议熟练后使用,所涉及知识和设备太多,新手出错的可能性比较大。新手可用简化的延时函数代替:


 


void Delay(vu32 nCount)//简单延时函数


 


{


 


  for(; nCount != 0; nCount--);(循环变量递减计数)


 


}


 


当延时较长,又不需要精确计时的时候可以使用嵌套循环:


 


void Delay(vu32 nCount)        //简单的长时间延时函数


 


{int i;                         //声明内部递减变量


 


  for(; nCount != 0; nCount--)  //递减变量计数


 


{for (i=0; i<0xffff; i++)}  //内部循环递减变量计数


 


}


 


4、阅读gpio:I/O设置函数


 


我的理解——所有输入输出管脚模式设置,可以是上下拉、浮空、开漏、模拟、推挽模式,频率特性为2M,10M,50M。也可以向该管脚直接写入数据和读取数据。


 


    基础应用1,gpio初始化函数。所有程序必须。


 


    用法:void GPIO_Configuration(void)


 


{


 


    GPIO_InitTypeDef GPIO_InitStructure;   //GPIO状态恢复默认参数


 


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_标号 | GPIO_Pin_标号 ;


 


//管脚位置定义,标号可以是NONE、ALL、0至15。


 


GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//输出速度2MHz


 


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


 


    GPIO_Init(GPIOC, &GPIO_InitStructure);        //C组GPIO初始化


 


//注:以上四行代码为一组,每组GPIO属性必须相同,默认的GPIO参数为:ALL,2MHz,FLATING。如果其中任意一行与前一组相应设置相同,那么那一行可以省略,由此推论如果前面已经将此行参数设定为默认参数(包括使用GPIO_InitTypeDef GPIO_InitStructure代码),本组应用也是默认参数的话,那么也可以省略。以下重复这个过程直到所有应用的管脚全部被定义完毕。


 


……


 


}


 


    基础应用2,向管脚写入0或1


 


    用法:GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01);//写入1


捕捉精彩瞬间,脉冲方波长度捕获 

a)   目的:基础PWM输入也叫捕获,以及中断配合应用。使用前一章的输出管脚PB1(19脚),直接使用跳线连接输入的PA3(13脚),配置为TIM2_CH4,进行实验。 

b)   对于简单的PWM输入应用,暂时无需考虑TIM1的高级功能之区别,按照目前我的应用目标其实只需要采集高电平宽度,而不必知道周期,所以并不采用PWM输入模式,而是普通脉宽捕获模式。 

c)   初始化函数定义: 

void TIM_Configuration(void);  //定义TIM初始化函数 

d)   初始化函数调用: 

TIM_Configuration();  //TIM初始化函数调用 

e)   初始化函数,不同于前面模块,TIM的CAP初始化分为三部分——计时器基本初始化、通道初始化和时钟启动初始化: 

void TIM_Configuration(void)//TIM2的CAP初始化函数 

{  

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//定时器初始化结构 

  TIM_ICInitTypeDef TIM_ICInitStructure;         //通道输入初始化结构 

//TIM2输出初始化 

  TIM_TimeBaseStructure.TIM_Period = 0xFFFF;     //周期0~FFFF 

  TIM_TimeBaseStructure.TIM_Prescaler = 5;       //时钟分频 

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;   //时钟分割 

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//模式 

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//基本初始化 

//TIM2通道的捕捉初始化   

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;//通道选择 

  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;//下降沿 

  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//管脚与寄存器对应关系 

  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//分频器 

  TIM_ICInitStructure.TIM_ICFilter = 0x4;        //滤波设置,经历几个周期跳变认定波形稳定0x0~0xF 

  TIM_ICInit(TIM2, &TIM_ICInitStructure);        //初始化



  TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);   //选择时钟触发源 

  TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);//触发方式 

  TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //启动定时器的被动触发 

  TIM_ITConfig(TIM2, TIM_IT_CC4, ENABLE);        //打开中断 

  TIM_Cmd(TIM2, ENABLE);                         //启动TIM2 

f)    RCC初始化函数中加入TIM时钟开启: 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM3, ENABLE); 

g)    GPIO里面将输入和输出管脚模式进行设置。IN_FLOATING,50MHz。 

h)    使用中断的话在NVIC里添加如下代码: 

//打开TIM中断(与前一章相同) 

  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel; 

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; 

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;


  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 

i)     简单应用: 

变量 = TIM_GetCapture4(TIM2); 

j)     注意事项: 

i.    由于我的需求只跟高电平宽度有关,所以避免了使用PWM输入模式,这样可以每个管脚捕捉一路信号。如果使用PWM模式,每一路需要占用两个寄存器,所以一个定时器只能同时使用两路PWM输入。 

ii.   由于捕捉需要触发启动定时器,所以PWM输出与捕捉不容易在同一个TIM通道上实现。如果必须的话只能增加计数溢出的相关代码。 

iii.  有些程序省略了捕捉通道的初始化代码,这是不对的 

iv.   在基本计时器初始化代码里面注意选择适当的计数器长度,最好让波形长度不要长于一个计数周期,否则需要增加溢出代码很麻烦。一个计数周期的长度计算跟如下几个参数有关: 

(1)   RCC初始化代码里面的RCC_PCLKxConfig,这是TIM的基础时钟源与系统时钟的关系。 

(2)   TIM初始化的TIM_Period,这是计数周期的值 

(3)   TIM初始化的TIM_Prescaler,这是计数周期的倍频计数器,相当于调节计数周期,可以使TIM_Period尽量大,提高计数精度。


关键字:STM32  捕捉 引用地址:STM32笔记记录5,捕捉

上一篇:STM32输入捕获简介
下一篇:STM32 I/O的耐压问题,中断问题

推荐阅读最新更新时间:2024-03-16 15:27

一文看懂stm32的引脚的两种用途:GPIO和AFIO
stm32的引脚有两种用途:GPIO(general purpose io)和AFIO(alternate function io) 对于一些引脚(视芯片而定),这两种用途都没有,如在64脚产品中,OSC_IN/OSC_OUT与作为GPIO端口的PD0/PD1共用一样的引脚,而在100、144引脚产品中,这四个功能各有引脚与之对应,不互相冲突,所以OSC_IN/OSC_OUT既不作GPIO也不作AFIO,当然,这样的引脚不是讨论重点。 1、引脚的配置 不论是作GPIO还是做AFIO,都要对引脚进行配置。在固件库函数中,用GPIO_Init()函数对引脚进行配置,并不是说这个函数带了“GPIO”字样就是要当做GPIO来用,而是把
[单片机]
一文看懂<font color='red'>stm32</font>的引脚的两种用途:GPIO和AFIO
用汇编语言实现STM32的LED和USART
; AREA RESET, DATA, READONLY DCD 0x20000000 + 1024 ;0 DCD UserMain ;1 DCD 0 ;NMI 2 DCD 0 ;HardFault 3 DCD 0 ;MemManage 4 DCD 0 ; 5 DCD 0 ; 6 DCD 0 ; 7 DCD 0 ; 8 DCD 0 ; 9 DCD 0 ; 10 DCD 0 ; 11 DCD 0 ; 12 DCD 0 ; 13 DCD 0 ; 14 DCD SysTick_Handler ; 15 HelloString DCB Hello Wordn HelloEnd HexTable DC
[单片机]
stm32定时器输出4路频率可调的原理分析
1标题说不清楚,简单点说就是一个定时器输出4路可调节频率的pwm。 2这个功能能干嘛? 一般是用于控制多个步进电机。这样做一个定时器就可以控制4个电机了。 先上代码吧 u16 capture = 0; vu16 CCR1_Val = 32768; vu16 CCR2_Val = 16384; vu16 CCR3_Val = 8192; vu16 CCR4_Val = 4096; void PWM1_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructur
[单片机]
CPLD被STM32读写VHDL程序
1 2 3 --本程序用来测试STM32对CPLD的读写操作 4 5 --测试功能如下: 6 7 --向0x05地址写入0x01,LED灯停止闪烁,写入其他数据闪烁继续 8 9 --0x03,0x04寄存器为定值,可以通过STM32读取然后使用串口输出看看是否一致 10 11 12 13 --文件名:AD.vhd 14 15 library ieee; 16 17 use ieee.std_logic_1164.all; 18 19 use ieee.std_logic_unsigned.all; 20 21 22 23 entity AD is 24 25 port
[单片机]
STM32呼吸灯的PWM原理与代码实现
用定时器生成PWM波 PWM全称是Pulse Width Modulation,通过控制高频信号的占空比,眼睛当成低通滤波器,可以控制亮暗。再循环更改pwm的阈值,就弄出了呼吸的效果。 这里采用一个比较简单的方法生成PWM波:设置定时器中断然后根据阈值判断置高和置低。 void TIM3_IRQHandler(void) { TIM_ClearITPendingBit(TIM3,TIM_IT_Update); if(counter==255) counter = 0; else counter +=1; if(mode == 0){ if(counter pwm) GPIO_SetBits(GPIOA,G
[单片机]
基于STM32的触摸屏学习笔记
本文共有三个内容:一、电阻触摸屏的原理;二、XPT2046的控制字与数字接口;三、程序源码讲解(参考正点原子的代码) 一、电阻触摸屏的原理,上图: 图上的文字介绍了触摸的原理,下面总结一下触摸的原理: 触摸屏工作主要是两个电阻屏(上下两层)在工作,如上图,当某一层电级加上电压时,会在该网络上形成电压梯度。如果有外力使得上下两层在某一点接触,则在未加电压的那一层可以测得接触点的电压,从而得出接触点的坐标(X或Y)。举个例子:当我们在上层的电极间(Y+和Y-)加上电压,则会在上层形成电压梯度(这里读者可以想想AD转换的原理),当有外力使得上下两层在某一点接触时,在底层X层就可以测得接触点处的电压(每个点电压都不同),再根据测得电
[单片机]
基于<font color='red'>STM32</font>的触摸屏学习笔记
一文知道STM32 GUI的应用
整体上讲,很多STM32芯片内置了功能强大的用于加速图形处理的硬件加速器,借助它们一方面可以大大减轻CPU负荷,以节省CPU处理带宽去应对其它任务,另一方面,在节省内存同时还能保障动画或视频播放更为流畅。这些硬件图形加速器分别是STM32 Chrom-ART 加速器,或称DMA2D,是个专门用于二维图形操作处理的DMA;硬件JPEG 编解码器,用于对JPEG图像的编解码;STM32 Chrom-GRC,它是个内存管理单元,用于优化非方形图形显示的存储开销。 到目前为止,由于支持图形显示的STM32系列或料号很多,有时想基于STM32 的GUI应用做选型,可能要费一番功夫。这里有个表格,汇总了目前直接支持各类显示接口的STM32
[单片机]
一文知道<font color='red'>STM32</font> GUI的应用
STM32学习笔记之电容触摸2
(4)在led.c文件中添加以下代码 (5)在tpad.c文件内添加以下代码 #include tpad.h #include delay.h /*************************************************** Name :TPAD_Get_Value Function :触摸按键值获取 Paramater :None Return :获取的充电时间 ***************************************************/ u16 TPAD_Get_Value() { //电容放电 GPIOA- CRL &= 0xFFF
[单片机]
<font color='red'>STM32</font>学习笔记之电容触摸2
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved