STM32(一):各种方式点亮LED灯
程序员文章站
2022-06-09 08:25:35
...
led灯电路如上,所以PB0=0,绿灯亮,PB1=0,蓝灯亮,PB5=0,红灯亮
总共分三步
- 1.使能GPIOB的时钟
- 2.将PB0,PB1,或PB5配置为输出引脚
- 3.电平置零
1. 使能GPIOB的时钟
2.将PB0,PB1,或PB5配置为输出引脚
所以配置为B0001即可
3.电平置零
程序
#ifndef STM32F10X_H
#define STM32F10X_H
#define uint16_t unsigned short
#define uint32_t unsigned int
/*片上外设基地址 */
#define PERIPH_BASE ((uint32_t)0x40000000)
/*总线基地址,GPIO 都挂载到 APB2 上 */
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE+0x18000)
/*GPIOB 外设基地址*/
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
/* GPIOB 寄存器地址,强制转换成指针 */
#define GPIOB_CRL *(uint32_t*)(GPIOB_BASE+0x00)
#define GPIOB_CRH *(uint32_t*)(GPIOB_BASE+0x04)
#define GPIOB_IDR *(uint32_t*)(GPIOB_BASE+0x08)
#define GPIOB_ODR *(uint32_t*)(GPIOB_BASE+0x0C)
#define GPIOB_BSRR *(uint32_t*)(GPIOB_BASE+0x10)
#define GPIOB_BRR *(uint32_t*)(GPIOB_BASE+0x14)
#define GPIOB_LCKR *(uint32_t*)(GPIOB_BASE+0x18)
/*RCC 外设基地址*/
#define RCC_BASE 0x40021000
/*RCC 的 AHB1 时钟使能寄存器地址,强制转换成指针*/
#define RCC_APB2ENR *(uint32_t*)(RCC_BASE+0x18)
typedef struct
{
uint32_t CRL;
uint32_t CRH;
uint32_t IDR;
uint32_t ODR;
uint32_t BSRR;
uint32_t BRR;
uint32_t LCKR;
}GPIO_TypeDef;
#define GPIOB ((GPIO_TypeDef*)GPIOB_BASE)
typedef struct
{
uint32_t CR;
uint32_t CFGR;
uint32_t CIR;
uint32_t APB2RSTR;
uint32_t APB1RSTR;
uint32_t AHBENR;
uint32_t APB2ENR;
uint32_t APB1ENR;
uint32_t BDCR;
uint32_t CSR;
}RCC_TypeDef;
#define RCC ((RCC_TypeDef*)RCC_BASE)
#endif //STM32F10X_H
#ifndef STM32F10X_GPIO_H
#define STM32F10X_GPIO_H
#include "stm32f10x.h"
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Ñ¡ÔñPin0 */ //(00000000 00000001)b
#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Ñ¡ÔñPin1 */ //(00000000 00000010)b
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Ñ¡ÔñPin2 */ //(00000000 00000100)b
#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Ñ¡ÔñPin3 */ //(00000000 00001000)b
#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Ñ¡ÔñPin4 */ //(00000000 00010000)b
#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Ñ¡ÔñPin5 */ //(00000000 00100000)b
#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Ñ¡ÔñPin6 */ //(00000000 01000000)b
#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Ñ¡ÔñPin7 */ //(00000000 10000000)b
#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Ñ¡ÔñPin8 */ //(00000001 00000000)b
#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Ñ¡ÔñPin9 */ //(00000010 00000000)b
#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Ñ¡ÔñPin10 */ //(00000100 00000000)b
#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Ñ¡ÔñPin11 */ //(00001000 00000000)b
#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Ñ¡ÔñPin12 */ //(00010000 00000000)b
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Ñ¡ÔñPin13 */ //(00100000 00000000)b
#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Ñ¡ÔñPin14 */ //(01000000 00000000)b
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Ñ¡ÔñPin15 */ //(10000000 00000000)b
#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< Ñ¡ÔñÈ«²¿Òý½Å*/ //(11111111 11111111)b
typedef enum
{
GPIO_Speed_10MHz = 1, // 10MHZ (01)b
GPIO_Speed_2MHz, // 2MHZ (10)b
GPIO_Speed_50MHz // 50MHZ (11)b
}GPIOSpeed_TypeDef;
typedef enum
{ GPIO_Mode_AIN = 0x0, // Ä£ÄâÊäÈë (0000 0000)b
GPIO_Mode_IN_FLOATING = 0x04, // ¸¡¿ÕÊäÈë (0000 0100)b
GPIO_Mode_IPD = 0x28, // ÏÂÀÊäÈë (0010 1000)b
GPIO_Mode_IPU = 0x48, // ÉÏÀÊäÈë (0100 1000)b
GPIO_Mode_Out_OD = 0x14, // ¿ªÂ©Êä³ö (0001 0100)b
GPIO_Mode_Out_PP = 0x10, // ÍÆÍìÊä³ö (0001 0000)b
GPIO_Mode_AF_OD = 0x1C, // ¸´ÓÿªÂ©Êä³ö (0001 1100)b
GPIO_Mode_AF_PP = 0x18 // ¸´ÓÃÍÆÍìÊä³ö (0001 1000)b
}GPIOMode_TypeDef;
typedef struct
{
uint16_t GPIO_Pin;
uint16_t GPIO_Speed;
uint16_t GPIO_Mode;
}GPIO_InitTypeDef;
void GPIO_SetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin);
void GPIO_ResetBits( GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin );
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
#endif /* STM32F10X_GPIO_H */
#include "stm32f10x_gpio.h"
void GPIO_SetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin)
{
GPIOx->BSRR |= GPIO_Pin;
}
void GPIO_ResetBits( GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin )
{
GPIOx->BRR |= GPIO_Pin;
}
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
uint32_t tmpreg = 0x00, pinmask = 0x00;
/*---------------- GPIO 模式配置 -------------------*/
// 把输入参数 GPIO_Mode 的低四位暂存在 currentmode
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
// bit4 是 1 表示输出,bit4 是 0 则是输入
// 判断 bit4 是 1 还是 0,即首选判断是输入还是输出模式
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
{
// 输出模式则要设置输出速度
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
}
/*-----GPIO CRL 寄存器配置 CRL 寄存器控制着低 8 位 IO- ----*/
// 配置端口低 8 位,即 Pin0~Pin7
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
{
// 先备份 CRL 寄存器的值
tmpreg = GPIOx->CRL;
// 循环,从 Pin0 开始配对,找出具体的 Pin
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
// pos 的值为 1 左移 pinpos 位
pos = ((uint32_t)0x01) << pinpos;
// 令 pos 与输入参数 GPIO_PIN 作位与运算
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
//若 currentpin=pos,则找到使用的引脚
if (currentpin == pos)
{
//pinpos 的值左移两位(乘以 4),因为寄存器中 4 个位配置一个引脚
pos = pinpos << 2;
//把控制这个引脚的 4 个寄存器位清零,其它寄存器位不变
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
// 向寄存器写入将要配置的引脚的模式
tmpreg |= (currentmode << pos);
// 判断是否为下拉输入模式
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
// 下拉输入模式,引脚默认置 0,对 BRR 寄存器写 1 对引脚置 0
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
// 判断是否为上拉输入模式
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
// 上拉输入模式,引脚默认值为 1,对 BSRR 寄存器写 1 对引脚置 1
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
}
}
}
// 把前面处理后的暂存值写入到 CRL 寄存器之中
GPIOx->CRL = tmpreg;
}
/*--------GPIO CRH 寄存器配置 CRH 寄存器控制着高 8 位 IO- -----*/
// 配置端口高 8 位,即 Pin8~Pin15
if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
{
tmpreg = GPIOx->CRH;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = (((uint32_t)0x01) << (pinpos + 0x08));
currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
if (currentpin == pos)
{
pos = pinpos << 2;
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
tmpreg |= (currentmode << pos);
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
}
}
GPIOx->CRH = tmpreg;
}
}
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
void Delay(void);
int main(void)
{
#if 0
//裸地址 :容易出错
*(unsigned int*)(0x40021018) |= (1<<3); //开启GPIOB时钟
*(unsigned int*)(0x40010C00) &=0;
*(unsigned int*)(0x40010C00) |= 0x100000; //输出和速度 PB0:0x1,PB1:0x10,PB5:0x100000
*(unsigned int*)(0x40010C0C) &= 0;//输出低电平 PB0-PB15
#elif 0
//宏定义
RCC_APB2ENR |= (1<<3);
GPIOB_CRL &=0;
GPIOB_CRL |= 0x1;
GPIOB_ODR &= 0;
#elif 0
//结构体
RCC->APB2ENR |= (1<<3);
GPIOB->CRL &=0;
GPIOB->CRL |= 0x10;
GPIOB->ODR &=0;
#elif 1
//使用BSRR, BRR可以单独操纵一位
RCC->APB2ENR |= (1<<3);
GPIOB->CRL &=0;
GPIOB->CRL |= 0x10;
GPIO_SetBits(GPIOB,GPIO_Pin_1);
//GPIO_ResetBits( GPIOB,GPIO_Pin_1);
#elif 0
//自定义库
GPIO_InitTypeDef GPIO_InitStructure;
RCC->APB2ENR |=(1<<3);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
while(1)
{
//绿灯
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits( GPIOB,GPIO_Pin_0 );
Delay();
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay();
//蓝灯
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits( GPIOB,GPIO_Pin_1 );
Delay();
GPIO_SetBits(GPIOB,GPIO_Pin_1);
Delay();
//红灯
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits( GPIOB,GPIO_Pin_5 );
Delay();
GPIO_SetBits(GPIOB,GPIO_Pin_5);
Delay();
}
#endif
}
void SystemInit(void)
{
// 函数体为空,目的是为了骗过编译器不报错
}
//软件延时,不准
void Delay(void)
{
uint32_t i=0;
uint32_t j=0;
uint32_t k=0;
for(;i<60000;i++)
{
for(;j<60000;j++)
{
for(;k<1000;k++)
{
}
}
}
}
//还可以定义一些硬件相关的宏,以提高程序可移植性
其他
什么叫推挽输出?
1、可以输出高低电平,用于连接数字器件,高电平由VDD决定,低电平由
VSS决定。
2、推挽结构指两个三极管受两路互补的信号控制,总是在一个导通的时候
另外一个截止,优点开关效率效率高,电流大,驱动能力强。
3、输出高电平时,电流输出到负载,叫灌电流,可以理解成推,输出低电
平时,负载电流流向芯片,叫拉电流,即挽。
什么叫开漏输出?
1、只能输出低电平,不能输出高电平。
2、如果要输出高电平,则需要外接上拉。
3、开漏输出具有“线与”功能,一个为低,全部为低,多用于I2C和
SMBUS总线。
推荐阅读
-
堆料并不是唯一!索泰GeForce RTX 3070 PGF OC评测:独一无二的ARGB-LED灯效
-
Linux嵌入式学习第二节:C语言版本点亮LED灯
-
首款400W TGP非公旗舰!索泰RTX 3080Ti PGF评测:独一无二的ARGB-LED灯效
-
STM32F4 阿波罗寄存器点亮LED灯
-
【STM32Cube_02】使用GPIO点亮一个LED灯
-
教育的本质是爱,教育的过程不过是一盏灯点亮另一盏灯的过程。
-
点亮LED灯实验、系统时钟设置、LED灯闪烁实验、 位带操作
-
新一代华为Sound X发布:48颗LED灯360°环绕
-
STM32之点亮LED
-
STC89C52通过寄存器点亮一个LED