我创建了一个程序来根据在端口a和端口b上按下哪个按钮来切换led灯,因为当在端口a上按下按钮时,led会从左向右或从右向左闪烁。按下按钮3时,指示灯开始从左向右弹跳并复位,并永远做下去。当按下按钮0时,它会反转方向并从右向左移动。按下按钮4时,它将再次反转方向,现在从左向右移动。我的问题是,一旦按下按钮4,就无法再通过按下按钮0来反转方向。我将如何修改代码以使其正常工作?使用PIC16F877A和PIC开发板]
#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);
}
}
使用状态变量来跟踪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
中,led_pattern
变量向左移动,一旦它“反弹”,状态便变回2
。
在任何状态下按下按钮1都会导致state
变量更改为3
。在这种状态下,就像在状态led_pattern
中一样,在循环的每次迭代过程中1
变量都向左移动,但是它不是“弹跳”而是“循环”。由于这不会改变LED的移动方向,因此状态保持3
,仅更新led_pattern
。同样,按下按钮4会将状态更改为4
,LED循环到右侧。
现在,从问题中还不能完全清楚这是否就是您希望代码执行的操作。例如,它不会等到移动的LED到达其运动的终点,然后再检查按钮。您可以随时按一个按钮,这将导致LED立即开始沿指示的方向移动。
无论如何,您应该能够看到如何仅使用一个while循环和一个或两个状态变量来实现所需的任何行为。