基础STM32的LED控制程序学习笔记

要写一个程序首先得明白写程序的目的,也就是需要实现的是什么,然后在进一步分析需要用到什么模块和主控的哪些功能引脚,就比如一个最简单的基于stm32的led控制程序:首先我们需要他点亮,点亮了之后可以闪烁,然后为了高级一点再加一个流水灯,也就是几个led依次闪烁。

第一步:led的控制需要用到的是GPIO引脚和时钟使能,需要将引脚拉高才能点亮,就需要加上GPIO的启动文件以及CORE文件,core应该就是启动文件,这个待后续了解。

第二步,初始化led对应的GPIO口,比如我的板子的4个led接的就是PG6、PA8、PB8和PB9,首先定义一个自己的GPIO初始化结构体,然后使能对应GPIO的时钟,这里的GPIO全都是挂接在APB2这个时钟上的,所以使能这四个I/O口的时钟即可,然后就是配置GPIO了,这里配置是使用的32启动程序中自带的结构体,当然被我们重定义名称了。其中结构体中需要配置是引脚(GPIO_Pin)、I/O口的速度(GPIO_Speed)、I/O口的输出模式(GPIO_Mode)、以及引脚初始化(GPIO_Init)。

第三步,写一个让i/o口输出低电平(点亮)的函数,函数中只需要用到GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)这个系统函数,这个函数的意思就是将对应引脚的电平拉低,一共写是三个,这里写三个是因为有两个引脚的GPIO是一样的,所以 |(或)一下就可以了,意思是该函数运行,四个灯都亮。代码如下:

void leds_on(void)

{

   //LED指示灯D1的引脚(PG6)输出低电平,即点亮D1

   GPIO_ResetBits(GPIOG,GPIO_Pin_6);

   //LED指示灯D2的引脚(PA8)输出低电平,即点亮D2

 GPIO_ResetBits(GPIOA,GPIO_Pin_8);

 //LED指示灯D3、D4的引脚(PB8 PB9)输出低电平,即点亮D3、D4

 GPIO_ResetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9);

}

如果想写全不亮的函数则用GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)这个函数,将电平拉高,我这里的led是低电平发光的。

第四步,写一个带参数输入的函数,参数为LED的引脚编号。引脚编号需要在.h文件中定义,代码如下:

#define LED_1          (GPIO_Pin_6 | (1UL<<16))

#define LED_2          (GPIO_Pin_8 | (2UL<<16))

#define LED_3          (GPIO_Pin_8 | (3UL<<16))

#define LED_4          (GPIO_Pin_9 | (4UL<<16))

其中1UL<<16是: LED 指示灯对应的引脚分属不同的数据端口,可能会存在的数据端口不同但引脚编号一样的情况(如LED2 和 LED3,引脚编号都是 8,但分别属于数据端口 GPIOA和 GPIOB),为了区分,在高 16 位上增加了和 LED 对应的编号。查看管脚定义可以知道,引脚是被强制转换为16进制的地址值,所以在高16上做标记不会有影响。然后在函数中定义一个无符号的16位整数型变量,用于存放引脚的编号,&(与)上0xffff取到高16位的编号,然后做判断将GPIOx的BSRR(这里只用到低16位,端口为设置寄存器,拉高是熄灭)赋值对应编号,用于熄灭LED

代码如下:

/***************************************************************************

 * 描  述 : 熄灭一个指定的LED

 * 参  数 : [IN]led_idx:LED 对应的引脚编号

 * 返回值 : 无

 ***************************************************************************/

void led_off(uint32_t led_idx)

{

   //取得引脚的编号

 uint16_t pin_num = (uint16_t)(led_idx&0xFFFF);

 //区分数据端口,并驱动pin_num对应的引脚输出高电平,即熄灭对应的LED

 if(led_idx == LED_1)GPIOG->BSRR = pin_num;

 if(led_idx == LED_2)GPIOA->BSRR = pin_num;

 if((led_idx == LED_3) || (led_idx == LED_4))

 {

   GPIOB->BSRR = pin_num;

 }

}

第五步,另起一个点亮led带参数的函数,与上述函数一样,不同点只在于用的寄存器不同,上述用的BSRR(置位寄存器),这里点亮的话需要用到GPIO的BRR(复位寄存器),代码如下:

/***************************************************************************

 * 描  述 : 点亮一个指定的LED

 * 参  数 : [IN]led_idx:LED 对应的引脚编号

 * 返回值 : 无

 ***************************************************************************/

void led_on(uint32_t led_idx)

{

   //取得引脚的编号

 uint16_t pin_num = (uint16_t)(led_idx&0xFFFF);

 //区分数据端口,并驱动pin_num对应的引脚输出低电平,即点亮对应的LED

 if(led_idx == LED_1)GPIOG->BRR = pin_num;

 if(led_idx == LED_2)GPIOA->BRR = pin_num;

 if((led_idx == LED_3) || (led_idx == LED_4))

 {

  GPIOB->BRR = pin_num;

 }

}

第六步,在主函数中调用这些函数就行了。这样一个LED灯的控制程序就完成了;比如我想让LED1亮,则调用led_on(LED1)即可。

简单提一下,翻转LED灯,使用GPIO的ODR寄存器,使用异或运算来让对应的I/O状态翻转,代码贴上:

/***************************************************************************

 * 描  述 : 翻转一个指定的LED的状态

 * 参  数 : [IN]led_idx:LED 对应的引脚编号

 * 返回值 : 无

 ***************************************************************************/

void led_toggle(uint32_t led_idx)

{

   //取得引脚的编号

 uint16_t pin_num = (uint16_t)(led_idx&0xFFFF);

 //区分数据端口,通过对ODR寄存器相应的位异或运算翻转对应的IO输出状态

 if(led_idx == LED_1)

 {

 GPIOG->ODR ^= pin_num;

 }

 if(led_idx == LED_2)

 {

 GPIOA->ODR ^= pin_num;

 }

 if((led_idx == LED_3) || (led_idx == LED_4))

 {

 GPIOB->ODR ^= pin_num;

 }

}

以上为学习的总结,不到之处望指正。感谢!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值