历史上的今天
返回首页

历史上的今天

今天是:2024年10月18日(星期五)

正在发生

2021年10月18日 | stm32专题一:GPIO输出—点亮LED

2021-10-18 来源:eefocus

新建led文件夹和bsp_led.c和bsp_led.h的板级支持包。


在bsp_led.c中,函数LED_GPIO_Config(void)提供了gpio的初始化过程:


定义GPIO初始化结构体;

开启RCC时钟,这一步非常重要,要找到对应的总线和外设时钟;

给初始化结构体成员赋值,由于和硬件相关,都在bsp_led.h中定义成宏,提高可移植性。

bsp_led.c


// bsp: board support package 板级支持包

 

#include "bsp_led.h"

 

void LED_GPIO_Config(void)

{

    // 定义GPIO初始化结构体

GPIO_InitTypeDef GPIO_InitStruct;

// 开启RCC时钟,非常关键

RCC_APB2PeriphClockCmd(LED_R_GPIO_CLK | LED_G_GPIO_CLK | LED_B_GPIO_CLK, ENABLE);

 

    // 配置初始化结构体,传入具体参数

GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_PIN;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;

// 初始化3个LED灯的GPIO

GPIO_Init(LED_G_GPIO_PORT, &GPIO_InitStruct);

GPIO_InitStruct.GPIO_Pin = LED_R_GPIO_PIN;

GPIO_Init(LED_R_GPIO_PORT, &GPIO_InitStruct);

GPIO_InitStruct.GPIO_Pin = LED_B_GPIO_PIN;

GPIO_Init(LED_B_GPIO_PORT, &GPIO_InitStruct);

// 初始状态关闭所有LED灯

GPIO_SetBits(LED_R_GPIO_PORT, LED_R_GPIO_PIN);

GPIO_SetBits(LED_G_GPIO_PORT, LED_G_GPIO_PIN);

GPIO_SetBits(LED_B_GPIO_PORT, LED_B_GPIO_PIN);

}

 

 

在bsp_led.h中,大量使用了宏定义,来封装硬件相关的函数


bsp_led.h


#ifndef __BSP_LED_H

#define __BSP_LED_H

 

#include "stm32f10x.h"

 

// 硬件封装宏

#define LED_R_GPIO_PIN GPIO_Pin_5

#define LED_R_GPIO_PORT GPIOB

#define LED_R_GPIO_CLK RCC_APB2Periph_GPIOB

 

#define LED_G_GPIO_PIN GPIO_Pin_0

#define LED_G_GPIO_PORT GPIOB

#define LED_G_GPIO_CLK RCC_APB2Periph_GPIOB

 

#define LED_B_GPIO_PIN GPIO_Pin_1

#define LED_B_GPIO_PORT GPIOB

#define LED_B_GPIO_CLK RCC_APB2Periph_GPIOB

 

// 直接操作寄存器的方法控制IO

#define digitalHi(port, pin) do {port->BSRR |= pin;} while (0) // 置位

#define digitalLo(port, pin) do {port->BRR |= pin;} while (0) // 复位

#define digitalToggle(port, pin) do {port->ODR ^= pin;} while (0) // 反转

 

// 定义控制IO的宏

#define LED_R_TOGGLE digitalToggle(LED_R_GPIO_PORT, LED_R_GPIO_PIN)

#define LED_R_ON digitalLo(LED_R_GPIO_PORT, LED_R_GPIO_PIN)

#define LED_R_OFF digitalHi(LED_R_GPIO_PORT, LED_R_GPIO_PIN)

 

#define LED_G_TOGGLE digitalToggle(LED_G_GPIO_PORT, LED_G_GPIO_PIN)

#define LED_G_ON digitalLo(LED_G_GPIO_PORT, LED_G_GPIO_PIN)

#define LED_G_OFF digitalHi(LED_G_GPIO_PORT, LED_G_GPIO_PIN)

 

#define LED_B_TOGGLE digitalToggle(LED_B_GPIO_PORT, LED_B_GPIO_PIN)

