STM32开发中各库函数的主要作用和关系。

2023-10-26

STM32开发中各库函数的主要作用和关系

STM32各库函数关系的简单解析

您好! 这是我第一次使用 CSDN来发布文章, 如果有排版不合理,结构凌乱,欢迎私信我交流经验。文章内容如有错误,欢迎读者指正!

首先我们了解一下什么是库函数?

众所周知,芯片本身仅仅是一种硬件,没有软件的加持,无法完成某种特定功能。我们通过电脑编写程序烧录入芯片后,芯片便有了某种功能。在对于微控制器来说,目前主流芯片便是51和STM32,51由于是8位处理器,所以通过寄存器进行程序编写是可行的,但是32位处理器因为寄存器数量庞大,数据手册动辄上千页,这么多的寄存器要去吃透它,在难度和时间上面肯定不允许。但有了库函数以后,会让我们的开发效率大大提高。这一点非常重要,毕竟做项目的时间是非常有限的,如果要去研究寄存器的使用,那真是费时又费力,作为工程师来说,我们当然希望操作越简单越好了,如果是傻瓜式的操作那更好。库函数的使用让我们不需要去了解硬件的机制,只要根据功能去找到相应的操作函数就好了,大大降低了开发要求。

有了库函数还需要学习寄存器的操作吗?

作为一个从事底层软件开发的人,我认为还是有必要更加了解硬件的。用了库函数的缺点就是,代码量会增大,库函数会把所有情况都考虑到函数里面,有时会造成代码的冗余,在程序空间吃紧的时候,你还是得乖乖优化成寄存器的方式。对于一些实时性要求极其严格的场合,直接操作寄存器无疑是更好的选择。对于学习而言,打好寄存器的基础会让你使用库函数时事半功倍。

对于想要了解寄存器的读者,推荐大家下面几个文件,都是在学习寄存器时必不可少的文件。由于版权问题,不便直接上传文件,网上资源还是很好找的,大家随便找找都找的到。

  1. STM32F10x参考手册-V9
  2. STM32F10x闪存编程手册
  3. STM32固件库使用手册
  4. ARM Cortex-M3权威指南(第2版)

下面我将介绍主要库函数文件的关系

  1. stm32f10x.h
    这个文件可以说是最重要的文件之一,无论是寄存器开发还是库函数开发,此文件都是必不可少的。文件中定义了系统寄存器的地址以及使用结构体封装,定义声明以及包装内存操作。
    此文件中还包含stm32f10x_conf.h,这个文件在下一个中细讲。
    stm32f10x.h中定义了启动设置,以及所有寄存器宏定义,此文件中需要注意的有:
    1、device选择;2、外部时钟频率选择;3、外设宏定义USE_STDPERIPH_DRIVER;

各种寄存器的地址(仅仅截取了极小的一部分),有兴趣的可以打开源文件自己看一下
各种寄存器的地址,有兴趣的可以打开源文件自己看一下
文件中还包含stm32f10x_conf.h

在这里插入图片描述

  1. stm32f10x_conf.h
    stm32f10x_conf.h中包含了所有外设的头文件,因此任意源文件只要包含了stm32f10x.h,就可以在源文件调用任意外设的函数,而不需要的外设部分,可以在stm32f10x_conf.h中注释掉,项目编译时就不会再编译以及去掉的外设。
    在这里插入图片描述
    至此,基本的库函数文件就都被包含进来了。
  2. stm32f10x_it.c和stm32f10x_it.h
    文件中包含了所有中断服务函数
    中断是嵌入式系统中重要的组成部分,但是在标准C中不包含中断。许多编译开发商在标准C上增加了对中断的支持,提供新的关键字用于标示中断服务程序 (ISR),类似于__interrupt、#program interrupt等。当一个函数被定义为ISR的时候,编译器会自动为该函数增加中断服务程序所需要的中断现场入栈和出栈代码。
      中断服务程序需要满足如下要求:
      (1)不能返回值;
      (2)不能向ISR传递参数;
      (3) ISR应该尽可能的短小精悍;
      (4) printf(char * lpFormatString,…)函数会带来重入和性能问题,不能在ISR中采用。

a.为什么不能有返回值?

