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