前言
在嵌入式开发过程中,有时候为了追求代码性能与效率不得不采用汇编语言来编写代码,但是汇编代码在阅读时表现不如C语言友好,本节给大家介绍一种新的方法,关键代码用汇编语言时行实现,然后用C语言时行接封装,用C语言与汇编语言混合编程的方式,在实现代码性能与运行效率的同时,又较方便阅读与理解决代码逻辑。
本节将以STM32 MCU平台作为展示,教大家如何实现编码与C混合编程,本节实现方式是在《STM32 进阶教程 4 - 软件实现高精度延时 2》基础上将一些C程序代码用汇编代码实现,最终的效果与《STM32 进阶教程 4 - 软件实现高精度延时 2》节一样,学会了stm32本节内容,在51,AVR,DSP等硬件平台同样适用。
示例详解
基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 STM32F103c8t6, 使用stm32cubemx 工具自动产生的配置工程,使用KEIL5编译代码。
本示例所用的最小系统板原理图:
-
- 关于CUBEMX工具及KEIL工具的操作将不再细讲,如果还有不熟悉的可以查看之前的教程文档。下面直接介绍工程配置:
-
-
- 系统时钟树
-
-
-
- 定时器配置
-
-
-
- 引脚配置
-
-
-
- 中断配置(保持默认)
-
-
- 工程代码
- 将事先准备好的delay.c和delay.h文件加到工程中,
- 工程代码
Delay.h文件放在INC文件夹下即可。
-
-
- 其实在Keil mdk 环境中STM32的很多底层代码的实现都是汇编都言,比如那个经典的启动文件“startup_stm32fxxxx.s”当然这个文只是定义了一些中断函数常量,堆和栈大小以及Reset_Handler的实现等。
-
不同于启动文件外,本节要讲的是C语言中包含汇码代码,这就需要用到关键字“__ASM” 或“__asm”关于__asm关键字的用法有如下说明:
__asm
这个关键字将信息从编译器传递给ARM汇编程序armasm。这个关键字的确切作用取决于它的使用。
嵌入式汇编/ 内联汇编:
关键字__asm可以将内联程序集合并到函数中。例如:
int add(int i, int j)
{
int res;
__asm
{
ADD res, i, j
}
return res;
}
指定汇编标签:
关键字__asm可以为C程序变量指定程汇编变量名。例如::
int count __asm__("count_v1"); // 在汇编代码中导出的变量count_v1,而不是count
命名寄存器变量:
关键字__asm可以声明一个命名的寄存器变量。例如:
register int foo __asm("r0"); // 变量foo 实际上就是寄存器r0. 类似的操作在”Cmsis_armcc.h”中较多见。
关于__asm关键中,本节主要用到的是 “嵌入式汇编/ 内联汇编”功能。
-
-
- 修改Delay.C中delay_us函数的部分实现:
-
将其延时1us及2us的操作用汇编指令nop来实现
-
-
- 在main.c 中加入如下图所示代码
-
-
- 编译工程,下载程序看效果,首先仿真运行代码,可以发现变量C = 1+2 = 3 结果正确,用汇编指令成功实现加法:
让程序全速运行,查看PC13引脚上的波形,
进入软件仿真可以看到Delay_us中函数1us及2us的函数对应汇编代码如下:
通过上面的实例,我们已基本学会基于keil MDK平台的stm32 中C程序中嵌入汇编的实现方法,那么如么在汇编程序中谳用C函数接口呢,这个其实更简单,可以参看stm32的官方启动文件“startup_stm32fxxxx.s” 它就是一个典型的汇编程序调用C函数的实现。最后更多关于__asm的说明可以查看KEIL mdk的帮助文档。:
OK,本期实验完成!下期见!同时如果大家有什么疑问或是有想了解的其它内容,也欢迎大家留言!!最后喜欢这个公众号的同学们记得加关注了,会有不定期技术干货推出!!
文中源码资料下载,在公众号里给十三发消息:
下载|STM32进阶教程 6
关注十三公众号