STM32F103VET6学习(1)

一.前言

我是按照STM32售方光盘中的资料《玩转STM32F10x》(.pdf)来学习的,前面的基本原理看了好几天,因为有点微机原理的底子,所以有些内容看起来还觉得不是特别难。几天后,终于看到了GPIO的这节的LED点亮,我心里想着终于可以有一个上手实践的东西可以做了。谁知道有很多问题一个接一个,下来就逐一说下,给自己看看做个记录也好。

二.问题陈述与对应的解决过程以及衍生的新的问题以及最后的解决

  1. 参考着pdf,我写的第一个程序如下:
#include"stm32f10x.h"
int main(void)
{
	RCC_APB2ENR |= (1<<3);    //开启时钟
	GPIOB_CRL &= ~( 0X0F << (4*0));  //清空控制PB0的端口位
	GPIOB_CRL |= (1<<4*0);
	GPIOB_ODR &= ~(1<<0);
	while(1);
}
//骗过编译器有这样一个函数,不报错
void SystemInit(void)
{
}

这就是第一个程序,运行后报错:缺少core_cm3.h文件,于是我找到这个文件把它和与它在同一目录下的core_cm3.c文件也一同copy到了报错的目录下,重新运行,这个错倒是没了,不过又出来了三个错,就是上方代码中的:GPIOB_CRL、GPIOB_ODR和RCC_APB2ENR 都是undefined,没定义。很离谱啊,我调用的头文件中有这几个的定义啊(但是我没有去看头文件里面的代码,偷懒了)。于是我百度,直到刚才前几个小时,我就想:既然它说我没定义,按我就给它定义呗!

2.定义后的代码添加了如下宏定义内容:

#define PERIPH_BASE ((unsigned int)0x40000000)
#define APB2PERIPH_BASE (PERIPH_BASE+0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
#define GPIOB_BASE (APB2PERIPH_BASE+0X0C00)

#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE + 0X00)
#define GPIOB_CRH *(unsigned int*)(GPIOB_BASE + 0X04)
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE + 0X0C)

#define RCC_BASE *(unsigned int*)(AHBPERIPH_BASE + 0X1000)
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE + 0X18)

让我高兴但是也迷乱的就是在写前四行基址定义的时候,有几个警告,说的是这几个宏已经定义过了(这里画个重点,后面还要提起)。于是我就写了后面的内容,好了,刚才没定义的错给解决了,然后又出来了一个错:__main ,这个文件/向导找不到或者冲突。百度之后,很多类似问题都有ADS这个关键词,将它卸载,环境变量删除后就好了。我想来想去,觉得ADS很熟悉,最后终于想起这学期学了个嵌入式操作系统的皮毛,但是老师当时让安装了ADS这个软件,想了下,以后也不会再去用它了,毕竟也比较老了,就果断找到其目录删除并卸载,然后再把环境变量删除。这里我肯定我是没有删错的,因为当时我建文件夹的名字我都是有注意的,所以哪个文件在哪里我都很清楚,但是…

3.这下子刚才的错没有了,但是!又出来了30个Errors!我想着应该是ADS目录下的有些文件被keil5使用了,但是我真的不想再去找他并恢复了,因为ADS的环境变量我刚删了,所以重来吧,我觉得缺少的配置在重新安装过程中会自己完成的。
于是我毅然重来,把Keil5卸载重装了一次,然后破解,设置Debug和各项配置,添加pack,一套走下来,十来分钟就完了。
将刚才的程序复制(这就要提到刚才说的宏的问题了),我没写那几行基址定义的宏,于是它又报错了,后面的几个宏涉及的宏我没有定义,来来回回操作了一会儿,我决定还是把它定义下吧。另外,我在“魔术棒”选项卡里进行了如下设置,添加了这个Include Path,他在固件库里:
Include Paths
这个Path里面我主要想要的就是stm32f10x.h这个头文件,这样确保我导入头文件的这句代码是有效地,以防报错说找不到我的头文件。
此外,我把core_cm3.h文件也放在了我的工程文件目录下,之后再次运行,终于!!!见图:

结果
4.虽然我看pdf后面讲到固件库主要还是要自己来写的,因为纯依靠寄存器是容易出错且不好控制的。但是解决了这个bug我还是很开心的,至此在stm32上遇到的第一个非技术类的问题得到了解决!在下面附上这次的全部代码,其功能是点亮一个LED,具体为推挽式输出,速率为10MHz,对应的为PB0口的设置(这也是代码里都写得GPIOB的原因)

#include"stm32f10x.h"

#define PERIPH_BASE ((unsigned int)0x40000000)

#define APB2PERIPH_BASE (PERIPH_BASE+0x10000)

#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)

#define GPIOB_BASE (APB2PERIPH_BASE+0X0C00)


//定义GPIO寄存器地址并强制转换为指针
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE + 0X00)
#define GPIOB_CRH *(unsigned int*)(GPIOB_BASE + 0X04)
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE + 0X0C)

//RCC外设基地址
#define RCC_BASE *(unsigned int*)(AHBPERIPH_BASE + 0X1000)
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE + 0X18)

int main(void)
{
		RCC_APB2ENR |= (1<<3);  
		GPIOB_CRL &= ~( 0X0F << (4*0)); 
		GPIOB_CRL |= (1<<4*0);
		GPIOB_ODR &= ~(1<<0);
		while(1);
}
void SystemInit(void)
{
}

