如何根据使用 C、PIC16 和 PIC 开发板按下的按钮改变 LED 方向?
How to change led direction depending on button pressed using C, PIC16 and PIC development board?
我创建了一个程序来根据在端口 a 和端口 b 上按下哪个按钮来切换 LED 灯,因为当在端口 A 上按下按钮时 LED 会从左向右或从右向左闪烁。
当按下按钮 3 时,led 开始从左向右弹跳并重置并继续做同样的事情。当按下按钮 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);
}
}
编辑 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;
}
}
}
}
使用状态变量来跟踪 LED 是否应该弹跳、向左移动或向右移动,并使用没有任何嵌套 while 循环的单个 while 循环。每次通过循环你都会延迟一段时间,然后根据变量向左或向右移动 LED,然后检查按钮的状态,相应地设置状态变量。就像 Weather Vane 所说的那样,将 LED 模式也保持在变量中是个好主意。
可能的 Python-like 伪代码为
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 时,它 "bounces" 将 led_pattern
设置为 0x02(因为它在循环开始时为 0x01),并将 state
变量更改为 1
。在状态 1
中, led_pattern
变量向左移动,一旦它 "bounces" 状态变回 2
.
在任何状态下按下按钮 1 都会导致 state
变量更改为 3
。在此状态下,led_pattern
变量在循环的每次迭代期间向左移动,就像在状态 1
中一样,但不是 "bouncing",而是 "cycles"。由于这不会改变 LED 应该移动的方向,因此状态保持 3
并且仅更新 led_pattern
。同样,按下按钮 4 会将状态更改为 4
,其中 LED 向右循环。
现在从你的问题中不能完全清楚这是否真的是你想要你的代码做的。例如,在检查按钮之前,它不会等到移动的 LED 到达其移动的终点。你可以随时按下一个按钮,它会导致 LED 立即开始向指示的方向移动。
无论如何,您应该能够了解如何仅使用一个 while 循环和一两个状态变量来实现您想要的任何行为。
我创建了一个程序来根据在端口 a 和端口 b 上按下哪个按钮来切换 LED 灯,因为当在端口 A 上按下按钮时 LED 会从左向右或从右向左闪烁。 当按下按钮 3 时,led 开始从左向右弹跳并重置并继续做同样的事情。当按下按钮 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);
}
}
编辑 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;
}
}
}
}
使用状态变量来跟踪 LED 是否应该弹跳、向左移动或向右移动,并使用没有任何嵌套 while 循环的单个 while 循环。每次通过循环你都会延迟一段时间,然后根据变量向左或向右移动 LED,然后检查按钮的状态,相应地设置状态变量。就像 Weather Vane 所说的那样,将 LED 模式也保持在变量中是个好主意。
可能的 Python-like 伪代码为
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 时,它 "bounces" 将 led_pattern
设置为 0x02(因为它在循环开始时为 0x01),并将 state
变量更改为 1
。在状态 1
中, led_pattern
变量向左移动,一旦它 "bounces" 状态变回 2
.
在任何状态下按下按钮 1 都会导致 state
变量更改为 3
。在此状态下,led_pattern
变量在循环的每次迭代期间向左移动,就像在状态 1
中一样,但不是 "bouncing",而是 "cycles"。由于这不会改变 LED 应该移动的方向,因此状态保持 3
并且仅更新 led_pattern
。同样,按下按钮 4 会将状态更改为 4
,其中 LED 向右循环。
现在从你的问题中不能完全清楚这是否真的是你想要你的代码做的。例如,在检查按钮之前,它不会等到移动的 LED 到达其移动的终点。你可以随时按下一个按钮,它会导致 LED 立即开始向指示的方向移动。
无论如何,您应该能够了解如何仅使用一个 while 循环和一两个状态变量来实现您想要的任何行为。