如何根据使用C,PIC16和PIC开发板按下的按钮来更改LED方向?

时间:2019-11-16 17:50:08

标签: c assembly pic

我创建了一个程序,以根据端口a和端口b上按下哪个按钮来改变led灯,因为在端口a上按下按钮时,led会从左向右或从右向左闪烁。 按下按钮3时,指示灯开始从左向右弹跳并复位,并永远做下去。当按下按钮0时,它会反转方向并从右向左移动。 按下按钮4时,它将再次反转方向,现在从左向右移动。 我的问题是,一旦按下按钮4,就无法再通过按下按钮0来反转方向。我将如何修改代码以使其正常工作? 使用PIC16F877A和图片开发板

#include <system.h>

void delay(int j) {
int i;
int x = 8600;
while (j != 0) {
    for (i = x; i != 0; i--);
    j--;
}
}

void main() {

trisb = 0; // sets all bits in port B as outputs
adcon1 = 0x06; // sets port A as digital inputs
while (1) // creates infinite loop
{

    if ((porta & 0x8)) { // Switch 3 - Left bounces from left to right and right to left

        portb = 0x80;
        delay(1);

        while (1) {
            while ((portb != 0)) { // Shifts LED from left to right as long as LED 0 is not active
                portb = portb >> 1;
                delay(1);

                if ((portb == 0)) { // When LED 0 is lit, it resets to LED 7
                    portb = 0x80;
                    delay(1);
                }

                if ((porta & 0x1)) { // If SA0 is pressed, LED shifting direction will reverse (right to left)
                    while ((portb != 0x80)) {
                        portb = portb << 1;
                        delay(1);
                        if ((portb == 0x80)) {
                            portb = 0x1;
                            delay(1);
                        }
                        if ((porta & 0x10)) { // If SA4 is pressed, LED shifting direction will reverse (left to right)
                            while ((portb != 0)) {
                                portb = portb >> 1;
                                delay(1);
                                if ((portb == 0)) {
                                    portb = 0x80;
                                    delay(1);
                                }
                            }

                        }
                    }

                }


            }

        }

    }

}

}

编辑:

void shiftRight() {

char value;
value = 0x80;

for (int i = 0; i < 8; i++) {
    portb = value;
    value = value >> 1;
    delay(1);
}

}

void shiftLeft() {

char value;
value = 0x1;

for (int i = 0; i < 8; i++) {
    portb = value;
    value = value << 1;
    delay(1);
}
}

编辑2:

#include <system.h>

void delay(int j) {
int i;
int x = 8600;
while (j != 0) {
    for (i = x; i != 0; i--);
    j--;
}
}

void shiftRight() {

char value = 0b10000000;


for (int i = 0; i < 8; i++) {
    portb = value;
    value = value >> 1;
    delay(1);
}

 }

void shiftLeft() {

char value = 0b00000001;


for (int i = 0; i < 8; i++) {
    portb = value;
    value = value << 1;
    delay(1);
}
}

void main() {

trisb = 0; // sets all bits in port B as outputs
adcon1 = 0x06; // sets port A as digital inputs


int movingRight = 1; //which way the led is moving - 0 = left, 1 = right

// creates infinite loop
while(1)
{

    if(movingRight == 1)
    {
        //led is moving right   
        shiftRight();

        if((porta & 0b00000001) && portb == 0b00000001) /*right button is pressed AND led is at the far right*/ 
        {
            //flip direction
            movingRight = 0;
        }
    }
    else
    {
        //led is moving left
        shiftLeft();

        if((porta&  0b00010000) && portb == 0b10000000) /*left button is pressed AND led is at the left right*/
        {
            //flip direction
            movingRight = 1;
        }
    }
}
}

1 个答案:

答案 0 :(得分:1)

使用状态变量来跟踪LED是应该跳动,向左移动还是向右移动,并使用单个while循环而不嵌套任何while循环。每次循环时,您都会延迟一段时间,然后根据变量向左或向右移动LED,然后检查按钮的状态,并相应地设置状态变量。就像Weather Vane所说,将LED模式也保持可变也是一个好主意。

可能是类似Python的伪代码

state = 0  # 0 = LEDs off
           # 1 = LEDs bounce left
           # 2 = LEDs bounce right
           # 3 = LEDs cycle left
           # 4 = LEDs cycle right
led_pattern = 0x00 

while True:
    set_leds(led_pattern)          # portb = led_pattern

    delay()

    # Update led_pattern according to the current state

    if state == 1 or state == 3:   # bounce or cycle left
        led_pattern <<= 1          
        if led_pattern & 0xFF == 0x00:
            if state == 1:         # bounce
                led_pattern = 0x40
                state = 2          # start bouncing right
            else:
                led_pattern = 0x01

    if state == 2 or state == 4:   # bounce or cycle right
        led_pattern >>= 1          
        if led_pattern == 0x00:
            if state == 2:         # bounce
                led_pattern = 0x02
                state = 1          # start bouncing left
            else:
                led_pattern = 0x80

    # Check the buttons and change state if necesssary

    if button_3_pressed():         # porta & 0x08
        if state == 1 or state == 3:
             state = 1             # continue moving left if already moving left
        else:
             if state == 0: 
                 led_pattern = 0x80  
             state = 2             # otherwise start moving LEDs to the right

    if button_0_pressed():         # porta & 0x01
        state = 3                  # start cycling left

    if button_3_pressed():         # porta & 0x10
        state = 4                  # start cycling right

程序将state变量设置为0,并将led_pattern变量设置为0x00。在状态0中,循环不会改变led_pattern,因此它始终保持0x00的状态,所有LED均关闭。但是,它正在检查按钮的状态,如果按下了按钮中的任何一个,它将更改状态变量的值。

在状态0中按下按钮3会使state变量更改为2,并且将led_pattern变量设置为0x80。在状态2中,循环的每次迭代将led_pattern向右移一位。如果这导致led_pattern变为0,则会将led_pattern设置为0x02反弹(因为循环开始时为0x01),并将state变量更改为{{1 }}。在状态1中,1变量向左移动,一旦它“反弹”,状态就变回led_pattern

在任何状态下按下按钮1都会导致2变量更改为state。在此状态下,3变量在循环的每次迭代过程中都向左移,就像在状态led_pattern中一样,但变量不是“反弹”而是“循环”。由于这不会改变LED的移动方向,因此状态保持1,仅更新3。同样,按下按钮4会将状态更改为led_pattern,其中LED循环到右侧。

现在从您的问题尚不清楚,这是否真的是您希望代码执行的操作。例如,它不会等到移动的LED到达其运动的终点,然后再检查按钮。您可以随时按一个按钮,这将导致LED立即开始沿指示的方向移动。

无论如何,您应该能够看到如何仅使用一个while循环和一个或两个状态变量来实现所需的任何行为。