stm32安富莱BSP学习(LED驱动)

如果不想看的可以直接使用git把我的代码下载出来,里面工程挺全的,后期会慢慢的补注释之类的

stm32学习笔记: stm32学习笔记源码 (gitee.com)(出差是公司电脑改的代码,有锁所以不能上传,只能回去了拿自己电脑上传了)

如果不会使用git快速下载可以选择直接下载压缩包或者去看看git的使用

git的使用git的使用(下载及上传_gitcode怎么下载代码-CSDN博客

有错误的地方欢迎大家多多指出,方便我修改错误,以及提升自己

目录

1 确定自己板子的硬件连接

2  宏定义

3 GPIO初始化

4 LED控制函数

4.1 LED开启函数

4.2 LED关闭函数

4.3  LED翻转函数

4.4 判断是否有输出

本系列主要为了学习安富莱源码的规范写法以及思想。

1 确定自己板子的硬件连接

我的板子硬件如下:为低电平导通,硬件连接为PB5 PB0 PB1

2  宏定义

附上安富莱的宏定义:写在bsp_led.c 里面的我个人还是喜欢宏定义和结构图在h文件,我给移到H文件去了,

这里改成了我自己的硬件GPIOB的时钟通道,以及引脚更改。

/*
	该程序适用于安富莱STM32-V4 开发板

	如果用于其它硬件,请修改GPIO定义
	
	如果用户的LED指示灯个数小于4个,可以将多余的LED全部定义为和第1个LED一样,并不影响程序功能
*/
/* 按键口对应的RCC时钟 */
#define RCC_ALL_LED 	(RCC_APB2Periph_GPIOB)

#define GPIO_PORT_LED1  GPIOB
#define GPIO_PIN_LED1	GPIO_Pin_5

#define GPIO_PORT_LED2  GPIOB
#define GPIO_PIN_LED2	GPIO_Pin_0

#define GPIO_PORT_LED3  GPIOF
#define GPIO_PIN_LED3	GPIO_Pin_1

#define GPIO_PORT_LED4  GPIOB
#define GPIO_PIN_LED4	GPIO_Pin_5

3 GPIO初始化

/*
*********************************************************************************************************
*	函 数 名: bsp_InitLed
*	功能说明: 配置LED指示灯相关的GPIO,  该函数被 bsp_Init() 调用。
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitLed(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	/* 打开GPIO时钟 */
	RCC_APB2PeriphClockCmd(RCC_ALL_LED, ENABLE);

	/*
		配置所有的LED指示灯GPIO为推挽输出模式
		由于将GPIO设置为输出时,GPIO输出寄存器的值缺省是0,因此会驱动LED点亮.
		这是我不希望的,因此在改变GPIO为输出前,先关闭LED指示灯
	*/
	bsp_LedOff(1);
	bsp_LedOff(2);
	bsp_LedOff(3);
	bsp_LedOff(4);

	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	/* 推挽输出模式 */
	
	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED1;
	GPIO_Init(GPIO_PORT_LED1, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED2;
	GPIO_Init(GPIO_PORT_LED2, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED3;
	GPIO_Init(GPIO_PORT_LED3, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED4;
	GPIO_Init(GPIO_PORT_LED4, &GPIO_InitStructure);
}

第一句:创建一个结构体变量 类型为GPIO_InitTypeDef  名字为GPIO_InitStructure

第二句:RCC_APB2PeriphClockCmd(RCC_ALL_LED, ENABLE); 

                库函数:可以在官方的rcc.c 里面找到,首先你需要清楚你使用的IO口是挂载在哪个总线下面:可以·看见所有的GPIO都在APB2下面,所有我们开启APB2的时钟

后面的这几句,就是关闭LED灯了,这个之前说过我们的LED是低电平点亮,然而GPIO输出寄存器默认值为0,所有开启后会默认点亮LED,所以这里直接关闭了LED。

    bsp_LedOff(1);
    bsp_LedOff(2);
    bsp_LedOff(3);
    bsp_LedOff(4);

之后就是往结构体写入数据:这是gpio结构体:往里面写入数据

1 GPIO的数据 2 GPIO的速度 3 GPIO的模式

1 直接写入GPIO引脚号 这里有上面结构体的定义 类型是16位短整型  这里我们之前用了宏定义:

2  类型为GPIOSpeed_TypeDef  可以选以下类型  我们选GPIO_Speed_50MHz

3 GPIO的模式:变量类型为GPIOMode_TypeDef  里面有这些类型,我们选择为推完输出:各个输出的类型区别可以去这个链接了解:

这里就写入了:GPIO_Init()  大部分外设都会将你自己创的结构体写入到init这个函数里面,他会帮你把你创的数据,赋值给各个寄存器。

这里LED2上面没有再写speed和mode,因为结构体的值是一直存在的,你没有更改的话他就是上面我们设置的这两个。

这样我们的LED灯就初始化完成了。

4 LED控制函数

4.1 LED开启函数

/*
*********************************************************************************************************
*	函 数 名: bsp_LedOn
*	功能说明: 点亮指定的LED指示灯。
*	形    参:  _no : 指示灯序号,范围 1 - 4
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_LedOn(uint8_t _no)
{
	_no--;

	if (_no == 0)
	{
		GPIO_PORT_LED1->BRR = GPIO_PIN_LED1;
	}
	else if (_no == 1)
	{
		GPIO_PORT_LED2->BRR = GPIO_PIN_LED2;
	}
	else if (_no == 2)
	{
		GPIO_PORT_LED3->BRR = GPIO_PIN_LED3;
	}
	else if (_no == 3)
	{
		GPIO_PORT_LED4->BRR = GPIO_PIN_LED4;
	}
}

函数类型无  输入参数为一个8位无符号整形  这里输入后做了一个--操作:这里我也不清楚为什么这样写:清楚的朋友可以给我留个言哈。我们led灯输入为1-4,--之后就是0-3了。

这里我们举例一个,假设输入参数为1,进来之后就为0,然后这里我们直接往GPIOB的BRR写入数据。BRR是清楚寄存器

这里往里写入1 就会清除ODR的数据。

这里我们可以看见假设我们是GPIO_PIN_5  官方库里面就是 ((uint16_t)0x0020) 这里就是0010  0000  第五位 ,所以就是将第五位写入1 从而将ODR清楚。 

4.2 LED关闭函数

/*
*********************************************************************************************************
*	函 数 名: bsp_LedOff
*	功能说明: 熄灭指定的LED指示灯。
*	形    参:  _no : 指示灯序号,范围 1 - 4
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_LedOff(uint8_t _no)
{
	_no--;

	if (_no == 0)
	{
		GPIO_PORT_LED1->BSRR = GPIO_PIN_LED1;
	}
	else if (_no == 1)
	{
		GPIO_PORT_LED2->BSRR = GPIO_PIN_LED2;
	}
	else if (_no == 2)
	{
		GPIO_PORT_LED3->BSRR = GPIO_PIN_LED3;
	}
	else if (_no == 3)
	{
		GPIO_PORT_LED4->BSRR = GPIO_PIN_LED4;
	}
}

还是一样_no- -  (不清楚为什么)之后和点亮灯一样 0-15位设置BSRR寄存器为1,为1之后ODR就会被设置为1.

 

4.3  LED翻转函数

/*
*********************************************************************************************************
*	函 数 名: bsp_LedToggle
*	功能说明: 翻转指定的LED指示灯。
*	形    参:  _no : 指示灯序号,范围 1 - 4
*	返 回 值: 按键代码
*********************************************************************************************************
*/
void bsp_LedToggle(uint8_t _no)
{
	if (_no == 1)
	{
		GPIO_PORT_LED1->ODR ^= GPIO_PIN_LED1;
	}
	else if (_no == 2)
	{
		GPIO_PORT_LED2->ODR ^= GPIO_PIN_LED2;
	}
	else if (_no == 3)
	{
		GPIO_PORT_LED3->ODR ^= GPIO_PIN_LED3;
	}
	else if (_no == 4)
	{
		GPIO_PORT_LED4->ODR ^= GPIO_PIN_LED4;
	}
}

这里就没有no--的操作了,写几进来就是几

还是举例;假设写入1 

^= :异或等于  不同为1 相同为0 :比如0010(2)0001(1) 异或就是0011(3)

然后:ODR假设为第5位为0 右侧第5位为1  异或之后就是1

          ODR为1,我们异或1  这时候ODR就会变为0,ODR就会不停翻转,到led上就是LED一直亮灭。

4.4 判断是否有输出

/*
*********************************************************************************************************
*	函 数 名: bsp_IsLedOn
*	功能说明: 判断LED指示灯是否已经点亮。
*	形    参:  _no : 指示灯序号,范围 1 - 4
*	返 回 值: 1表示已经点亮,0表示未点亮
*********************************************************************************************************
*/
uint8_t bsp_IsLedOn(uint8_t _no)
{
	if (_no == 1)
	{
		if ((GPIO_PORT_LED1->ODR & GPIO_PIN_LED1) == 0)
		{
			return 1;
		}
		return 0;
	}
	else if (_no == 2)
	{
		if ((GPIO_PORT_LED2->ODR & GPIO_PIN_LED2) == 0)
		{
			return 1;
		}
		return 0;
	}
	else if (_no == 3)
	{
		if ((GPIO_PORT_LED3->ODR & GPIO_PIN_LED3) == 0)
		{
			return 1;
		}
		return 0;
	}
	else if (_no == 4)
	{
		if ((GPIO_PORT_LED4->ODR & GPIO_PIN_LED4) == 0)
		{
			return 1;
		}
		return 0;
	}

	return 0;
}

假设写入为1:进入if这里通过ODR内存的值与库函数的值相与:按位与:相同为1不同为0  如果输出不为0  则代表ODR内的值为1 LED灯灭

所以为0时则返回1  代表已经点了

  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值