"Knight rider" in C

Hi, I have this code for a night rider - like thing for a PIC16F628

 

#include <pic.h> 

#include <HTC.h>

#define _XTAL_FREQ 4000000    

__CONFIG( UNPROTECT & LVPDIS & BORDIS & MCLREN & WDTDIS & 0x3FFD);

void delay(void); 

 

void main(void) { 

TRISB = 0x00;

while (1) 

{

PORTB = PORTB << 1;

delay(); 

 

if(PORTB == 0){

PORTB = 1;

delay();

 

} else {

 

if(PORTB == 0b10000000){

PORTB = PORTB >> 1;

delay();

}

}

}

}

void delay(void) { 

unsigned int i,j,k; 

for (i=0; i<100; i++) 

for (j=0; j<20; j++) 

k=j; //just to waste time 

}

 

 

However it doesn't work, and I know why, but I don't know how to make it work!

 

if you have MPlab run it in the simulator and see what happens...

 

PORTB does this:

00000001

00000010

00000100

00001000

00010000

00100000

01000000

10000000

01000000

10000000

01000000

 

because after getting to 10000000 it shifts right, so I get 01000000, but then it shift left again, so I have 10000000 again, I have wasted about the whole afternoon trying to get this to work...

 

thanks.

try something like to

try something like to replace those IFs

unsigned int aux_var;

while (1) 

{

for ( aux_var=0; aux_var<8; aux_var++)

{

PORTB = PORTB >> 1;

delay();

}

aux_var = 0;

for ( aux_var=0; aux_var<8; aux_var++)

{

PORTB = PORTB << 1;

delay();

}

}

goncaloc’s code works

goncaloc’s code works because it executes a full right shift sequence followed by a full left shift sequence.

If you wanted the program to work the way you were writing it, you’d need to add an extra boolean/bit variable to indicate the direction the PORTB register is to be shifted. When the active LED hits one end of the register, you flip the boolean value and the LED takes off in the opposite direction. Something like this:

int d = 0;

while (1) {

if(d==0) {

PORTB = PORTB << 1;

}

else {

PORTB = PORTB >> 1;

}

delay();

if(PORTB == 0) {

PORTB = 1;

delay();

}

else if(PORTB == 0b10000000) {

d = 1;

}

else if(PORTB == 0b00000001) {

d = 0;

}

}

BTW, the reason your code

BTW, the reason your code shifts back left again is that you do

PORTB = PORTB << 1;

at the start of the while() loop, no matter what the value in PORTB

Thanks dude, It didn’t

Thanks dude, It didn’t exactly work like that, but after changing it to:

#include

#include 
#define _XTAL_FREQ 4000000
unsigned int aux_var;
__CONFIG( UNPROTECT & LVPDIS & BORDIS & MCLREN & WDTDIS & 0x3FFD);

void delay(void);
void shift_right(void);
void shift_left(void);

void main(void) {
TRISB = 0x00;

while (1)
{
for ( aux_var=0; aux_var<8; aux_var++)
{
if(PORTB == 0){
PORTB = 1;
}
PORTB = PORTB << 1;
delay();
}
aux_var = 0;
for ( aux_var=0; aux_var<8; aux_var++)
{
if(PORTB == 0){
PORTB = 0b10000000;
}
PORTB = PORTB >> 1;
delay();
}
}
}

void delay(void) {
unsigned int i,j,k;
for (i=0; i<100; i++)

for (j=0; j<20; j++)
k=j; //just to waste time

}

It works in the simulator, gonna burn it in the chip now and check.

 

 

thanks again :smiley:

 

the missing libraries in the include disappeared because <> are using in html, and I’m using the html editor. so never mind that.

 

yep, also works on the PIC!

images.jpg

Aye, thanks for answering

Aye, thanks for answering :smiley:

though now I see that this way wastes resources.

They’re about the same

They’re about the same really, both require a value to act as ‘memory’ (aux_var, d) so the PIC knows what part of the sequence it’s up to.

If you want to free up some resources the first thing you should look at is replacing that delay loop with a timer based routine. Start by polling the timer complete flag, and then give the timer interrupt a try.