#define LED_B_ON digitalLo(LED_B_GPIO_PORT, LED_B_GPIO_PIN)

#define LED_B_OFF digitalHi(LED_B_GPIO_PORT, LED_B_GPIO_PIN)

 

// 颜色设置

#define LED_RED do {LED_R_ON; LED_G_OFF; LED_B_OFF;} while (0)

#define LED_GREEN do {LED_R_OFF; LED_G_ON; LED_B_OFF;} while (0)

#define LED_BLUE do {LED_R_OFF; LED_G_OFF; LED_B_ON;} while (0)

#define LED_YELLOW do {LED_R_ON; LED_G_ON; LED_B_OFF;} while (0)

#define LED_PURPLE do {LED_R_ON; LED_G_OFF; LED_B_ON;} while (0)

#define LED_CYAN do {LED_R_OFF; LED_G_ON; LED_B_ON;} while (0)

 

#define LED_ALL_ON do {LED_R_ON; LED_G_ON; LED_B_ON;} while (0)

#define LED_ALL_OFF do {LED_R_OFF; LED_G_OFF; LED_B_OFF;} while (0)

 

void LED_GPIO_Config(void);

 

#endif /* __BSP_LED_H */

然后在主函数中进行调用


main.c


#include "stm32f10x.h"

#include "bsp_led.h"

 

void delay(uint32_t count);

 

int main(void)

{

LED_GPIO_Config();

 

while (1)

{

LED_CYAN;

delay(0XFFFFF);

LED_ALL_OFF;

delay(0XFFFFF);

}

}

 

void delay(uint32_t count)

{

for (; count != 0; count--);

}

 

GPIO具有锁定机制,可以冻结该GPIO的配置,即在下次复位前,不能更改GPIO的配置。

锁定操作的寄存器为GPIOx_LCKR,具体描述如下

上面的说明起始我感觉挺难理解的,于是找到了标准库里面的源码,发现写的非常清晰,具体如下


void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

{

  uint32_t tmp = 0x00010000;

  

  /* Check the parameters */

  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  assert_param(IS_GPIO_PIN(GPIO_Pin));

  

  tmp |= GPIO_Pin;

  /* Set LCKK bit */

  GPIOx->LCKR = tmp;

  /* Reset LCKK bit */

  GPIOx->LCKR =  GPIO_Pin;

  /* Set LCKK bit */

  GPIOx->LCKR = tmp;

  /* Read LCKK bit*/

  tmp = GPIOx->LCKR;

  /* Read LCKK bit*/

  tmp = GPIOx->LCKR;

}

tmp为LCCK位置1,然后把GPIO_Pin的相应值也置1。接下来就是对相应的位执行写入序列操作。


首先是写1,即写入带LCCK和GPIO_Pin的位;


然后写0,写只带GPIO_Pin的位;


然后重复写1;


接下来读GPIOx_LCKR的值到tmp,连续读取两次,完成操作。

推荐阅读

史海拾趣

Global Power Technologies Group公司的发展小趣事
在数字电路中,集基耦合单稳态电路可以用于将高频信号分频为低频信号。
EPCOS (TDK)公司的发展小趣事

2009年10月1日,EPCOS与TDK元件事业部合并,成立了TDK-EPC公司。这次合并进一步增强了EPCOS在电子元器件领域的实力,使其在全球市场中的地位更加稳固。合并后,TDK-EPC公司继续秉承EPCOS的技术创新和产品拓展战略,不断推出具有竞争力的新产品和解决方案,以满足客户日益增长的需求。

DAESAN公司的发展小趣事

DAESAN公司以其独特的设备回收与再利用技术,在电子行业中崭露头角。起初,公司只是一个小型的设备拆卸公司,但在一次偶然的机会中,他们发现许多被废弃的电子设备中,仍然含有大量可再利用的零部件和材料。于是,DAESAN公司开始专注于电子设备的回收和再利用,通过精细的拆卸和修复技术,将废旧设备转化为新的生产资源。这一举措不仅为公司带来了可观的利润,也为环保事业做出了贡献。

