希望读者能点赞,互动,分享,让我更有动力,等我彻底写完stm32的学习日志,我会制作成电子书,分享给大家。
我为什么使用库函数进行编写程序?
截至2020年8月28日,ST公司一共开发了三个库,分别是标准外设库(STD),HAL库,LL库,此前使用直接控制寄存器的方式控制微处理器,从开发时间上是寄存器--->标准外设库--->HAL库--->LL库,其中寄存器的优点是代码量少,标准外设库可移植性强,HAL库和LL库虽然代码量少于标准外设库和固定平台的可移植性增强,但是在跨平台的可移植性大大降低,各平台的兼容性差,并且STM32Cube平台有些臃肿,我鉴于学习时间和未来的跨平台考虑,选择了标准外设库。
下面开始正文:
跑马灯实验:
重要翻译:
Reset Clock Controller ——RCC寄存器(复位时钟控制器寄存器)
步骤:
- 确定stm32中的所需引脚的连接
- LED0-PB5
- LED1-PE5
- 确定使用库函数
- 头文件
- Stm32f10x_gpio.h
- Stm32f10x_rcc.h
- 源文件
- Stm32f10x_gpio.c
- Stm32f10x_rcc.c
- 一般常见库函数重要函数:
- 1个初始化函数:
- 头文件
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
作用:
初始化一个或者多个IO口(同一组)的工作方式和速度。该函数主要是操作GPIO_CRL(CRH)寄存器,在上拉或者下拉的时候有设置BSRR或者BRR寄存器
GPIOx: GPIOA~GPIOG
这里的 GPIO_InitTypeDef* GPIO_InitStruct为:
typedef struct
{
uint16_t GPIO_Pin; //指定要初始化的IO口
GPIOSpeed_TypeDef GPIO_Speed; //设置IO口输出速度
GPIOMode_TypeDef GPIO_Mode; //设置工作模式:8种中的一个
}GPIO_InitTypeDef;
GPIO_Init函数初始化样例:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 ,可高可低
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
- 2个读取输入电平函数:
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
作用:读取某个GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。
例如:
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);//读取GPIOA.5的输入电平
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
作用:读取某组GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。
例如:
GPIO_ReadInputData(GPIOA);//读取GPIOA组中所有io口输入电平
- 2个读取输出电平函数:
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit (GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
作用:读取某个GPIO的输出电平。实际操作的是GPIO_ODR寄存器。
例如:
GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_5);//读取GPIOA.5的输出电平
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
作用:读取某组GPIO的输出电平。实际操作的是GPIO_ODR寄存器。
例如:
GPIO_ReadOutputData(GPIOA);//读取GPIOA组中所有io口输出电平
- 4个设置输出电平函数:
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
作用:设置某个IO口输出为高电平(1)。实际操作BSRR寄存器
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
作用:设置某个IO口输出为低电平(0)。实际操作的BRR寄存器。
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
这两个函数不常用,也是用来设置IO口输出电平。
- 编程
文件结构图:
硬件编程:
Led.h
#ifndef __LED_H
#define __LED_H
//#include "sys.h"
//LED 端口定义
//#define LED0 PBout(5)// DS0-digital signal 0
//#define LED1 PEout(5)// DS1
void LED_Init(void);//初始化
#endif
Led.c
#include "led.h"
#include "stm32f10x.h"
//初始化 PB5 和 PE5 为输出口.并使能这两个口的时钟
//LED IO 初始化
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义一个结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//使能 PB,PE 端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
//指定端口,LED0-->PB.5 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//指定模式,推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度
GPIO_Init(GPIOB, &GPIO_InitStructure); //端口初始化
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高电平
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure); //端口初始化
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
}
main.c
#include "led.h"
#include "delay.h"
//#include "sys.h"
#include "stm32f10x.h"
//跑马灯实验
int main(void)
{
delay_init(); //延时函数初始化
LED_Init(); //初始化与 LED 连接的硬件接口
while(1)
{
//LED0 =0;
//LED1 =1;
//delay_ms(1000); //延时 300ms
//LED0 =1;
//LED1 =0;
//delay_ms(300); //延时 300ms
GPIO_SetBits(GPIOB,GPIO_Pin_5);//置高电平
GPIO_SetBits(GPIOE,GPIO_Pin_5);//同上
delay_ms(3000);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);//置低电平
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
delay_ms(3000);
}
}
添加头文件路径,设置obj路径,添加target文件夹和头文件,源文件
按照上面的步骤设置,就可以完成最简单的跑马灯实验。