GD32 LED例程解析 叫例程解析有点大了,就是大概分析下程序实现流程和思路。一个帖子发不完,见附件吧。剩下的一些事对延时函数配置中断优先级函数和位带操作的大概说下。有点简单,高手误见怪。 一. 启动文件 程序必然从启动文件开始运行了,上电复位根据选择启动模式,然后就进入相应的地址运行程序,烧写好的正常程序一般都是从flash运行的,启动文件startup_stm32f10x_md.s是个汇编文件,汇编我也不怎么懂,大概看下知道怎么回事就行了。设置堆栈,定义向量表,预先定义好了一些中断向量表,都是虚函数,内容需要自己实现,用到那部分重新定义下相关的函数就行了,只是ARM规定好了函数名字。下面一段话从ppt摘过来的,但是其实在启动文件里没有设置系统时钟频率,网上的东西,不可全信的,包括我的**,但是知道个思路就行了,自己慢慢琢磨才有意思,才能学习到东西的。 • 启动代码功能总结: • 1)堆和栈的初始化; • 2)向量表定义; • 3)地址重映射及中断向量表的转移; • 4)设置系统时钟频率; • 5)中断寄存器的初始化; • 6)进入C应用程序。 说白了就是启动设置个C语言运行需要的环境,然后跳转到main函数。具体我就不细说了,免的误导大家,附一个网上下载的Cortex-M3启动代码分析.ppt,其实这部分不需要知道的太细的,知道有这么回事就行了。ARM公司推出thumb2指令集有一个重要的好处就是可以完全甩开汇编。当然不是说处理器不运行汇编,只是一般的程序员不需要写汇编代码,完全用C语言就能达到很好的效果,当然,如果有精力有时间学习下汇编对处理器的理解会更深一步,不建议初学去抠汇编,也别提效率的事,这年头处理器时间要比人的时间便宜好多,嫌运行的不快只能说明你选的处理器不够,优化你的C语言也比用汇编省事很多。而且,一般用户使用汇编写出来的代码真不一定有现代化的智能编译器编译的汇编代码效率高。啰嗦了很多,嗯。 二. main.c 以下是LED例程的主函数(main.c文件)。很显然前面是头文件包含,接着一个main函数,初始化,然后while(1)死循环,这是嵌入式程序的典型流程。这里把led,延时,还有系统相关的函数都在其它文件里实现,然后主文件只需要包含相关的头文件就可以了,这样主要为了简洁通用,条理也清晰好多。 #include"led.h" #include"delay.h" #include"sys.h" intmain(void) { SystemInit(); //系统时钟初始化为72MSYSCLK_FREQ_72MHz delay_init(72); //延时函数初始化 NVIC_Configuration();//设置NVIC中断分组2:2位抢占优先级,2位响应优先级 LED_Init(); //LED端口初始化 while(1) { LED0=0; // 这里使用了位带操作,也可以使用GPIO_ResetBits(GPIOA,GPIO_Pin_8); LED1=1; // 也可以使用 GPIO_SetBits(GPIOD,GPIO_Pin_2); delay_ms(300); LED0=1; // 也可以使用 GPIO_SetBits(GPIOA,GPIO_Pin_8); LED1=0; // 也可以使用 GPIO_ResetBits(GPIOD,GPIO_Pin_2) ; delay_ms(300); } } SystemInit()函数主要填写RCC寄存器。使能需要的时钟源,设置时钟,基本上就是设置使用外部8M晶振,PLL倍频到72M作为系统时钟。啰嗦下,STM32最高稳定运行频率是72Mhz,但是GD32最高运行频率是108Mhz,由于使用的库文件里运行频率什么的都用宏定义好了,没有108Mhz的选项,以下system_stm32f10x.c中的SetSysClock函数。如果要设置系统运行到108M,下载GD32修改的版本。增加了108M的选项。还有,如果需要使用到USB的话,因为没有单独的USB PLL,USB又必须运行在48Mhz,USB使用系统PLL进行分频。STM32可以设置分频系数为1或者1.5,就是说系统可以运行在48Mhz或者72Mhz,GD32增加了2和2.5的寄存器定义。但是48*2.5=120Mhz,不是推荐的稳定运行状态。所以如果要使用USB最高运行频率是96M,108Mhz下USB不能使用,时钟是乱的。 static void SetSysClock(void) {#ifdef SYSCLK_FREQ_HSE SetSysClockToHSE(); #elif defined SYSCLK_FREQ_24MHz SetSysClockTo24(); #elif defined SYSCLK_FREQ_36MHz SetSysClockTo36(); #elif defined SYSCLK_FREQ_48MHz SetSysClockTo48(); #elif defined SYSCLK_FREQ_56MHz SetSysClockTo56(); #elif defined SYSCLK_FREQ_72MHz SetSysClockTo72(); #elif defined SYSCLK_FREQ_108MHz SetSysClockTo108(); //GD32修改增加选项。 #endif } 三.
|