完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM32的库函数操作给设计开发人员带来了诸多的便利,开发人员不必十分了解STM32的内部寄存器及硬件机制,只要有C语言基础,即可完成单片机的开发,缩短了开发周期,降低了开发难度,因而备受工程师喜爱。
基于库函数的开发模式,与基于API(Application Programming Interface)的软件开发有着异曲同工之处,程序员通过调用 API 函数对应用程序进行开发,而又无需访问源码,或理解内部工作机制的细节,可以减轻编程任务。STM32的基于函数库的开发模式也是一样的道理,因此对于有单片机开发经验的工程师来说,学习STM32,很容易就可以上手。 虽然可以不考虑库函数内部的细节,不考虑如何实现硬件寄存器的配置,但是深入了解库函数对于提高编程能力是很有好处的,下面以系统滴答时钟为例,详解其工作流程。 滴答时钟是STM32内部的一个24位定时器,其操作相对简单,配置寄存器较少。大体的工作流程是这样的,定时器首先要有时钟源,时钟源配置好之后,设置定时时间,然后定时器启动,当定时时间到时,置位标志位,重载定时器初值,系统可采用查询标志位和中断两种工作方式做出相应的响应,下面来看看程序如何实现延时功能。 //初始化配置函数 Void Delay_Init() { RCC_ClocksTypeDef RCC_ClocksStatus; RCC_GetClocksFreq(&RCC_ClocksStatus);//获取时钟频率 SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//时钟源配置为系统主时钟频率/8 SysTick_ITConfig(DISABLE);//不使能中断,采用查询方式 delay_fac_us = RCC_ClocksStatus.HCLK_Frequency / 8000000;// 1us的定时初值 } //实现延时Nus的延时功能 void Delay_us(u32 Nus) { SysTick_SetReload(delay_fac_us * Nus);//载入初值 SysTick_CounterCmd(SysTick_Counter_Clear);//计数器清零 SysTick_CounterCmd(SysTick_Counter_Enable);//计数器开始计数 do { Status = SysTick_GetFlagStatus(SysTick_FLAG_COUNT); }while (Status != SET);//不断查询标志位,当载入初值与计数器相等时,标志位置位。 SysTick_CounterCmd(SysTick_Counter_Disable);//关闭计数器 SysTick_CounterCmd(SysTick_Counter_Clear);//清零计数器 } //实现闪灯 Delay_Init(); While(1) { LED1(ON); Delay_us(500000);//延时500ms LED1(OFF); } 下面来看看库函数如何实现相应的寄存器配置。 void SysTick_ITConfig(FunctionalState NewState) { /* Check the parameters */ assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { SysTick-》CTRL |= CTRL_TICKINT_Set; } else { SysTick-》CTRL &= CTRL_TICKINT_Reset; } } 这个函数的作用是配置寄存器开启/关闭中断,FunctionalState是自定义的数据类型,是一个枚举类型,typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; 枚举类型是一种基本数据类型而不是构造类型,它用于声明一组命名的常数,将变量的值一一列出来,变量的值只限于列举出来的值的范围内,因此当一个变量有几种可能的取值时,可以将它定义为枚举类型。 assert_param(IS_FUNCTIONAL_STATE(NewState)); 这句话的作用是判断参数NewState的值是否正确,如果发现参数出错,它会调用函数assert_failed()向程序员报告错误。 void assert_failed(uint8_t* file, uint32_t line) { while (1) {} } SysTick-》CTRL |= CTRL_TICKINT_Set;这句话就是用来配置寄存器的语句, SysTick是系统定义的一个结构体如下,SysTick-》CTRL即为滴答时钟的控制寄存器。 typedef struct { __IO uint32_t CTRL; /*!《 Offset: 0x000 (R/W) SysTick Control and Status Register */ __IO uint32_t LOAD; /*!《 Offset: 0x004 (R/W) SysTick Reload Value Register */ __IO uint32_t VAL; /*!《 Offset: 0x008 (R/W) SysTick Current Value Register */ __I uint32_t CALIB; /*!《 Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type; //声明一个SysTick_Type型的结构体。 #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!《 SysTick configuration struct */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!《 SysTick Base Address */ #define SCS_BASE (0xE000E000UL) /*!《 System Control Space Base Address */ 定义一个SysTick_Type类型的结构体实例SysTick,而从根本上来说这是一个地址,就是STM32芯片内部分配给滴答时钟的实际地址0xE000E000UL+0x0010UL。 CTRL_TICKINT_Set是一个宏定义,定义如下 /* CTRL TICKINT Mask */ #define CTRL_TICKINT_Set ((u32)0x00000002) #define CTRL_TICKINT_Reset ((u32)0xFFFFFFFD) 至此,SysTick-》CTRL |= CTRL_TICKINT_Set;这句话的意义已经很清晰了,就是给地址0xE000E000+0x0010 +0x000赋一个0x00000002的值,对应滴答时钟的CTRL寄存器的第2位置1。即为开启中断的意思。 上面讲的是用查询的方式,下面再说下中断触发。只需调用下面这个函数即可完成中断的设置。 SysTick_Config(uint32_t ticks);具体实现如下: __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1) 》 SysTick_LOAD_RELOAD_Msk) return (1); SysTick-》LOAD = ticks - 1; NVIC_SetPriority (SysTick_IRQn, (1《《__NVIC_PRIO_BITS) - 1); SysTick-》VAL = 0; SysTick-》CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; return (0); } 函数的参数为ticks,是要装入寄存器SysTick-》LOAD的计数值,如果系统时钟为72M,把ticks赋值为SystemFrequency/10000,表示计数到720个时钟周期产生一次中断,而一个时钟周期的时间为(1/72)us,所以720x(1/72)=10us,也就实现了定时10us的功能。 NVIC_SetPriority (SysTick_IRQn, (1《《__NVIC_PRIO_BITS) - 1);为SysTick中断设置优先级。将寄存器SysTick-》VAL的值清0。然后使能中断,使能SysTick定时器,时钟源选择为AHB时钟。当定时时间到时,进入中断函数 void SysTick_Handler(void) { //具体函数实现由用户编写。 } 通过对这样一个简单定时器的操作,我们可以初步了解到STM32库函数的使用方法,其实开发人员没必要深究库函数内部是如何处理实现的,只需要了解已经封装好的库函数,进行调用即可,因此可以大大降低开发周期,提高开发效率,更多的功能留给读者自行研究开发。 |
|
|
|
只有小组成员才能发言,加入小组>>
798 浏览 0 评论
1154 浏览 1 评论
2531 浏览 5 评论
2863 浏览 9 评论
移植了freeRTOS到STMf103之后显示没有定义的原因?
2713 浏览 6 评论
keil5中manage run-time environment怎么是灰色,不可以操作吗?
1081浏览 3评论
195浏览 2评论
461浏览 2评论
374浏览 2评论
M0518 PWM的电压输出只有2V左右,没有3.3V是怎么回事?
455浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 17:14 , Processed in 1.100111 second(s), Total 77, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号