STM32学习笔记1——软硬件基础之keil5编程与GPIO开发

目录

前言

一、Keil uVision5 MDK软件的安装以及一些问题的解决方案

1.1 软件安装

1.2 注意事项

二、 keil5编程与GPIO开发

2.1 第一步:使能IO口时钟

2.2 第二步:初始化IO口模式。

2.3 第三步:操作IO口,输出高低电平

2.4 综合代码 

2.5 位操作

总结


前言

本人为自动化专业准大三学生,由于大创项目需要开始着手自学STM32,拥有一定的数模电知识基础与C++语言编程基础(计算机二级C++良好并曾获蓝桥杯软件类省三)。全程根据正点原子的开发板与配套教程进行自学,目前已学习了一周(配套视频第2讲~第15讲),总结了一点对于初学者的学习方法与学习笔记。

另:数学建模专栏主要连载2021暑期数学建模培训期间的MATLAB编程代码以供参考(曾获建模国赛省三),目前培训处于休息阶段,之后会继续连载。

开发板型号:正点原子精英STM32F103ZET6开发板

淘宝链接:https://m.tb.cn/h.fahDKDf?sm=041383

资料链接:http://www.openedv.com/docs/boards/stm32/zdyz_stm32f103_jingying.html#


一、Keil uVision5 MDK软件的安装以及一些问题的解决方案

1.1 软件安装

这里推荐一个宝藏公众号,相信对于我们自动化人来说大家应该都已知晓:软件管家

安装包以及安装教程:https://mp.weixin.qq.com/s/TCeWLme8BcOISr-n4HDBGw

1.2 注意事项

安装的过程不会出现什么问题,但实际在使用的过程中还会出现一系列的问题,首先要跟随视频学习,其次会遇到视频中没有出现的问题。以下为博主本人遇到的一些问题以及其解决方案。

keil5编译一直有一个报错

1.点魔术棒,选Target选项卡,把右上角那个Code Generation里的use default compiler version 6改成use default compiler version 5,这样就好了。

2.环境变量有问题,可以试试修改环境变量的方法:https://pan.baidu.com/s/1YPc5g87Trf8M8AhqMIkgOQ

keil5自动补全代码功能(关于STM32的)

版权声明:本文为CSDN博主「KYYZSGD」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yjyenjoy1/article/details/107332168

keil5输入中文乱码问题一步解决!详细!

版权声明:本文为CSDN博主「阳光下午茶。」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36687153/article/details/102631268 


二、 keil5编程与GPIO开发

首先,看过原子哥视频的同学都知道有关IO口的知识是学习整个STM32过程中的重中之重;

其次,虽然原子哥已经讲的很细致了但毕竟“师傅领进门,修行在个人”,本人总结了一些有关基于库函数方向以实验1跑马灯实验为例如何初始化和使用IO口的一些重点知识。 

2.1 第一步:使能IO口时钟

IO口时钟其实可以结合数电实验FPGA自带的时钟引脚进行理解,其实就是一个触发条件。重点是要掌握调用时要输入怎样的参数。

时钟使能函数RCC_APB2PeriphClockCmd()共有2个参数。以下模块为可填入的参数,其中加粗部分为分类注释。

时钟使能函数

使能IO口时钟。调用函数

RCC_APB2PeriphColckCmd();

不同的IO组,调用的时钟使能函数不一样。

1.1 assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));

#define RCC_APB2Periph_AFIO              ((uint32_t)0x00000001)
#define RCC_APB2Periph_GPIOA             ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB             ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC             ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD             ((uint32_t)0x00000020)
#define RCC_APB2Periph_GPIOE             ((uint32_t)0x00000040)
#define RCC_APB2Periph_GPIOF             ((uint32_t)0x00000080)
#define RCC_APB2Periph_GPIOG             ((uint32_t)0x00000100)
#define RCC_APB2Periph_ADC1              ((uint32_t)0x00000200)
#define RCC_APB2Periph_ADC2              ((uint32_t)0x00000400)
#define RCC_APB2Periph_TIM1              ((uint32_t)0x00000800)
#define RCC_APB2Periph_SPI1              ((uint32_t)0x00001000)
#define RCC_APB2Periph_TIM8              ((uint32_t)0x00002000)
#define RCC_APB2Periph_USART1            ((uint32_t)0x00004000)
#define RCC_APB2Periph_ADC3              ((uint32_t)0x00008000)
#define RCC_APB2Periph_TIM15             ((uint32_t)0x00010000)
#define RCC_APB2Periph_TIM16             ((uint32_t)0x00020000)
#define RCC_APB2Periph_TIM17             ((uint32_t)0x00040000)
#define RCC_APB2Periph_TIM9              ((uint32_t)0x00080000)
#define RCC_APB2Periph_TIM10             ((uint32_t)0x00100000)
#define RCC_APB2Periph_TIM11             ((uint32_t)0x00200000)

