❤ 2018.8.11
最近入了STM32的坑,主要是马老师又有新项目,老师看我最近有点闲(哪里闲了?),就让我来协助,之前学了一些基础的东西了,不过没时间整理,现在准备补上。
我学习使用的是野火stm32开发板,教程很详细,强烈推荐!
〇 STM32基础知识
❤ 2018.8.11
○什么是STM32
○ STM32有什么功能
○ 开发板的硬件资源
○ STM32分类
○ STM32命名方法
○ 引脚分配
○ 参考手册与数据手册
○ 数据手册中对引脚的定义
〇 什么是寄存器
○ STM32架构简图
○ 系统框图
○ 寄存器映射
关于寄存器映射,之前没有思考过,这么一说确实是认识上有不足。
之所以能够直接给寄存器赋值,是因为把地址作为指针定义到了寄存器别名里。
❤2018.8.12
○ STM32的位操作
和以前51单片机的位操作还是有很大区别的,习惯就好习惯就好。
○ STM32的寄存器是通过结构体的形式封装的
使用的时候可以这样
不过一般都是这样
大概明白是什么个意思了,就是说结构体里面都是32位的地址偏移量,把结构体的首地址定义成对应的寄存器地址,然后用指针去调用就能访问相应的寄存器。不过最简单的方式是定义地址的时候就将他强制转化成指针,这样调用的时候就可以直接用了。
〇 新建第一个工程
○ 新建好工程后keil5不会自动提示拷贝启动文件,需要自己去st的官网下载相应的启动文件。
“【固件库】STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm”
大概是这么个路径。。。
○ 每个启动文件对应的单片机型号:
○ #include "stm32f10x.h"
〇 点亮一个LED灯
直接对寄存器操作是这样的
❤ 2018.8.17
〇 GPIO
○ GPIO简介
○ 引脚分类
○ GPIO功能框图
○ 推挽输出
♣ 推挽输出时,最高可以提供25ma电流
○ 开漏输出
♣ 开漏输出具有“线与”功能,一个为低,全部为低,多用于I2C和SMBUS总线。
○ GPIO输出初始化顺序
❤ 2018.8.18
〇 使用寄存器映射点亮LED
首先定义头文件
然后这样写代码
〇 构建库函数
○ 通过结构体形式映射寄存器
这样定义头文件
然后这样写代码:
♣ 我理解的是,之所以调用结构体的时候不需要用取内容运算符或者说宏定义的时候前面不加*是因为->运算符就是用来取内容的(?)
❤ 2018.8.19
○ 使用固件库初始化GPIO并点亮LED的程序这样写
〇 STM32固件库分析
❤ 2018.8.20
〇 新建一个固件库模板
○ 新建工程模板文件夹,如“Fwlib-Template”,下面新建如下文件夹:
○ 新建工程,选择相应芯片型号(这是需要提前在st官网下载相应芯片包并安装的)。
○ 在工程中target文件夹下新建相应group
○ 将官方库的相应文件拷贝到自己的工程模板目录中
· libraries:(将官方库的libraries拷贝过来之后调整目录结构)
· user:(这个是从官方库的例程里面拷贝过来的,除了main.c)
○ 将相应文件添加到工程中
○ 添加include path
○ 定义宏
♣ USE_STDPERIPH_DRIVER是为了使工程包含stm32f10x_conf.h
STM32F10X_HD是使头文件stm32f10x.h初始化为相应芯片型号(容量不同)。
○配置options
♣ use microlib是为了在编程中使用c的标准库
○ 添加一个清楚垃圾文件的命令行
○ 仿真器设置(dap仿真器)
先打开开发板
♣reset那里视频里说是autodetect,但是没找到,那就sysresetreq吧
♣ 更改了芯片型号之后仿真器设置一定会变,记得改过来。
〇 使用固件库点亮LED
· 拷贝固件库模板
· 在user里面新建led文件夹,新建bsp_led.c和bsp_led.h
· 打开工程,添加刚才的文件
· bsp_led.c添加头文件,并把头文件目录添加到include path里
· bsp_led.h添加条件编译语句
· 互相添加头文件
· 将跟硬件相关的都定义成宏,增加程序可读性
· 最后写成了这样
大概就是这样了。
· 加个延时,让灯闪烁
· 新花样,使用带参宏
· 新花样2,使用c语言里面的续行符使语句变短
♣ 续行符后面如果不小心有东西了就会报错
❤ 2018.10.7
好久没有学习stm32了,不过今天学到一个可以同时操作多个gpio的技巧,原贴在这里:
http://www.openedv.com/posts/list/0/62161.htm
我把代码改了一下,大概就是这样的:
初始化:
void GPIO_DefaultInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC \
| RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF \
| RCC_APB2Periph_GPIOG, ENABLE); //使能所有时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | \
GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | \
GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | \
GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; //选中所有IO口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //输出模式,推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //100M
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB
GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOC
GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIOD
GPIO_Init(GPIOE, &GPIO_InitStructure); //初始化GPIOE
}
操作的时候也可以这样子。
一下子就腰不酸腿不痛一口气上五楼了呢!
❤ 2018.10.9
昨天调录入系统的stm32程序的时候遇到了一个问题,stm32的GPIO总有三个端口不能工作,查询之后发现是PB3 PB4 PA15
,查看端口功能发现是JTAG的下载端口,又查资料发现这个端口在初始化端口时钟后默认是作为下载端口而不是作为IO口的。
在一番百度之后发现了如下解决方法:
把STM32的JTAG下载引脚:JTDO、JTDI、JTCK 当成普通IO口进行操作
简单来说就是这样:
1、打开复用时钟:RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
2、调用重映射函数:GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
但是!
出现了一个严重的问题,SWD下载不能用了!
经过一番百度之后发现,GPIO_Remap_SWJ_Disable这个是关闭JTAG和SWD下载功能,GPIO_Remap_SWJ_JTAGDisable这个才是只关闭JTAG保留SWD。
知道真相的我眼泪掉下来。。。
虽然知道原因了但是下不了程序,于是又一番百度之后知道了这个方法:
链接如下:
stm32不小心把SWD和JTAG都给关了,程序下载不进去,解决办法
不过呢,直接把这几个GPIO口复用功能打开之后他们都是默认拉高的(其实也好像不全是),所以最后的代码是这样:
//这四句的作用是将JTAG下载引脚PB3 PB4 PA15作为普通IO口进行的设置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //打开复用时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //调用重映射函数(关闭JTAG不关闭SWD)!!!
GPIO_ResetBits(GPIOB,GPIO_Pin_3 | GPIO_Pin_4);
GPIO_ResetBits(GPIOA,GPIO_Pin_15);
over