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.

PIC12F675 C code doesnt work

Status
Not open for further replies.
T

treez

Guest
Hello
Do you know why this C code for PIC12F675 doesn’t work?
Its using XC8 C
All it does is make GP0 = 0 if the ADC reads the ‘busvoltage’ variable as being greater than 0x19. If the ‘busvoltage’ variable is less than 0x19 then it should make GP0 = 1;

However, it does not work.
I think its the ADC function doADC(); ...but i am not sure.

When i don’t call the doADC function i have got it able to oscillate the GP0 output. (but i don’t want the code to do that, we want the code to read ADC and act accordingly.)

Code:
//Main for the crammed long PCB

//Each Buckboost has a PIC12F675 to control it.


// PIC12F675 Configuration Bit Settings
// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include [I]<[/I]xc.h>
#include [I]<[/I]stdint.h>
#include [I]<[/I]pic12f675.h>

#define  _XTAL_FREQ 4000000
//#define  driversOff   GP0 = 1
//#define  driversOn    GP0 = 0
//#define  udhigh       GP2 = 1
//#define  udlow        GP2 = 0
//#define  cshigh       GP5 = 1
//#define  cslow        GP5 = 0


        uint8_t   count;
        uint8_t   count1;
        uint8_t   count2;
        uint8_t   busvoltage;
  
void zeropot(void);
void decrement(void);
void increment(void);
void doADC(void);
void up5steps (void);
void up35steps (void);
void up64steps (void);
         
        void up5steps (void) {
        for (count=5; count=0; count--) { 
        __delay_us(100);
        GP2 = 0;    //UD = low
        __delay_us(100);
        GP2 = 1;    //UD = high
        __delay_us(100);
        }
        return;
        }
        
        void up35steps (void) {
        for (count=35; count=0; count--) { 
        __delay_us(100);
        GP2 = 0;    //UD = low
        __delay_us(100);
        GP2 = 1;    //UD = high
        __delay_us(100);
        }
        return;
        }
        
        void up64steps (void) {
        for (count=64; count=0; count--) { 
        __delay_us(100);
        GP2 = 0;    //UD = low
        __delay_us(100);
        GP2 = 1;    //UD = high
        __delay_us(100);
        }
        return;
        }
   
        void doADC(void) {
        //Initiate ADRESH, ADRESL
        busvoltage = 0x00;
        ADRESL = 0x00;
        __delay_us(100);
        ADON = 1;   //Turn on ADC module
        __delay_ms(1);
        GO_DONE = 1;    //start conversion
        while (GO_DONE) {;}     //Wait for conversion to finish
        __delay_us(100);
        busvoltage = ADRESL;
        ADON = 0;   //Turn off ADC module
        __delay_us(100);
        return;
        }
        
        void increment(void) {    //GET DIGIPOT READY FOR INCREMENT
        __delay_us(100);
        GP5 = 1;    //CS HIGH
        __delay_us(100);
        GP2 = 0;    //UD low
        __delay_us(100);
        GP2 = 1;    //UD high
        __delay_us(100);
        GP5 = 0;    //CS LOW  ....NOW inCREMENT
        __delay_us(100);
        return;
        }
        
        void decrement(void) {    //GET DIGIPOT READY FOR DECREMENT
        __delay_us(100);
        GP5 = 1;    //CS HIGH
        __delay_us(100);
        GP2 = 1;    //UD high
        __delay_us(100);
        GP2 = 0;    //UD low
        __delay_us(100);
        GP5 = 0;    //CS LOW  ....NOW DECREMENT
        __delay_us(100);
        return;
        }
        
        void zeropot(void) {  //get wiper to bottom of resistor ladder, ie GND
        //ZERO THE DIGI POT
        __delay_us(100);
        GP5 = 1;    //CS HIGH
        __delay_us(100);
        GP2 = 1;    //UD HIGH
        __delay_us(100);
        GP2 = 0;    //UD LOW
        __delay_us(100);
        GP5 = 0;    //CS LOW  ....NOW DECREMENT
        __delay_us(100);     
        //Now decrement 64 times
        for (count = 65; count = 0; count--) {
            __delay_us(100);
            GP2 = 1;
            __delay_us(100);
            GP2 = 0;
            __delay_us(100);
        }                       //Now wiper is at the bottom.
        return;
        }
  