中断服务函数的调用是硬件级别的,当中断产生,pc指针强制跳转到对应的中断服务函数入口,进入中断具有随机性,并不是某段代码对其进行调用,那么如果有返回值它的返回值返回给谁?显然这个返回值毫无意义,如果有返回值,它必定需要进行压栈操作,这样一来何时出栈怎么出栈将变得无法解决。

b.不能向ISR传递参数?

同理,也是由于这样会破坏栈的原因,因为函数传递参数必定会要求压栈出栈操作,由于进入中断服务函数的随机行,谁给它传递参数都成问题

c.ISR应尽可能的短小精悍?

如果某个中断频繁产生,而它对应的ISR相当的耗时,那么对中断的响应就会无限的延迟,会丢掉很多的中断请求

d.printf(char * lpFormatString,…)函数会带来重入和性能问题,不能在ISR中采用。

这就涉及到一个中断嵌套问题,由于printf之类的glibc函数采用的是缓冲机制,这个缓冲区是共享的,相当于一个全局变量,第一层中断来时,它向缓冲里面写入一些部分内容,恰好这时来了个优先级更高的中断,它同样调用了printf,也向缓冲里面写入一些内容,这样缓冲区的内容就错乱了。

实际上,中断服务函数的函数名,是已经被强制定义过的,我们无法更改,只能使用。具体内容在启动文件 startup_stm32f10x_hd.s 之中,(芯片不同启动文件名称不同)。

一小部分中断服务函数,有兴趣的可以打开源文件自己看一下。
在这里插入图片描述
在使用中断服务函数时,我们只需要编写中断服务函数的具体内容便可,以串口1的中断服务函数为列。

