本文共 2772 字,大约阅读时间需要 9 分钟。
说了那么多,我们终于开始写代码了.毫不例外,我们从世界上最著名的程序"helloword"开始,硬件的"helloword"就是点亮一个LED.
硬件原理图:
从原理图看出,LED (D1)连接电源和地,上电就亮. LED D2连接VCC和PC13,所以我们只要给PC13引脚一个低电平就可以点亮这个LED.
准备点灯
俗话说,让我点亮一个LED我就能上天. 看把你能的,LED 可不是那么好点的,要准备准备.
如果你学过51,你会告诉我点灯很容易.
如果你学过STM32,也许你会告诉我很容易.(为什么我说也许?因为我知道你心虚,你用的是别人的库吧?你有很多不明白的地方吧.哈哈哈)
今天我们就从头来,明明白白的点一回灯.
其实这个STM32点灯的却不是那么容易,因为在真实点灯之前有很多配置,往往这些配置是最让人头疼的.
这也是用库编程的问题所在:虽然你用了库点亮了LED灯,干了很多别的事情,但是有些事情还是模模糊糊不清楚.
扯远了,其实那些烦人的配置是用来配置时钟的,STM32这样设计也是有原因的:默认所有外设时钟关闭,使用的时候再开启,这样可以省电啊.有地方省,就有地方多付出,比如芯片设计人员和软件开发人员--我们.幸好STM32有默认内部时钟,虽然不咋地,但是能用,我们先凑合着用内部时钟点亮我们的LED.
点灯
先使能portC的时钟(我们要用PC13),然后将PC13设置为输出模式.
while(1)循环设置PC13高低电平,就可以看见LED灯一闪一闪的了
/* main.c */#define RCC_BASE 0x40021000#define RCC_CR (*(volatile unsigned long *)(RCC_BASE))#define RCC_APB2ENR (*(volatile unsigned long *)(RCC_BASE+0x18))#define GPIOC_BASE 0x40011000#define GPIOC_CRH (*(volatile unsigned long *)(GPIOC_BASE+0x04))#define GPIOC_ODR (*(volatile unsigned long *)(GPIOC_BASE+0x0c))int main(){ int i; RCC_APB2ENR = 1<<4; //portC 时钟使能 GPIOC_CRH = 3<<20; // pin13 输出模式 GPIOC_ODR = 0; while(1){ GPIOC_ODR |= 1<<13; //pin13 高电平 for(i=0;i<1000000;i++); GPIOC_ODR &= ~(1<<13); //pin13 低电平 for(i=0;i<1000000;i++); } return 0;}
好像本章应该结束了?可是想想还有很多疑问:为什么从mian()函数开始执行?怎么编译成APP.bin?
为什么从mian()函数开始执行?
很多写应用的人往往会忽略忽这点,因为平时的应用都是从main开始的所以就理所当然的认为STM32也认识main().
要回答这个问题,这就要说说cortexM3的启动流程(复位流程).
如上图,CPU一上电就从0x00000000地址处取一个值赋给MSP(R13)寄存器.然后从接下来的一个32bit对齐的地址0x00000004处读取第一条要执行的指令执行.
那么我们的程序怎么保证0x00000004处就是main()函数呢?
/* start.S */.text.globl _start _start: .word 0x20000000+20480 /*sram form 0x20000000,size 20K*/ .word main /*跳转到main函数*/
从_start开始,第一个 .word 后面就是放入MSP中的值,因为.word占用4个字节所有.word main 就0x00000004处了.
这就保证了程序一上电就执行main()函数.
其实,入口也不一定非要是main()函数,你写exit()也是可以的,只要你愿意,main只是约定俗成.
怎么编译?
//将start.S编译为start.o 但是不链接arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -c start.S -o start.o//将main.c编译为main.o 但是不链接arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -c main.c -o main.o//将start.o 和start.o 链接成nuttx. 第一个字节放在0x00000000 //这样main就在0x00000004arm-none-eabi-ld -Ttext=0x00000000 start.o main.o -o nuttx//最后转换格式,确保CPU可以正常运行arm-none-eabi-objcopy -O binary -S nuttx nuttx.bin
上面解释的很详细了,就不再多说,可是每次编译都敲这么多命令也太麻烦了,干脆写一个脚本(针对make的Makefle)
# file :MakefileAll: arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -c start.S -o start.o arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -c main.c -o main.o arm-none-eabi-ld -Ttext=0x08000000 start.o main.o -o nuttx arm-none-eabi-objcopy -O binary -S nuttx nuttx.bin arm-none-eabi-objdump -D -m arm nuttx > nuttx.disclean: -rm *.o nuttx*flash: sudo stm32flash -w nuttx.bin -v -g 0 /dev/ttyUSB0
这样创建led目录,创建3个文件
main.c Makefile start.S 内容如上文.
这样以后编译烧写就方便多了.
//编译PC#make//清除编译产生的文件PC#make clean//烧写到STM32PC#make flash
576648661@qq.com
- 微信号:find_xiaohei
- 名称:找小黑
转载地址:https://blog.csdn.net/yyyyyyyyyywwwwwwwwww/article/details/85932437 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!