一、寄存器操作
1、新建工程,新建一个目录存放以后所有的工程stmproject,在这个目录下新建文件夹寄存器点灯,文件名为LED。
接下来选择所用的软件包,之前安装软件时安装的,选择对应型号即可。
如果需要安装别的安装包可以在这个网址下载。点击打开文件
点击next,再点击finish就安装成功了。可以在包安装里找到。
2、新建文件main.c并双击source group文件夹添加进去
3、添加启动文件,取官方固件库中根据FLASH大小选择型号,我选大容量hd
复制到点灯文件夹后再添加进source group
框架搭好
4、编写main程序通过寄存器控制I/O口输入输出点灯
使能时钟
本人开发板LED等分别连到PB5和PE5上,所以点亮这两个灯需要使第三位和第六位置一开启时钟。上图给出了偏移地址,还需要知道RCC寄存器的起始地址,由中文参考手册里的存储器映射图可得,
下面写出代码
*(unsigned int *) 0x40021018 |=(1<<3); //使能端口B时钟
*(unsigned int *) 0x40021018 |=(1<<6); //是能端口E时钟
配置端口寄存器,再通过端口寄存器输出数据
stm32因为引脚太多,所以把引脚分成了几组,每组最多16个引脚,其中32位端口配置低寄存器控制低八位引脚,32位端口配置高寄存器控制高八位引脚。本次只用到了低八位
每个引脚分为配置位和模式位4位来配置,首先确定模式位是输入还是输出,再确定输入和是输出模式下具体的模式。上图可以得到端口的起始地址和偏移地址。代码如下:
*(unsigned int *) 0x40010C00 &=~(0x0F<<(4*5)); //把配置B端口5引脚那四位清零
*(unsigned int *) 0x40010C00 |=(0x01<<(4*5)); //把PB5配置成通用推挽输出,最大速度10MHz
*(unsigned int*)0x40011800 &=~(0x0F<<(4*5)); //把配置E端口5引脚那四位清零
*(unsigned int*)0x40011800 |=(0x03<<(4*5)); //把PE5配置成通用推挽输出,最大速度10MHz
再用端口输出寄存器使PB5和PE5输出低电平(由pcb图可直),由下图可知偏移地址0x0C
io口输出低电平电流才能流过二极管点灯
代码如下:
*(unsigned int*)0x40010C10 &=~(1<<5); //B端口5清零
*(unsigned int*)0x4001180C &=~(1<<5); //E端口5清零
最后把程序下载到单片机里即可点亮两个小灯。
总结
1、首先新建工程时,需要启动文件,main里需要一个系统时钟。
2、STM32引脚多,为节约资源,每个引脚都需要开启对应时钟。
3、点亮LED主要是控制GPIO输出高电平或低电平,需要GPIO寄存器来实现。
4、置零,置一技巧
某几位置零 &=~(x<<y)
某位置一 |=(x<<y)
5、各种地址可以用宏定义表示出来放在一个头文件里,这样程序可读性更高,以后库函数变成就这样,结构相同需要重复的还可用结构体表示。如
RCC_APB2ENR |=(1<<3); //是能端口B时钟
GPIOB_CRL &=~(0x0F<<(4*5)); //把配置B端口5引脚那四位清零
GPIOB_CRL |=(1<<(4*5)); //把PB5配置成通用推挽输出,最大速度10MHz
GPIOB_ODR &=~(1<<5); //B端口5清零
二、库函数点灯
1 建立库函数工程模板
-
在stmproject文件夹下新建Template文件夹,并新建 USER,CORE,OBJ ,STM32F10x_FWLib这几个文件夹用于装需要的库文件。
-
CORE文件夹需要从固件库中找到三个文件并复制进来,分别在这两条文件路径下寻找:
1 STM32F1xx固件库 \STM32F10x_StdPeriph _Li b_V3.5. 0\ Libraries \CMSIS \CM3\CoreSupport
2 STM32F1xx固件库 \STM32F10x_StdPeriph_Lib_V3.5.0 \Libraries\ CMSIS \CM3 \DeviceSupport\ST\STM32F10x\startup\arm里的启动文件
注:hd代表大容量,根据自身的芯片容量选取。 -
STM32F10x_FWLib文件夹下需要找到两个文件夹并复制进来,在这条路径下:
STM32F1xx固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries \STM32F10x_StdPeriph_Driver -
USER文件夹下需要找到6个文件并复制进来,文件路径如下:
1 STM32F1xx固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Project\ STM32F10x_StdPeriph_Template
2 STM32F1xx固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3 \DeviceSupport\ST\STM32F10x -
OBJ里存放编译完的文件。
到此为止,模板就建成了,以后需要建立工程之前可以直接复制一份改个名字。
2 新建库函数点灯工程
- 把Template复制一份并改名为库函数点灯
- 打开keil5,点击new uVision project ,把工程文件放在库函数点灯下的USER里,取名为LED,然后弹出界面选择自己的芯片,点击ok。
- 右键点击Target1,选择manage project items,把group栏和files栏变成下图的样子:
这三个组分别把之前复制到同名文件夹下的.c文件添加进来,CORE多添加了一个启动文件。 - 点击魔术棒进入工程配置
先配置文件输出,点击output,选择OBJ为输出文件夹
再配置C/C++选项卡,在Define中填写STM32F10X_HD,USE_STDPERIPH_DRIVER 配置全局宏定义变量,再把带有头文件的文件夹添加到include paths
5. 再USER文件夹中添加main.c文件,写下如下代码,点击编译,不报错就可以进行代码编写了。
6. 在库函数点灯文件夹下,新建HARDWARE文件夹,再从HARDWARE里新建LED文件夹,LED文件夹里新建两个文件led.c和led.h。
7. 再按照第三步添加HARDWARE组,组里添加led.c,
添加完写下#include "led.h"
编译一下点左边加号就会有led.h,还需要配置一下C/C++选项卡include paths使得可以被找到。
3 调用库函数编写程序点亮
由上面寄存器点灯可知,点亮小灯就是控制GPIO引脚输出高电平或低电平(根据硬件电路决定),电流流通二极管就发光了。
所以控制GPIO引脚输出低电平需要的函数要去STMF10x_FWLib中的rcc和gpio文件中找。
- 先进入rcc的头文件寻找APB2外设时钟使能的函数
点击右键可以回到函数的定义看到函数的参数怎么填
- 去gpio里找到配置GPIO的函数,也是同上,先去头文件最下找到函数的声明,再右键跳到函数定义。
由于这个函数第二个参数是一个结构体,所以我们需要用这个结构体实例化一个对象,所以可以右键转到结构体的函数定义。
结构体中参数的取值也都在头文件里用枚举和宏定义表示了。
最后还需要一个置位复位函数
3. 编写led.c,把PB5和PE5时钟使能,并配置输入输出模式
#include "led.h"
void LED_Init(void)
{
//实例化结构体
GPIO_InitTypeDef GPIO_InitStruct;
//使能B和E端口的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
//配置端口引脚5输入输出模式和速度
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
//把B和E端口按照上面配置的进行初始化
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_Init(GPIOE, &GPIO_InitStruct);
}
- 编写led.h
#ifndef __LED_H //避免头文件交叉引用后被重复编译
#define __LED_H
#include "stm32f10x.h"
void LED_Init(void); //声明函数
#endif
- 编写main.c,调用初始化函数,并通过复位和置位函数控制灯的亮灭
#include "stm32f10x.h"
#include "led.h"
//写一个简单的延时函数
void Delay( uint32_t count)
{
for(;count!=0;count--);
}
int main()
{
LED_Init(); //调用初始化函数
while(1)
{
//复位低电平灯亮,置位高电平灯灭
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
GPIO_SetBits( GPIOE,GPIO_Pin_5);
Delay(0xFFFFF);
GPIO_SetBits( GPIOB,GPIO_Pin_5);
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
Delay(0xFFFFF);
}
}
此时就可以把程序下载到芯片里,(程序下载见我第一篇文章),此时就可以看到两个等交替亮灭。
4 程序升级
上述程序可以达到要求,但是可移植性和查看性不强,可以把GPIO端口、引脚、时钟和控制灯亮灭的置位复位函数都写成宏定义,具体代码如下:
led.h
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
//定义两个灯的端口、引脚和时钟,LED0是PB5,LED1是PE5
#define LED_0_PIN GPIO_Pin_5
#define LED_0_PORT GPIOB
#define LED_0_CLK RCC_APB2Periph_GPIOB
#define LED_1_PIN GPIO_Pin_5
#define LED_1_PORT GPIOE
#define LED_1_CLK RCC_APB2Periph_GPIOE
//用LED(ON/OFF)控制两灯亮灭
#define ON 1
#define OFF 0
#define LED0(x) if (x) GPIO_ResetBits(LED_0_PORT,LED_0_PIN);\
else GPIO_SetBits( LED_0_PORT,LED_0_PIN);
#define LED1(x) if (x) GPIO_ResetBits(LED_1_PORT,LED_1_PIN);\
else GPIO_SetBits( LED_1_PORT,LED_1_PIN) ;
void LED_Init(void); //声明初始化函数
#endif
led.c文章来源:https://www.toymoban.com/news/detail-427485.html
#include "led.h"
void LED_Init(void)
{
//实例化配置GPIO模式和速度结构体
GPIO_InitTypeDef GPIO_InitStruct;
//使能两灯的时钟
RCC_APB2PeriphClockCmd(LED_0_CLK, ENABLE);
RCC_APB2PeriphClockCmd(LED_1_CLK, ENABLE);
//配置LED0引脚为推挽输出,速度为50MHz
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = LED_0_PIN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
//调用GPIO初始化函数,对LED0端口按上面配置初始化
GPIO_Init(LED_0_PORT, &GPIO_InitStruct);
//配置LED1引脚为推挽输出,速度为50MHz
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = LED_1_PIN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
//调用GPIO初始化函数,对LED1端口按上面配置初始化
GPIO_Init(LED_1_PORT, &GPIO_InitStruct);
}
main.c文章来源地址https://www.toymoban.com/news/detail-427485.html
#include "stm32f10x.h"
#include "led.h"
//一个简单的延时函数
void Delay( uint32_t count)
{
for(;count!=0;count--);
}
int main()
{
//调用初始化函数
LED_Init();
//两个灯交替亮灭
while(1)
{
LED0(1);
LED1(0);
Delay(0xFFFFF);
LED0(0);
LED1(1);
Delay(0xFFFFF);
}
}
到了这里,关于2、STM32点亮LED灯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!