Good Will Instrument Co., Ltd.公司的发展小趣事

随着全球化进程的加速,DAESAN公司开始将目光投向国际市场。他们制定了详细的国际化战略,积极拓展海外市场。通过与国外企业的合作和交流,DAESAN公司逐渐建立起全球化的生产和销售网络。他们的产品不仅畅销亚洲市场,还成功打入欧美等发达国家市场。国际化战略的实施,使DAESAN公司的品牌知名度和影响力得到了显著提升。

HM International公司的发展小趣事

在电子行业中,技术创新是企业发展的核心驱动力。DAESAN公司深知这一点,因此一直致力于技术研发和创新。他们投入大量资金和资源,引进先进的生产设备和技术人才,不断推出具有竞争力的新产品。其中,一款高性能的电子芯片引起了行业的广泛关注。这款芯片采用了最新的纳米技术和低功耗设计,不仅性能卓越,而且节能环保。DAESAN公司凭借这一技术创新,成功打开了高端电子市场的大门。

GCi Technologies公司的发展小趣事
内部包含一个定时器,用于设定充电时间。当充电时间达到预设值时,IC将自动切断充电电流,防止电池过充。

问答坊 | AI 解惑

数字电路非常基础的教材

数字电路非常基础的教材…

查看全部问答>

来讨论下VHDL里边的库吧

最近用VHDL编程,发现有很多时候遇到《Error (10327): VHDL error at and2.vhd(11): can\'t determine definition of operator \"\"+\"\" -- found 0 possible definitions》这样的问题,开始不知道为什么,后来在知道不同的数据类型的运算是定义在 ...…

查看全部问答>

你如何定义射频?

此前一直在说射频,但是具体到概念,心里还真有些迷糊,呵呵,网上查了查,有个概念 射频表示可以辐射到空间的电磁频率,频率范围从300KHz~30GHz之间。 在电磁波频率低于100khz时,电磁波会被地表吸收,不能形成有效的传输,但电磁波频率高于100 ...…

查看全部问答>

为什么9650预览的图像很红?

原来我的9650输出图像时30万像素的,可以正常显示图像。 可是我从代理要到了130万像素的配置后,图像发红,而且是很红。 不知道有没有遇到这种情况的?是如何解决的?…

查看全部问答>

去各位救急!!!

那位可以为小弟买到一套。44b0的散件。全部。包括电容、电阻之类的东西。不要成品。想自己动手做板子。小弟这里的市场什么都没有。只有一些电视机的配件别的一概没有啊! 谢谢!…

查看全部问答>

做一个受欢迎的提问者

要想让你的问题尽快得到解答,我想以下几条是你应该注意的: 1.首先说清楚你使用的软,硬件平台。比如:我使用wince5.0在 2440上做开发... 2.问题要尽量具体,不要问诸如:我要做一个什么项目,该怎么做?或者我要做一个什么软件,该怎么做这类的 ...…

查看全部问答>

uversion如何知道arm的程序内存占用情况

我用的uversion4,lm3s8962的芯片。 我建立一个全局变量 uchar a[9000]100]; 按道理应该超过ram的容量了,但是怎么编译后不报错呢?如何才知道内存有没有超?…

查看全部问答>

生产厂家规范的-- LED驱动电源测试报告范例

replyreload += \',\' + 1365593;这份报告是基于一个8W LED驱动电源临时做的一个基本范例,是考虑有公司商业机密的问题,略作修改: 1.不对版权负责,只供参考. 2.不对内容负责,不做解释.每家公司各不相同,难于解释不同.敬请谅解. Timson,如果您要 ...…

查看全部问答>

ad测量通过串口发出的程序,只能发出FF

我用AD采样,然后想通过串口发出,结果只能得到FF。大家帮我看看那里出现了问题,谢谢 #include  \"msp430g2553.h\" #define uchar unsigned char long temp; void uart_init(void) {         BCSCTL1 = CAL ...…

查看全部问答>