该工程下的文件结构如下,其中startup_stm32f10x_hd.s是用汇编语言写的“启动文件”,即执行代码是先从这里开始,之后才进入C的世界执行自己写的main.c中的代码。stm32f10x.h是我自己建立的头文件,用于存放寄存器映射的代码,暂时是空的,没用。
结构
这次也没什么技术性的问题,但我就是做个记录,有人可能会用到吧,毕竟每次有问题去百度时,对于一个问题,百度里网友给出n种情况与解法,但我觉得自己的总是第n+1种问题,自己时常莫名其妙的就解决了。
所以做个记录,本次,完结!

三.新的问题与解决(最终方案)

1.问题回顾
上面的一和二的内容是昨天(2020.1.18)完成的,但是由于当时晚上比较晚了,所以没有用板子测试。今天(2020.1.19)中午重新运行时,Traslate没有错,但是在Build时就又出错了:找不到__main.h了。昨晚好着呢呀,就待机了一晚上就六亲不认了。由于我还没有测试板子效果,因此自然也很有耐心去把这个问题再看看,这时候百度真的没用了。
在之前的程序里,我加的头文件都是这样写的:

#include"stm32f10x.h"

我还给里面工程同目录下建立了一个stm32f10x.h头文件,作用之前说过了,但是目前它没用。但是,出来了一个stm32f10x.h头文件在main.c文件的子目录下,我双击它,里头是空的。所以我把它删了。并且把头文件的调用改成了如下形式:

#include<stm32f10x.h>

诶,也是神奇哈,Build之后,那个错没了,同时,出来了一个新错误,缺少core_cm3.h文件,于是我又试探性的把头文件调用的代码又改成了最开始的双引号括起来,然后出现了恶性循环,又来了。
最后,我找到core_cm3.h文件和stm32f10x.h文件,共同放在main.c文件的相同目录下,然后Translate,没错;Build,没错!最后,Load加载,烧录到板子上,原来我还好奇要点亮的LED到底在哪儿,看了许久的原理图以及拿着手电筒找板子的LED,后来发现下图中的共阳接法的三个LED就是同一个发光二极管D3,该说自己什么好呢?
led
代码到了板子上后,D3点亮,颜色为绿色,我最“爱”的颜色。
2.代码注意
在经历了上面的过程后,我大致对所谓的地址和寄存器等的东西有了自己的认知了。
(1)在运行成功后,工程文件结构发生了新的变化,如下:
Project
system_stm32f10x.h文件图标上的锁表示该文件在此为只读,不可写。
(2)代码内容(main.c文件)
在stm32f10x.h文件正式“过门”后,main.c文件对它进行调用时就不会出现调用无效的问题了。可以在stm32f10x.h文件的代码中使用ctrl+F,然后搜索之前定义的基址的宏名,都是可以找到的,这说明我们不需要再去重新定义了,而且如果定义了,运行后会报错:incompetible redefined …,意思就是我们定义这个为重复定义且和已定义的不兼容。所以之前的基址的定义就可以不要了,因为头文件中已经有了。下面是修改之后的代码,为了与之前的形成对比,我把之前定义的但是在此又不需要的给注释了:

#include"stm32f10x.h"
/*总线基地址(第一条总线)*/
//#define PERIPH_BASE ((unsigned int)0x40000000)

/*第二三条总线的基地址*/
//#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000)
//#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000)

/*GPIO基地址*/
//#define GPIOB_BASE (APB2PERIPH_BASE + 0X0C00)

/*RCC外设基地址*/
//#define RCC_BASE *(unsigned int*)(AHBPERIPH_BASE + 0X1000)

/*定义GPIO寄存器地址,强制转换位指针*/
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE + 0X00)
#define GPIOB_CRH *(unsigned int*)(GPIOB_BASE + 0X04)
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE + 0X0C)
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE + 0X18)

int main(void)
{
		RCC_APB2ENR |= (1<<3);  //开启时钟
		GPIOB_CRL &= ~( 0X0F << (4*0));  //清空控制PB0的端口位
		GPIOB_CRL |= (1<<4*0);  // 配置 PB0 为通用推挽输出,速度为 10M
		GPIOB_ODR &= ~(1<<0);  //PB0输出低电平(因为LED是共阳极接法)
		while(1);
}
void SystemInit(void)
{
}

四.问题总结

对之前的问题,我总结如下几步解决方法,试过后应该就都能解决。
(1)先看看电脑上是否有Keil4,如果有,在安装Keil5时,不要把它们放在同一个根目录下,避免版本的部分配置产生冲突。
(2)电脑上是否有ADS软件或是否安装过ADS软件。因为ADS和Keil5都是使用ARM公司的芯片技术,所以会产生冲突。将ADS的环境变量删除,卸载ADS,之后开始安装Keil5。
(3)新建一个工程,建立好main.c文件。在固件库中找到core_cm3.h文件(在CoreSupport文件夹内)和startup_stm32f10x_hd.s文件(该文件的路径在我的电脑中的路径如下,可以参考)

D:\STM32\3-程序源码\【固件库】STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm\startup_stm32f10x_hd.s

以及stm32f10x.h文件,将这三个文件放在和main.c相同的目录下,并注意将startup_stm32f10x_hd.s文件添加到Source Group1中,之后运行main.c文件,我觉得这样子是一定不会再报错的了,除非你main.c文件中的代码写错了,寄存器地址偏移量不清楚就去看数据手册就好了。
(4)最后就是烧录了,找不到LED就看开发板原理图,找对应的端口就OK。至此,就是这些问题的全部统一解决方法,完结!

发布了11 篇原创文章 · 获赞 12 · 访问量 2386

猜你喜欢

转载自blog.csdn.net/J_GMson/article/details/104033251