You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改AVR C代码实现RPI-1031倾斜传感器控制LED功能?

问题修复:AVR读取RPI-1031倾斜传感器仅上方LED常亮

问题背景

使用Atmel Studio编写AVR C代码,通过PORTD引脚2和3读取RPI-1031四向倾斜传感器的上/下/左/右信号,控制PORTB连接的4个对应方向LED点亮。但代码运行后仅上方LED常亮,尝试过宏定义引脚和直接读取引脚均无效。

原代码

#include <avr/io.h>
#include <util/delay.h>

#ifndef F_CPU
#define F_CPU   16000000UL
#endif

//// define input sensor on PORT D
//
//#define tilt_S1 (PIND&(1<<2))
//#define tilt_S2 (PIND&(1<<3))
//
////define output LEDs on PORT B
//
//#define LED_U (PINB&(1<<0))
//#define LED_D (PINB&(1<<1))
//#define LED_L (PINB&(1<<2))
//#define LED_R (PINB&(1<<3))

int main(void)
{
    DDRD =0x00; //port d as input
    DDRB =0xFF; //port b as out
    
    while (1)
    {
        //int pos = GetTiltPos();     //get current sensor position
        
        if ( ( (PIND & (1<<2))==0 ) && ((PIND & (1<<3))==0 ) )  //Up (North) [S1=0, S2=0]
        {
            PORTB |=  1<<PINB0;    //up   turn on TOP led only
            PORTB &= ~(1<<PINB1); //down
            PORTB &= ~(1<<PINB2); //left 
            PORTB &= ~(1<<PINB3);  //right
        }
        
        else if (((PIND & (1<<2))==1 ) && ((PIND & (1<<3))==0 ))   //Left (West)
        {
            PORTB &=  ~(1<<PINB0);    //up   
            PORTB &=  ~(1<<PINB1);    //down
            PORTB |=   1<<PINB2;       //left       turn on LEFT led only
            PORTB &=  ~(1<<PINB3);    //right
        }
        
        else if (((PIND & (1<<2))==0) && ((PIND & (1<<3))==1))    //Right (East)
        {
            PORTB &= (~(1<<PINB0));    //up   
            PORTB &= (~(1<<PINB1));    //down
            PORTB &= (~(1<<PINB2));    //left
            PORTB |=  (1<<PINB3);       //right    turn on RIGHT led only
        }
        else if ( ((PIND & (1<<2))==1 ) && ((PIND & (1<<3))==1 ) )     //Down (South)
        {
            PORTB &= ~(1<<PINB0);      //up   
            PORTB |=   1<<PINB1;         //down    turn on BOTTOM led only
            PORTB &= ~(1<<PINB2);      //left
            PORTB &= ~(1<<PINB3);      //right
        }
    }
}

//int GetTiltPos()   //function to determine position of sensor
//{
    //int S1 = 1<<PIND2;
    //int S2 = 1<<PIND3;
    //int R = ((S1<<1)| S2) ;
    //return R;
//}

问题诊断

  1. 输入引脚浮空:DDRD设为0x00后,PORTD2/3为浮空输入,无外部上拉/下拉时电平不稳定,导致传感器信号无法被正确读取,代码始终进入第一个if分支(上方LED常亮)。
  2. PORTB初始状态未清零:上电后PORTB寄存器可能残留默认电平,导致LED异常点亮。
  3. 缺少防抖处理:倾斜传感器触发时可能存在机械抖动,导致电平频繁变化,影响逻辑判断。

修改方案

1. 配置输入引脚上拉电阻

RPI-1031是开关型倾斜传感器,触发时对应引脚接地,因此需要给PORTD2/3配置内部上拉电阻,确保空闲时为高电平,触发时为低电平。

2. 初始化PORTB为全灭状态

上电时先将PORTB置0,避免残留电平导致LED异常。

3. 添加防抖延迟

在循环中加入短延迟,过滤传感器的机械抖动。

4. 简化代码逻辑(可选)

用位操作直接设置PORTB值,减少冗余代码。

修改后的代码

#include <avr/io.h>
#include <util/delay.h>

#ifndef F_CPU
#define F_CPU   16000000UL
#endif

// 传感器引脚定义
#define S1_PIN (1 << PD2)
#define S2_PIN (1 << PD3)

// LED引脚定义
#define LED_U_PIN (1 << PB0)
#define LED_D_PIN (1 << PB1)
#define LED_L_PIN (1 << PB2)
#define LED_R_PIN (1 << PB3)

int main(void)
{
    DDRD = 0x00;          // PORTD设为输入
    PORTD |= S1_PIN | S2_PIN; // 开启PORTD2/3内部上拉电阻
    
    DDRB = 0xFF;          // PORTB设为输出
    PORTB = 0x00;         // 初始化PORTB为全灭

    while (1)
    {
        uint8_t s1_state = !(PIND & S1_PIN); // 取反:触发时为1
        uint8_t s2_state = !(PIND & S2_PIN);

        // 根据传感器状态设置LED
        if (!s1_state && !s2_state) {
            PORTB = LED_U_PIN; // 仅上方LED亮
        } else if (s1_state && !s2_state) {
            PORTB = LED_L_PIN; // 仅左方LED亮
        } else if (!s1_state && s2_state) {
            PORTB = LED_R_PIN; // 仅右方LED亮
        } else if (s1_state && s2_state) {
            PORTB = LED_D_PIN; // 仅下方LED亮
        }

        _delay_ms(50); // 防抖延迟,过滤机械抖动
    }
}

额外调试建议

  • 用万用表测量PORTD2/3的电平,确认传感器倾斜时电平是否在高/低之间切换。
  • 单独测试PORTB引脚:直接设置PORTB = LED_L_PIN等,确认LED硬件连接正常。
  • 若传感器触发逻辑相反(触发时为高电平),则去掉代码中的!取反操作。

内容的提问来源于stack exchange,提问作者Mariam Ghanem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 06:20:41