1.2 assert_param(IS_FUNCTIONAL_STATE(NewState));

#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))

2.2 第二步:初始化IO口模式。

有关GPIO的初始化底层原理我们了解即可,其实就是不断地调用库函数。重点是要掌握调用时要输入怎样的参数。

初始化函数GPIO_Init()共有2个参数,其中第2个参数为结构体,其中还包含三个参数。以下模块为可填入的参数,其中加粗部分为分类注释。

初始化函数

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

1.GPIOx: GPIOA~GPIOG


2. GPIO_InitTypeDef  GPIO_InitStructure;

typedef struct
   {
     uint16_t GPIO_Pin;                           //指定要初始化的IO口         
    GPIOSpeed_TypeDef GPIO_Speed; //设置IO口输出速度
    GPIOMode_TypeDef GPIO_Mode;    //设置工作模式:8种中的一个
   }GPIO_InitTypeDef;
    
2.1 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */

2.2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出

typedef enum
{ GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,//推挽
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}

2.3 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz

typedef enum

  GPIO_Speed_10MHz = 1,
  GPIO_Speed_2MHz, 
  GPIO_Speed_50MHz
}

 GPIO_Init(GPIOB, &GPIO_InitStructure);     //根据设定参数初始化GPIOB.5

2.3 第三步:操作IO口,输出高低电平

这里主要用到了4个设置输出电平函数,其实就是通过这几个函数控制IO口输出高低电平。重点是要掌握调用时要输入怎样的参数。

设置输出电平函数GPIO_SetBits()共有2个参数。以下模块为可填入的参数,其中加粗部分为分类注释。

1.GPIOx: GPIOA~GPIOG

2.GPIO_Pin:

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */

2.4 综合代码 

有关led.h led.c main.c这三个文件的关系是:.h文件相当于两个.c文件的衔接,使得main.c能够通过led.h头文件引用led.c文件(C语言的知识,但说实话学校没怎么学有关头文件的内容)。

注:这是基于看过视频以后对程序项目经过初始化后的主程序,详情还需观看配套视频前15讲。

 

led.h 代码:

#ifndef __LED_H
#define __LED_H

void LED_Init(void);//起到衔接作用
#endif

led.c 代码: 

#include "led.h"
#include "stm32f10x.h"
void LED_Init(void)//主函数
{
	GPIO_InitTypeDef GPIO_InitStructure;//定义第二步的结构体
	
	//第一步:使能IO口时钟。调用函数 RCC_APB2PeriphColckCmd();不同的IO组,调用的时钟使能函数不一样。
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//GPIOB
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//GPIOE
	
	//第二步:初始化IO口模式。调用函数 GPIO_Init();
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	//第三步:操作IO口,输出高低电平。GPIO_SetBits();GPIO_ResetBits();
	GPIO_SetBits(GPIOB,GPIO_Pin_5);
	
	//GPIOE同二三步
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&GPIO_InitStructure);
	GPIO_SetBits(GPIOE,GPIO_Pin_5);
}

 main.c 代码:

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
int main(void)
{
	delay_init();//延时函数
	LED_Init();//初始化IO口,通过led.h调用led.c函数
	while(1)
{
	GPIO_SetBits(GPIOB,GPIO_Pin_5);//高电平
	GPIO_SetBits(GPIOE,GPIO_Pin_5);
	delay_ms(500);//延时500ms
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_5);//低电平
	GPIO_ResetBits(GPIOE,GPIO_Pin_5);
  delay_ms(500);//延时500ms
}
}

注:代码最后结尾时需要加一行回车,否则会报错!

2.5 位操作

有关位操作,在代码上的体现仅仅是main.c不同,更为简单,但底层原理十分复杂,了解即可。

  main.c 代码:

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"//该头文件中已包含"sys.h"
 int main(void)
 {	
	 delay_init();//初始化延时函数
	 LED_Init();//初始化LED函数
	 while(1)
	 {
		 PBout(5)=1;//PB IO口设置为高电平灯灭(位操作,内嵌函数宏定义)
		 PEout(5)=1;//PE IO口设置为高电平灯灭(位操作,内嵌函数宏定义)
		 
		 delay_ms(500);//延时500ms
		 
		 PBout(5)=0;//PB IO口设置为低电平灯亮(位操作,内嵌函数宏定义)
		 PEout(5)=0;//PE IO口设置为低电平灯亮(位操作,内嵌函数宏定义)
		 
		 delay_ms(500);//延时500ms
		 //LED一端接3.3V,共阳极接法,低电平导通(有电位差),高电平截止(无电位差)
	 }
 }

总结

对于STM32的学习在我看来对底层原理了解即可,重点在于会用,即会灵活调用各种库函数。

目前本人对STM32只学习了不到一周的时间,可能在一些问题的理解上还有差错,还望各位大佬积极指正。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

糖—果

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值