void main(void) {
    //Setup ports
    //GP0 = OP  SHUTDOWN; High is shutdown
    //GP1 = OP  UNUSED OUTPUT   
    //GP2 = OP  U/D MCP4013
    //GP3     = IP  MCLR
    //GP4/AN3 = IP  ADC input from input rail
    //GP5 = OP  CS MCP4013
    
    //To increment CS LOW, AFTER UD high
    //To decrement CS lOW AFTER UD LOW
    
    //HW SETUP
        GP0 = 1;    //SHUTDOWN
        GP1 = 0;    //UNUSED
        GP2 = 0;   //UD LOW
        //GP3 = INPUT
        //GP4 = ADC INPUT
        GP5 = 1;  //CS HIGH
        TRISIO = 0x18;   //ADC IN
        INTCON = 0x00;
        OPTION_REG = 0xD7;
        CMCON  = 0x07;
        ADCON0 = 0x0C;  //0000-1100 ADCoff_noconv; ch AN3; VREF=VDD;ADON is OFF//L just       
        ANSEL  = 0x68;   //fosc/64, AN3,

        //5 second delay
        for (count=1;count<=10;count++)   {
        __delay_ms(1);
        }
        
        GP0 = 1;    //Shutdown the led drivers
        zeropot();
        increment();
        up64steps();
       
        GP0 = 0;    //Turn on LEDs
        
        doADC();
        if (busvoltage >= 0x19) {GP0 = 1;}
        
        
        while(1) {;}
        
        
     /*   while(1) {
        GP0 = 1;    //driversOff;
        for (count=1;count<=10;count++)   {
        __delay_ms(100);                   }
        GP0 = 0;    //driversOn;
        for (count=1;count<=10;count++)   {
        __delay_ms(100);                   } 
        
        }     */
        
        
        
        return;

}
 
Last edited by a moderator:

Seems to have lots of delays in there that do nothing!
However, your fundamental problem is you read AN0 instead of AN3, try changing ADCON0 to 0x4D.

Brian.
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
Agreeing totally with Brian on remarking the unnecessary use of delays spread along the whole code, the only exception where I would opportunely include a delay is in the following section, between both instructions:

Code:
GP0 = 0;    //Turn on LEDs
        
        doADC();

The reason for this - and many people may consider an exaggerated care - is that whenever we take the VDD as a positive reference for the A/D (as you did), either if the layout routing of the grounding, or decoupling capacitor is not sufficiently effective, immediately before the sample of the voltage to be converted, the analogue input may vary, albeit little, but in a 10-bit conversion even a 0.1% voltage drop impacts on the acuracy of the result. In short, it is not totally unplausible to consider that the sudden current sinked by the LED right before conversion could somehow affect the VDD, therefore a little delay there would help more than disturb.

- - - Updated - - -

Obviously, the above mentioned condition is considering the usual scenario in which the function ADC() does not already have those unnecessary delays inside.
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
There are multiple '#include' statements with no files. Also you *must* reference 'xc.h' as the first include.
The 'for' loops in 'up5steps' (etc.) are wrong in that the 2nd statement should be a comparison (e.g. 'for(count=5; count==0, count--)' - you have 'count=0;'). And, as previously mentioned, you have one too many calls to the delay macro.
Also for those 3 functions, why not have a single function and pass a parameter with the number of 'toggles'?
Susan
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
Hi,

There are multiple '#include' statements with no files
This is a known problem of the forum HTML parser. It treats the text between "<" and ">" as tags....

I've just corrected this in the post above. Now the names are visible.

Klaus
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
Code:
for (count=35; count=0; count--) {

This looks completely wrong to me. Try...

Code:
for (count = 35 ; count > 0; count--) {

And same change for the other similar functions.
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
Or better still make a general routine for any number of steps and pass the required number as a parameter, for example "upsteps(64);"

Code:
        void upsteps (uint8_t StepCount) 
        {
            for (count=StepCount; count>0; count--)
            { 
                GP2 = 0;    //UD = low
                __delay_us(100);
                GP2 = 1;    //UD = high
                __delay_us(100);
            }
        return;
        }


or for even shorter but general code, use "while(StepCount--) ......"

Brian.
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
Or better still make a general routine for any number of steps and pass the required number as a parameter, for example "upsteps(64);"

Or even going a little further...:wink:
To improve reusability of the code, this routine could have also delay duration configurable:

Code:
        void upsteps (uint8_t StepCount, uint16_t HighState, uint16_t LowState) 
        {
            for (count=StepCount; count>0; count--)
            { 
                GP2 = 0;    //UD = low
                __delay_us(LowState);
                GP2 = 1;    //UD = high
                __delay_us(HighState);
            }
        return;
        }
 

You could pass the port number as well....

I was expecting someone suggest the same...:wink:


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
void upsteps (uint8_t StepCount, uint16_t HighState, uint16_t LowState, uint8_t PortNum) 
        {
            for (count=StepCount; count>0; count--)
            { 
                (BANKMASK(GPIO), PortNum) = 0;    //UD = low
                __delay_us(LowState);
                (BANKMASK(GPIO), PortNum) = 1;    //UD = high
                __delay_us(HighState);
            }
        return;
        }



Perhaps would issue syntax errors at compilation...anyway, it's a start point.
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
So minimally:
Code:
void upsteps (uint8_t StepCount, uint16_t HighState, uint16_t LowState, uint8_t PortNum) 
        {
            while(StepCount--)
            { 
                (BANKMASK(GPIO), PortNum) = 0;    //UD = low
                __delay_us(LowState);
                (BANKMASK(GPIO), PortNum) = 1;    //UD = high
                __delay_us(HighState);
            }
        }
I removed the 'return' as well as it is a void function. I don't think the compiler would object to that.
We should buy shares in Treez company if we are going to write software for it!

Brian.
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
Thankyou guys.....if i had shares, i would give you guys the lions share.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top