void USART1_IRQHandler(void)                	//串口1中断服务程序
{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
  1. system_stm32f10x.c和 system_stm32f10x.h
    设备外设访问层,主要配置时钟频率(设置系统以及总线时钟)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32开发中各库函数的主要作用和关系。 的相关文章

  • 除了提供必要的保证之外,硬件内存屏障是否还能使原子操作的可见性更快?

    TL DR 在生产者 消费者队列中 放置不必要的 从 C 内存模型的角度来看 内存栅栏或不必要的强内存顺序是否有意义 以牺牲可能更差的吞吐量为代价获得更好的延迟 C 内存模型在硬件上执行 通过为更强的内存顺序设置某种内存栅栏 而不是在较弱的
  • 中断的尾链

    什么是 ARM Cortex M3 中 NVIC 支持的中断尾链 尾链是异常的背对背处理 无需 中断之间的状态保存和恢复的开销 这 处理器跳过八个寄存器的弹出操作和八个寄存器的压入操作 当退出一个 ISR 并进入另一个 ISR 时 因为这没
  • 如何在ARMv8-a上启用Aarch32指令集?

    Raspberry Pi 3 使用具有 ARMv8 A53 内核的 Broadcom SoC https www raspberrypi org magpi raspberry pi 3 specs benchmarks 它还使用基于 De
  • 抢占和上下文切换的区别

    一点介绍 我目前正在编写一个小型 读微型 RTOS 内核 它应该与内核中的大多数内容是一体的 然而 我找不到关于下面列出的一些事情的太多信息 这会很有帮助 除此之外 它实际上不是某种大学项目 而是我按照自己的意愿做的事情 回答所有问题的一个
  • 为什么无符号类型在arm cpu中效率更高?

    我正在阅读手臂手册并提出这个建议 但没有提到原因 为什么无符号类型更快 在 ARMv4 之前 ARM 没有对加载半字和有符号字节的本机支持 要加载有符号的字节 你必须LDRB然后对值进行符号扩展 LSL那就起来吧ASR它回落 这很痛苦所以c
  • 手臂 g++ 中缺少一些东西

    我安装了 CodeSourcery g 工具链并尝试编译一个简单的 hello world 程序 include
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • 将结构体偏移属性赋予汇编器

    如何将 C 结构体的偏移量发送到汇编代码 例如 在我的 C 代码中 typedef struct unsigned int a unsigned int b CMyStruct 我向 ASM 函数发送一个 CMyStruct 结构的指针 假
  • 使用 gnueabihf 为 ARMv6 构建

    我尝试为 ARMv6 构建应用程序 但失败了 我猜问题是工具链支持硬浮点 但 ARMv6 不支持 好吧 首先我设置 march armv6 编译失败 opt gcc linaro arm linux gnueabihf 4 8 2014 0
  • 使用 STM32 USB 设备库将闪存作为大容量存储设备

    我的板上有这个闪存IC 它连接到我的STM32F04 ARM处理器 处理器的USB端口可供用户使用 我希望我的闪存在通过 USB 连接到 PC 时被检测为存储设备 作为第一步 我在程序中将 USB 类定义为 MSC 效果很好 因为当我将主板
  • ARM架构中不同处理器模式下如何使用内核堆栈?

    据我了解 每个进程都有一个用户堆栈和内核堆栈 除此之外 ARM 架构中的每种模式都有一个堆栈 所以我想知道不同的堆栈和堆栈指针在 ARM 模式下如何工作 另外 何时会使用与进程关联的内核堆栈 何时会使用与进程关联的内核堆栈 当您进行系统调用
  • DSP 库 - RFFT - 奇怪的结果

    最近我一直在尝试在我的STM32F4 Discovery评估板上进行FFT计算 然后将其发送到PC 我已经调查了我的问题 我认为我对制造商提供的 FFT 函数做错了 我正在使用 CMSIS DSP 库 现在我一直在用代码生成样本 如果工作正
  • ARM Cortex A8 PMNC 读取在启用后也给出 0.. 有什么想法/建议吗?

    MODULE LICENSE GPL MODULE DESCRIPTION user mode access to performance registers int init arm init void unsigned int valu
  • C 嵌入式应用程序中 time() 函数的问题

    我在用time 在 ARM 微控制器上 处理器一到达此函数就会重新启动 奇怪的是 当我处于调试模式时 代码运行得很好 但一旦我想将其应用到独立模式 我就会遇到重置 我是否忽略了什么 这个功能有替代品吗 代码部分是这样的 include
  • 源和目标具有不同的 EABI 版本

    我正在尝试使用 ARM 工具链编译 so 文件 但是我不断收到这个错误 错误 源对象的 EABI 版本为 0 但目标对象的 EABI 版本为 5 我无法更改工具链中的任何内容 因为我必须使用给定的工具链 我以前从未见过这个错误 我使用了这个
  • 可以使用Visual Studio 2012构建ARM桌面程序吗?

    我正在使用 Visual Studio 2012 beta 我的桌面 win32 程序在 ARM 架构中编译得很好 升级到 Visual Studio 2012 RC 后 编译器无法工作并出现以下错误 不支持为 ARM 平台编译桌面应用程序
  • 如何在 Android 设备上运行 VS Code [重复]

    这个问题在这里已经有答案了 我有 Galaxy Tab S6 它具有替代笔记本电脑的很酷的功能 例如连接鼠标和键盘 但不幸的是它运行 Android 操作系统 并且没有很多开发应用程序可用于 Android 所以我想是否有一个选项可以在至少
  • 交叉编译 Qt 4.7 时出现“非法指令”

    我已经在这个问题上苦苦挣扎了一个多星期了 但仍然找不到解决方案 我正在尝试为 ARM 设备交叉编译 Qt 4 7 嵌入式开源版本 构建过程本身可以顺利完成 但生成的二进制文件似乎包含处理器无法理解的指令 构建主机是 i386 上的 Debi
  • ARM + gcc:不要使用一大块 .rodata 部分

    我想使用 gcc 编译一个程序 并针对 ARM 处理器进行链接时间优化 当我在没有 LTO 的情况下编译时 系统会被编译 当我启用 LTO 时 使用 flto 我收到以下汇编错误 错误 无效的文字常量 池需要更近 环顾网络 我发现这与我系统
  • 如何使用 Neon SIMD 将无符号字符转换为有符号整数

    如何转换变量的数据类型uint8 t to int32 t使用霓虹灯 我找不到执行此操作的任何内在因素 假设您想要将 16 x 8 位整数的向量转换为 4 个 4 x 32 位整数的向量 您可以通过首先解压缩为 16 位 然后再次解压缩为

随机推荐