【精选】STM32学习笔记1

您所在的位置:网站首页 Keil5编译优化注意事项 【精选】STM32学习笔记1

【精选】STM32学习笔记1

2023-11-04 12:07| 来源: 网络整理| 查看: 265

目录

前言

一、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只学习了不到一周的时间,可能在一些问题的理解上还有差错,还望各位大佬积极指正。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3