Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Help with PIC C code

Status
Not open for further replies.

RishabhG

Member level 3
Joined
Aug 10, 2012
Messages
65
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,815
I am using PIC16F877A with a 16MHz crystal. MPLAB v8.4 HiTech C compiler
I have written the following code (Hope it is self-explanatory)

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
This program does the following:
                  Ext int     : Start  Running the motor
                  Port b int : Stop running the motor 
    
 
Author : RKG
 
Date: 18/03/13
 
 
*/
 
 
#include<htc.h>
 
__CONFIG(0x2F0A);
 
unsigned char motor_status;
 
void delay()
{
  for(int i=0;i<750;i++);
}
 
void run_motor()
{
            PORTC=0x09;
            PORTC=0x08; // for half step sequence
            delay();
    
            PORTC=0x0C;
            PORTC=0x04; // for half step sequence
            delay();
 
            PORTC=0x06;
            PORTC=0x02; // for half step sequence
            delay();
    
            PORTC=0x03;
            PORTC=0x01; // for half step sequence
            delay();
}
void interrupt ISR()
{
    
    if(INTF==1)     
    {       
            RB1=1;
            motor_status=1; //run       
            INTF=0;
    }
    if(RBIF == 1)
    {
        RB1=0;              //turn off run LED
        RB2=1;              //glow stop LED
        motor_status=0;
        RBIF=0;
    }   
}
 
void main()
{
    TRISC=0;                    //motor o/p port
    RBPU=0;
    TRISB=0xF0;                 //i/p port
    PORTB & =0xF0;
    
    GIE=1;                      //global int enable
    INTE=1;                     //external int enable
    INTEDG=0;                   //neg edge triggered
    RBIE=1;                     //PORTB change int enable
 
    while(1)
    {
        if(motor_status==1)
        {
            run_motor();
        }
    }   
}



But the control stays always at the PORTB change interrupt ISR. Please help me find the mistake I am doing.
 

When RBIF == 1 then motor_status becomes 0. In while loop only if motor_status == 1 motor is run. You have to use if motor_status == 0 then stop_motor()

You are using RBIF i.e., PORTB interrupt and you have LEDs on PORTB? doesn't it cause false RBIF interrupts when they change state?
 

Hello!

You have to use if motor_status == 0 then stop_motor()

No! This is a stepper motor. It does not run permanently and you don't have to stop it.

However, about the program:

1. The function run motor() will do 4 steps at once. This is a waste: you buy a 400 steps per rotation
motor, and you drive it in 100 steps mode. Well, in this case, as you run it in a loop, it doesn't matter,
but I guess it's just the beginning of a real program and you will need single steps soon.

2. Your half-step sequences ares useless because there is no time for the half step itself to settle.
Example: if you do PORTC = 9 and then port C = 8, then the port C will be 9 for a very short time
(a few clocks of your processor), probably even less time than necessary for the current to stabilize.

Here is an improved version. It will also allow you to change the direction of the motor by toggling
the static dir variable between FORWARD and BACKWARD.
And as you can see, the half steps are now functional.
Note that I didn't test it so I am not absolutely sure it will compile at once, but the idea is here.

Beside this: a delay loop is never a good idea because your processor cannot do anything else,
and you cannot get an accurate timing: suppose you make an accurate delay of 1 ms, then the
total delay will also depend on the other instructions. If you add instructions, then the delay
will grow longer. Use a timer, that's what they are made for.
And at each timer interruption, you call step(). It will have the same effect, and you will be
able to do something else between interrupts.

Dora


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<htc.h>
 
__CONFIG(0x2F0A);
 
const uint8 stepval[] = {
    0x09, 0x08, 0x0C, 0x04, 0x06, 0x02, 0x03, 0x01
};
 
#define FORWARD     1
#define BACKWARD    (-1)
 
static uint8 dir = FORWARD;
 
unsigned char motor_status;
 
void delay() {
  for(int i=0;i<750;i++);
}
 
void step() {
    static int8 crtstep = 0;
    crtstep += dir;
    if(step > 7) step = 0;
    if (step < 0) step = 7
    PORTC = stepval[step];
    delay();
}
void interrupt ISR() {
    if(INTF==1) {
        RB1=1;
        motor_status=1; //run       
        INTF=0;
    }
    if(RBIF == 1) {
        RB1=0;              //turn off run LED
        RB2=1;              //glow stop LED
        motor_status=0;
        RBIF=0;
    }   
}
 
void main() {
    TRISC=0;            //  motor o/p port
    RBPU=0;
    TRISB=0xF0;         //  i/p port
    PORTB & =0xF0;
    
    GIE=1;              //  global int enable
    INTE=1;             //  external int enable
    INTEDG=0;           //  neg edge triggered
    RBIE=1;             //  PORTB change int enable
 
    while(1) {
        if(motor_status==1) {
            step();
        }
    }   
}

 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top