谁会STM32单片机c语言编程300例,c语言程序

您当前的位置:&>&&>&&>&
高手带你分析STM32 的启动过程(写的不错)
当前的嵌入式应用程序开发过程里,并且C语言成为了绝大部分场合的最佳选择。如此一来main函数似乎成为了理所当然的起点&&因为C程序往往从main函数开始执行。但一个经常会被忽略的问题是:微控制器(单片机)上电后,是如何寻找到并执行main函数的呢?很显然微控制器无法从硬件上定位main函数的入口地址,因为使用C语言作为开发语言后,变量/函数的地址便由编译器在编译时自行分配,这样一来main函数的入口地址在微控制器的内部存储空间中不再是绝对不变的。相信读者都可以回答这个问题,答案也许大同小异,但肯定都有个关键词,叫&启动文件&,用英文单词来描述是&Bootloader&。
无论性能高下,结构简繁,价格贵贱,每一种微控制器(处理器)都必须有启动文件,启动文件的作用便是负责执行微控制器从&复位&到&开始执行main函数&中间这段时间(称为启动过程)所必须进行的工作。最为常见的51,AVR或MSP430等微控制器当然也有对应启动文件,但开发环境往往自动完整地提供了这个启动文件,不需要开发人员再行干预启动过程,只需要从main函数开始进行应用程序的设计即可。
话题转到微控制器,无论是keiluvision4还是IAR EWARM开发环境,公司都提供了现成的直接可用的启动文件,程序开发人员可以直接引用启动文件后直接进行C应用程序的开发。这样能大大减小开发人员从其它微控制器平台跳转至平台,也降低了适应微控制器的难度(对于上一代ARM的当家花旦ARM9,启动文件往往是第一道难啃却又无法逾越的坎)。
相对于ARM上一代的主流ARM7/ARM9内核架构,新一代Cortex内核架构的启动方式有了比较大的变化。ARM7/ARM9内核的控制器在复位后,CPU会从存储空间的绝对地址0x000000取出第一条指令执行复位中断服务程序的方式启动,即固定了复位后的起始地址为0x000000(PC = 0x000000)同时中断向量表的位置并不是固定的。而Cortex-M3内核则正好相反,有3种情况:
1、通过boot引脚设置可以将中断向量表定位于SRAM区,即起始地址为0x2000000,同时复位后PC指针位于0x2000000处;
2、通过boot引脚设置可以将中断向量表定位于FLASH区,即起始地址为0x8000000,同时复位后PC指针位于0x8000000处;
3、通过boot引脚设置可以将中断向量表定位于内置Bootloader区,本文不对这种情况做论述;
而Cortex-M3内核规定,起始地址必须存放堆顶指针,而第二个地址则必须存放复位中断入口向量地址,这样在Cortex-M3内核复位后,会自动从起始地址的下一个32位空间取出复位中断入口向量,跳转执行复位中断服务程序。对比ARM7/ARM9内核,Cortex-M3内核则是固定了中断向量表的位置而起始地址是可变化的。
有了上述准备只是后,下面以的2.02固件库提供的启动文件&stm32f10x_vector.s&为模板,对的启动过程做一个简要而全面的解析。
程序清单一:
;文件&stm32f10x_vector.s&,其中注释为行号
DATA_IN_ExtSRAM EQU 0 ;1
Stack_Size EQU 0x
AREA STACK, NOINIT, READWRITE, ALIGN = 3 ;3
Stack_Mem SPACE Stack_S4
__initial_5
Heap_Size EQU 0x
AREA HEAP, NOINIT, READWRITE, ALIGN = 3 ;7
Heap_Mem SPACE Heap_S9
PRESERVE8 ;12
IMPORT NMIE13
IMPORT HardFaultE14
IMPORT MemManageE15
IMPORT BusFaultE16
IMPORT UsageFaultE17
IMPORT SVCH18
IMPORT DebugM19
IMPORT PendSVC ;20
IMPORT SysTickH21
IMPORT WWDG_IRQH22
IMPORT PVD_IRQH23
IMPORT TAMPER_IRQH24
IMPORT RTC_IRQH25
IMPORT FLASH_IRQH26
IMPORT RCC_IRQH27
IMPORT EXTI0_IRQH28
IMPORT EXTI1_IRQH29
IMPORT EXTI2_IRQH30
IMPORT EXTI3_IRQH31
IMPORT EXTI4_IRQH32
IMPORT DMA1_Channel1_IRQH33
IMPORT DMA1_Channel2_IRQH34
IMPORT DMA1_Channel3_IRQH35
IMPORT DMA1_Channel4_IRQH36
IMPORT DMA1_Channel5_IRQH37
IMPORT DMA1_Channel6_IRQH38
IMPORT DMA1_Channel7_IRQH39
IMPORT ADC1_2_IRQH40
IMPORT USB_HP_CAN_TX_IRQH41
IMPORT USB_LP_CAN_RX0_IRQH42
IMPORT CAN_RX1_IRQH43
IMPORT CAN_SCE_IRQH44
IMPORT EXTI9_5_IRQH45
IMPORT TIM1_BRK_IRQH46
IMPORT TIM1_UP_IRQH47
IMPORT TIM1_TRG_COM_IRQH48
IMPORT TIM1_CC_IRQH49
IMPORT TIM2_IRQH50
IMPORT TIM3_IRQH51
IMPORT TIM4_IRQH52
IMPORT I2C1_EV_IRQH53
IMPORT I2C1_ER_IRQH54
IMPORT I2C2_EV_IRQH55
IMPORT I2C2_ER_IRQH56
IMPORT SPI1_IRQH57
IMPORT SPI2_IRQH58
IMPORT USART1_IRQH59
IMPORT USART2_IRQH60
IMPORT USART3_IRQH61
IMPORT EXTI15_10_IRQH62
IMPORT RTCAlarm_IRQH63
IMPORT USBWakeUp_IRQH64
IMPORT TIM8_BRK_IRQH65
IMPORT TIM8_UP_IRQH66
IMPORT TIM8_TRG_COM_IRQH67
IMPORT TIM8_CC_IRQH68
IMPORT ADC3_IRQH69
IMPORT FSMC_IRQH70
IMPORT SDIO_IRQH71
IMPORT TIM5_IRQH72
IMPORT SPI3_IRQH73
IMPORT UART4_IRQH74
IMPORT UART5_IRQH75
IMPORT TIM6_IRQH76
IMPORT TIM7_IRQH77
IMPORT DMA2_Channel1_IRQH78
IMPORT DMA2_Channel2_IRQH79
IMPORT DMA2_Channel3_IRQH80
IMPORT DMA2_Channel4_5_IRQH81
AREA RESET, DATA, READONLY ;82
EXPORT __V83
DCD __initial_85
DCD Reset_H86
DCD NMIE87
DCD HardFaultE88
DCD MemManageE89
DCD BusFaultE90
DCD UsageFaultE91
DCD SVCH96
DCD DebugM97
DCD PendSVC ;99
DCD SysTickH100
DCD WWDG_IRQH101
DCD PVD_IRQH102
DCD TAMPER_IRQH103
DCD RTC_IRQH104
DCD FLASH_IRQH105
DCD RCC_IRQH106
DCD EXTI0_IRQH107
DCD EXTI1_IRQH108
DCD EXTI2_IRQH109
DCD EXTI3_IRQH110
DCD EXTI4_IRQH111
DCD DMA1_Channel1_IRQH112
DCD DMA1_Channel2_IRQH113
DCD DMA1_Channel3_IRQH114
DCD DMA1_Channel4_IRQH115
DCD DMA1_Channel5_IRQH116
DCD DMA1_Channel6_IRQH117
DCD DMA1_Channel7_IRQH118
DCD ADC1_2_IRQH119
DCD USB_HP_CAN_TX_IRQH120
DCD USB_LP_CAN_RX0_IRQH121
DCD CAN_RX1_IRQH122
DCD CAN_SCE_IRQH123
DCD EXTI9_5_IRQH124
DCD TIM1_BRK_IRQH125
DCD TIM1_UP_IRQH126
DCD TIM1_TRG_COM_IRQH127
DCD TIM1_CC_IRQH128
DCD TIM2_IRQH129
DCD TIM3_IRQH130
DCD TIM4_IRQH131
DCD I2C1_EV_IRQH132
DCD I2C1_ER_IRQH133
DCD I2C2_EV_IRQH134
DCD I2C2_ER_IRQH135
DCD SPI1_IRQH136
DCD SPI2_IRQH137
DCD USART1_IRQH138
DCD USART2_IRQH139
DCD USART3_IRQH140
DCD EXTI15_10_IRQH141
DCD RTCAlarm_IRQH142
DCD USBWakeUp_IRQH143
DCD TIM8_BRK_IRQH144
DCD TIM8_UP_IRQH145
DCD TIM8_TRG_COM_IRQH146
DCD TIM8_CC_IRQH147
DCD ADC3_IRQH148
DCD FSMC_IRQH149
DCD SDIO_IRQH150
DCD TIM5_IRQH151
DCD SPI3_IRQH152
DCD UART4_IRQH153
DCD UART5_IRQH154
DCD TIM6_IRQH155
DCD TIM7_IRQH156
DCD DMA2_Channel1_IRQH157
DCD DMA2_Channel2_IRQH158
DCD DMA2_Channel3_IRQH159
DCD DMA2_Channel4_5_IRQH160
AREA |.text|, CODE, READONLY ;161
Reset_Handler PROC ;162
EXPORT Reset_H163
IF DATA_IN_ExtSRAM == 1 ;164
LDR R0,= 0x5
LDR R1,= 0x6
STR R0,[R1] ;167
LDR R0,= 0x ;168
LDR R1,= 0x9
STR R0,[R1] ;170
LDR R0,= 0x44BB44BB ;171
LDR R1,= 0x2
STR R0,[R1] ;173
LDR R0,= 0xBBBBBBBB ;174
LDR R1,= 0x5
STR R0,[R1] ;176
LDR R0,= 0xB44444BB ;177
LDR R1,= 0x8
STR R0,[R1] ;179
LDR R0,= 0xBBBBBBBB ;180
LDR R1,= 0x1
STR R0,[R1] ;182
LDR R0,= 0x44BBBBBB ;183
LDR R1,= 0x4
STR R0,[R1] ;185
LDR R0,= 0xBBBB
LDR R1,= 0x7
STR R0,[R1] ;188
LDR R0,= 0x44BBBBBB ;189
LDR R1,= 0x0
STR R0,[R1] ;191
LDR R0,= 0x2
LDR R1,= 0x3
STR R0,[R1] ;194
LDR R0,= 0x5
LDR R1,= 0xA6
STR R0,[R1] ;197
LDR R0,= 0x8
LDR R1,= 0xA9
STR R0,[R1] ;200
ENDIF ;201
IMPORT __202
LDR R0, =__203
BX R0 ;204
ALIGN ;206
IF :DEF:__MICROLIB ;207
EXPORT __initial_208
EXPORT __heap_209
EXPORT __heap_210
IMPORT __use_two_region_212
EXPORT __user_initial_213
__user_initial_214
LDR R0, = Heap_M215
LDR R1, = (Stack_Mem + Stack_Size) ;216
LDR R2, = (Heap_Mem + Heap_Size) ;217
LDR R3, = Stack_M218
BX LR ;219
ALIGN ;220
ENDIF ;221
ENDIF ;223
如程序清单一,的启动代码一共224行,使用了汇编语言编写,这其中的主要原因下文将会给出交代。现在从第一行开始分析:
? 第1行:定义是否使用外部SRAM,为1则使用,为0则表示不使用。此语行若用C语言表达则等价于:
#define DATA_IN_ExtSRAM 0
? 第2行:定义栈空间大小为0x个字节,即1Kbyte。此语行亦等价于:
#define Stack_Size 0x
? 第3行:伪指令AREA,表示
? 第4行:开辟一段大小为Stack_Size的内存空间作为栈。
? 第5行:标号__initial_sp,表示栈空间顶地址。
? 第6行:定义堆空间大小为0x个字节,也为1Kbyte。
? 第7行:伪指令AREA,表示
? 第8行:标号__heap_base,表示堆空间起始地址。
? 第9行:开辟一段大小为Heap_Size的内存空间作为堆。
? 第10行:标号__heap_limit,表示堆空间结束地址。
? 第11行:告诉编译器使用THUMB指令集。
? 第12行:告诉编译器以8字节对齐。
? 第13&81行:IMPORT指令,指示后续符号是在外部文件定义的(类似C语言中的全局变量声明),而下文可能会使用到这些符号。
? 第82行:定义只读数据段,实际上是在CODE区(假设从FLASH启动,则此中断向量表起始地址即为0x8000000)
? 第83行:将标号__Vectors声明为全局标号,这样外部文件就可以使用这个标号。
? 第84行:标号__Vectors,表示中断向量表入口地址。
? 第85&160行:建立中断向量表。
? 第161行:
? 第162行:复位中断服务程序,PROC&ENDP结构表示程序的开始和结束。
? 第163行:声明复位中断向量Reset_Handler为全局属性,这样外部文件就可以调用此复位中断服务。
? 第164行:IF&ENDIF为预编译结构,判断是否使用外部SRAM,在第1行中已定义为&不使用&。
? 第165&201行:此部分代码的作用是设置FSMC总线以支持SRAM,因不使用外部SRAM因此此部分代码不会被编译。
? 第202行:声明__main标号。
? 第203&204行:跳转__main地址执行。
? 第207行:IF&ELSE&ENDIF结构,判断是否使用DEF:__MICROLIB(此处为不使用)。
? 第208&210行:若使用DEF:__MICROLIB,则将__initial_sp,__heap_base,__heap_limit亦即栈顶地址,堆始末地址赋予全局属性,使外部程序可以使用。
? 第212行:定义全局标号__use_two_region_memory。
? 第213行:声明全局标号__user_initial_stackheap,这样外程序也可调用此标号。
? 第214行:标号__user_initial_stackheap,表示用户堆栈初始化程序入口。
? 第215&218行:分别保存栈顶指针和栈大小,堆始地址和堆大小至R0,R1,R2,R3寄存器。
? 第224行:程序完毕。
以上便是的启动代码的完整解析,接下来对几个小地方做解释:
1、 AREA指令:伪指令,用于定义代码段或数据段,后跟属性标号。其中比较重要的一个标号为&READONLY&或者&READWRITE&,其中&READONLY&表示该段为只读属性,联系到的内部存储介质,可知具有只读属性的段保存于FLASH区,即0x8000000地址后。而&READONLY&表示该段为&可读写&属性,可知&可读写&段保存于SRAM区,即0x2000000地址后。由此可以从第3、7行代码知道,堆栈段位于SRAM空间。从第82行可知,中断向量表放置与FLASH区,而这也是整片启动代码中最先被放进FLASH区的数据。因此可以得到一条重要的信息:0x8000000地址存放的是栈顶地址__initial_sp,0x8000004地址存放的是复位中断向量Reset_Handler(使用32位总线,因此存储空间为4字节对齐)。
2、 DCD指令:作用是开辟一段空间,其意义等价于C语言中的地址符&&&。因此从第84行开始建立的中断向量表则类似于使用C语言定义了一个指针数组,其每一个成员都是一个函数指针,分别指向各个中断服务函数。
3、标号:前文多处使用了&标号&一词。标号主要用于表示一片内存空间的某个位置,等价于C语言中的&地址&概念。地址仅仅表示存储空间的一个位置,从C语言的角度来看,变量的地址,数组的地址或是函数的入口地址在本质上并无区别。
4、第202行中的__main标号并不表示C程序中的main函数入口地址,因此第204行也并不是跳转至main函数开始执行C程序。__main标号表示C/C++标准实时库函数里的一个初始化子程序__main的入口地址。该程序的一个主要作用是初始化堆栈(对于程序清单一来说则是跳转__user_initial_stackheap标号进行初始化堆栈的),并初始化映像文件,最后跳转C程序中的main函数。这就解释了为何所有的C程序必须有一个main函数作为程序的起点&&因为这是由C/C++标准实时库所规定的&&并且不能更改,因为C/C++标准实时库并不对外界开发源代码。因此,实际上在用户可见的前提下,程序在第204行后就跳转至.c文件中的main函数,开始执行C程序了。
至此可以总结一下的启动文件和启动过程。首先对栈和堆的大小进行定义,并在代码区的起始处建立中断向量表,其第一个表项是栈顶地址,第二个表项是复位中断服务入口地址。然后在复位中断服务程序中跳转&&C/C++标准实时库的__main函数,完成用户堆栈等的初始化后,跳转.c文件中的main函数开始执行C程序。假设被设置为从内部FLASH启动(这也是最常见的一种情况),中断向量表起始地位为0x8000000,则栈顶地址存放于0x8000000处,而复位中断服务入口地址存放于0x8000004处。当遇到复位信号后,则从0x处取出复位中断服务入口地址,继而执行复位中断服务程序,然后跳转__main函数,最后进入mian函数,来到C的世界。谁会STM32单片机,c语言程序_百度知道
谁会STM32单片机,c语言程序
我有更好的答案
不懂单片机内部资源,下载对应的头文件就可以,用c语言编程了是吗?
采纳率:100%
你有什么问题 可以问我
为您推荐:
其他类似问题
您可能关注的内容
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。查看: 403|回复: 3
如果用C语言来写的STM32程序,主要用到了那部分的知识 求大佬指教
如果用C语言来写的STM32程序,主要用到了那部分的知识
c语言部分,全部用到了,建议将唐浩强的c语言好好学习 ,而且建议先将51单片机学学,整体思路和流程
指针,结构体,宏定义,if,while还有位运算(左右移,与或非等)
主要是结构体
Powered bystm32的程序用c语言写的求助_百度知道
stm32的程序用c语言写的求助
sprintf(report, &ADC1 = %.1f cm
ADC2= %.1f cm\r\n&, (float)(leftInfrad)/10, (float)(rightInfrad)/10);什么意思这个格式,看不懂
我有更好的答案
将leftInfrad和rightInfrad转成浮点数, 除以10后, 保留一位小数输出到report字符串中。比如 如果leftInfrad=23
rightInfrad=18那么 执行后, report字符串为&ADC1 = 2.3 cm ADC2= 1.8 cm\r\n&
请问sprintf(字符,内容1+输出格式,...内容n+输出格式,内容1的值...内容n的值)这个函数的格式可以这样理解吗?以后我可以直接按照这样理解用吗?
可以你应该用过printf吧,其实这两个很像的
谢谢啊,初学者一个,被好多没看过的格式搞得好懵逼
软件工程师
为您推荐:
其他类似问题
您可能关注的内容
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。网站已改版,请使用新地址访问:
C 用stm32单片机使用C语言写的一个简单的五线四相的步进电机控制程序 SCM 开发 274万源代码下载- www.pudn.com
&文件名称: C& & [
& & & & &&]
&&所属分类:
&&开发工具: C++
&&文件大小: 317 KB
&&上传时间:
&&下载次数: 0
&&提 供 者:
&详细说明:用stm32单片机使用C语言写的一个简单的五线四相的步进电机控制程序-A stepping motor using C language used to write a simple microcontroller stm32 five-wire four-phase control program
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&C&&.\JLinkArm_HC6800-EM3.ini&&.\Lst&&.\...\LED灯闪烁.map&&.\...\STM3210B-EVAL.map&&.\...\STM3210E-EVAL.map&&.\...\stm32f10x_vector.lst&&.\...\二进制加法.map&&.\...\步进电机.map&&.\Obj&&.\...\main.crf&&.\...\main.d&&.\...\main.o&&.\...\stm32f10x_it.crf&&.\...\stm32f10x_it.d&&.\...\stm32f10x_it.o&&.\...\stm32f10x_vector._ia&&.\...\stm32f10x_vector.o&&.\...\步进电机.axf&&.\...\步进电机.hex&&.\...\步进电机.htm&&.\...\步进电机.lnp&&.\...\步进电机.plg&&.\...\步进电机.sct&&.\...\步进电机.tra&&.\Project.Uv2.bak&&.\Project.opt.bak&&.\Project.uvopt&&.\Project.uvproj&&.\Project_HC6800-EM3.dep&&.\Project_Opt.Bak&&.\Project_STM3210E-EVAL.dep&&.\Project_Uv2.Bak&&.\Project_uvopt.bak&&.\main.c&&.\note.txt&&.\platform_config.h&&.\readme.txt&&.\stm32f10x_conf.h&&.\stm32f10x_it.c&&.\stm32f10x_it.h&&.\stm32f10x_vector.s
&输入关键字,在本站274万海量源码库中尽情搜索:

我要回帖

更多关于 单片机c语言教程 的文章

 

随机推荐