巧用GPIO口控制多个LED

3个IO口控制6个LED灯

这个电路用到了单片机GPIO的三种状态:

  • 高电平

  • 低电平

  • 高阻态

 所谓“高阻态”,是指GPIO对外部电路表现出极大的阻抗。因阻抗很大,几乎不会吸入电流,也不会对外输出电流。

各个LED灯单独亮起,分为六种情况。

1、当只有LED1亮起时,单片机各GPIO的状态如下:(带箭头的红线为电流回路)

2、当只有LED2亮起时,单片机各GPIO的状态如下:

3、当只有LED3亮起时,单片机各GPIO的状态如下:

4、当只有LED4亮起时,单片机各GPIO的状态如下:

5、当只有LED5亮起时,单片机各GPIO的状态如下:

6、当只有LED6亮起时,单片机各GPIO的状态如下:

整理如下:

就是这么简单!

使用该方法,n个GPIO可以驱动 n*(n-1) 个LED,所以:

  • 使用2个GPIO可以驱动2个LED。

  • 使用3个GPIO可以驱动6个LED。

  • 使用4个GPIO可以驱动12个LED。

  • 以此类推。

这种方式能够实现的基础是:

  • 单片机GPIO的三个状态:高电平、低电平、高阻态。

  • LED具有单向导电性。

查理复用设计的方法:

  • 任意两个GPIO引脚之间串入两个LED,这两个LED为并联,且LED方向相反。

  • 当你想要点亮某个特定的LED时,就将其两端所连接到的GPIO引脚分别设定为高电平和低电平,其它剩余的GPIO引脚设定为高阻态。

  • 前面电动牙刷中6个LED灯的电路,就是这么设计的。

下面从最简单的开始,一步一步体会查理复用的电路设计。

1、使用2个GPIO时最简单:

LED1亮起时:

LED2亮起时:

这里只用到高电平、低电平的状态,不需要用高阻态的状态。

2、使用3个GPIO时,前面已经分析过:

可以等效为下图:

可以看出,确实是任意两个GPIO之间均串入了两个并联的LED,且LED方向相反。

查理复用这样的电路接法也会引发一些问题。

首先,LED亮起时完全由单片机的GPIO输出电流,所以对于GPIO的电流驱动能力有一定的要求。设计电路时要注意查询自己使用的MCU的电流驱动能力,下图是STM32单片机中对GPIO电流驱动能力的说明:

其次,如果出现了某个LED开路或短路的情况,电流的流向会被打乱,LED亮起来的逻辑会变得错乱。最坏的情况下,电路会对GPIO索取大电流,导致单片机损坏。下图是假设LED1短路,那么在点亮LED5时,LED3也会亮起:

  • 14
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
可以使用PWM(脉宽调制)控制LED的亮度。首先,要在STM32上配置定时器,定时器可以作为计数器,也可以用来产生PWM输出。然后,通过改变占空比来达到不同亮度的控制。占空比实际上是以高电平时间占总周期时间的百分比,这决定了PWM信号的亮度。代码示例如下: ``` #include "stm32f10x.h" void TIM3_PWM_Init(u16 arr, u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; // Enable clock for TIM3 and GPIOB RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // Initialize GPIOB.4, GPIOB.5, GPIOB.6 as alternative function push-pull GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // Set Timer 3 to 1kHz (1ms) clock TIM_TimeBaseInitStruct.TIM_Period = arr; // ARR:计数器自动重装值,决定了PWM信号的输出频率,高频率就是短的亮度时间和渐变 TIM_TimeBaseInitStruct.TIM_Prescaler = psc; //定时器分频系数是通过 TIM_PSC 寄存器控制的,psc 肯定是提前算好的一个数字,分配 SystemCoreClock,以得到一个计数器内部时钟的频率,为 x MHz TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct); // Configure the PWM channels TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStruct.TIM_Pulse = 0; TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM3, &TIM_OCInitStruct); TIM_OC2Init(TIM3, &TIM_OCInitStruct); TIM_OC3Init(TIM3, &TIM_OCInitStruct); // Enable Timer 3 TIM_Cmd(TIM3, ENABLE); } int main() { TIM3_PWM_Init(999, 72); // 信息,ARR:999,PSC:72,pwm频率= 72MHz / (999+1) /(72+1) = 1KHz TIM_SetCompare1(TIM3, 500); //设置占空比 (0~999) TIM_SetCompare2(TIM3, 300); TIM_SetCompare3(TIM3, 700); while (1) { // do nothing } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值