Announcement

Collapse
No announcement yet.

3.2PTU with a Pic18F1320 UART

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • 3.2PTU with a Pic18F1320 UART

    Hey 4D systems,

    I'm working on a Project using a 3.2PTU and a Pic18F1320.

    I'm Using VisiGenie, MPLab IDE 8.92, XC8, PicKit2 and Altium for my PCB Design.
    The hardware side is done and has no flaws. Programming the chip and the screen are no problem.

    My issue is the communication between the Pic and the Screen.
    I have been able to transmit and Receive, but never both at the same time.
    I've gone over the data sheet for the configure pins and the UART set up hundreds of times.
    I've had some engineering friends look at it and we still can not figure out what to do.
    The app notes helped a lot but they did not get us to where I needed to be.

    To simplfy what im trying to do I've attached a screen shot of the Form.

    I would like to use the Leddiggits however I am not able to get them to work on the GTX so I didn't bother trying them in the code.
    I want to be able to push the UP userbutton to increase the number on the coolgauge and the DOWN userbutton to decrease it.

    That's all I want to start with for right now.

    So down to it.
    This is my transmit code with some ADC for a sensor, but thats not the important part.

    /////////////////////////////////////////////////
    #pragma config WDT = OFF, OSC = XT, FSCM = OFF, IESO = OFF, LVP = OFF, MCLRE = OFF, STVR = OFF, DEBUG = OFF, WRT0 = OFF, WRT1 = OFF, CP0 = OFF, CP1 = OFF, CPD = OFF, BOR = OFF, WRTB = OFF, WRTC = OFF, WRTD = OFF, EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF

    #include <pic18f1320.h>
    #include <xc.h>
    #include <delays.h>
    #include <adc.h>

    #define READ 0x00
    #define WRITE 0x01
    #define COOL_GAUGE 0X08
    #define FORM 0X0A
    #define USER_BUTTON 0X21
    #define ON 0X01
    #define OFF 0x00
    #define _XTAL_FREQ 4000000
    #define WASTE PORTBbits.RB3

    float PSICALC, PSIreading;
    int PSILIMIT = 40;
    void UART(void);
    void send(void);
    void geniewrite_coolGauge(unsigned char index, unsigned char value);
    void main()
    {
    ADCON1 = 0b01111110; //this adc section I am still not sure about
    TRISA = 0x01;
    TRISB = 0x10;
    UART();
    OpenADC(
    ADC_FOSC_32 &
    ADC_RIGHT_JUST &
    ADC_4_TAD, ADC_CH0 &
    ADC_VREFPLUS_VDD &
    ADC_VREFMINUS_VSS &
    ADC_INT_OFF, 0b01111101);
    while(1)
    {

    ConvertADC();
    while(BusyADC())
    {
    }
    PSIreading = ReadADC(); //read the adc and set it to PSIreading
    PSICALC = ((0.0707*(double)PSIreading- 22.013)+30); //calculated formula for the sensor I have
    //PSICALC = PSIreading*0.05859375; //Formula for a POT at 5Vs
    geniewrite_coolGauge(00,(int)PSICALC); //changing PSICALC to a number between 0-60 will change the coolgauge manually
    __delay_ms(60); //wait
    }
    }
    void UART(void)
    {
    TRISBbits.TRISB4=1; //Make UART RX pin input
    TRISBbits.TRISB1=0; //Make UART TX pin output
    SPBRGH=0; //9600bps 4MHz Osc
    SPBRG=25;

    RCSTAbits.CREN=1; // 1 = Enables receiver
    RCSTAbits.SPEN=1; // 1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
    BAUDCTLbits.BRG16=0;// 16-bit Baud Rate Generator

    TXSTAbits.SYNC=0; //0 = Asynchronous mode
    TXSTAbits.BRGH=1; //1 = High speed
    TXSTAbits.SENDB=0;
    BAUDCTLbits.SCKP=0;
    /*PIE1bits.RCIE = 1; //this is commented out as when it is not I have sever errors, it will only allow me to receive or transmit not both
    RCONbits.IPEN = 1;
    INTCONbits.GIE = 1;
    PIE1bits.TXIE = 1;*/
    }
    void geniewrite_coolGauge(unsigned char index, unsigned char value)
    {
    TXREG = WRITE;
    send();
    TXREG = COOL_GAUGE;
    send();
    TXREG = index;
    send();
    TXREG = 0x00;
    send();
    TXREG = value;
    send();
    TXREG = (WRITE ^ COOL_GAUGE ^ index ^ 0x00 ^ value);
    send();
    }
    void send(void)
    {
    TXSTAbits.TXEN=0;
    while(TXSTAbits.TRMT == 0)
    {
    TXSTAbits.TXEN=1; // enable transmission
    while(TXSTAbits.TRMT == 0 ) // wait here till transmit complete
    { NOP(); }
    }
    TXSTAbits.TXEN=0;
    }

    ///////////////////////////////////////////


    With that code I am able to change the value of the Coolgauge.
    I want to be able to press the up arrow Userbutton and have it increment the value of the coolgauge and the opposite for the down arrow.

    I would like to use the Leddiggits, however I cant even get them to change on the GTX so I didn't bother trying to use them.

    Ideally, the user button would change the Leddiggits and the coolgauge would read off and display the Pressure that the Pic detects.

    If I could get that started then I would be extremely grateful.



    Anything help is appreciated.
    I am lost at this point
    Attached Files

  • #2
    You will need to use an interrupt driven receive buffer on your PIC. You will then be able to see the responses coming back and handle them effectively.

    You should be able to google up many examples of how to setup and use an interrupt driven comms RX routine(s).
    Mark

    Comment


    • #3
      void interrupt high_priority InterruptServiceHigh()
      {
      genie_report_handler();
      }
      void UART(void)
      {
      TRISBbits.TRISB4=1; //Make UART RX pin input
      TRISBbits.TRISB1=0; //Make UART TX pin output
      SPBRGH=0; //9600bps 4MHz Osc
      SPBRG=25;

      RCSTAbits.CREN=1; // 1 = Enables receiver
      RCSTAbits.SPEN=1; // 1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
      BAUDCTLbits.BRG16=0;// 16-bit Baud Rate Generator

      TXSTAbits.SYNC=0; //0 = Asynchronous mode
      TXSTAbits.BRGH=1; //1 = High speed
      TXSTAbits.SENDB=0;
      BAUDCTLbits.SCKP=0;
      PIE1bits.RCIE = 1;
      RCONbits.IPEN = 1;
      INTCONbits.GIE = 1;
      PIE1bits.TXIE = 1;
      }

      void genie_report_handler(void)
      {
      while(PIR1bits.RCIF == 1)
      {
      data[i] = RCREG;
      i++;
      if (i>=6)
      {

      i=0;
      }
      }

      }



      I tried that here, wasn't getting what i wanted

      Comment


      • #4
        Err, would you have only received the first character?

        You need to 'reenable' the interrupt at the end otherwise it won't retrigger
        Mark

        Comment


        • #5
          Please enlighten me
          I was never very good at interrupts




          #pragma config WDT = OFF, OSC = XT, FSCM = OFF, IESO = OFF, LVP = OFF, MCLRE = OFF, STVR = OFF, DEBUG = OFF, WRT0 = OFF, WRT1 = OFF, CP0 = OFF, CP1 = OFF, CPD = OFF, BOR = OFF, WRTB = OFF, WRTC = OFF, WRTD = OFF, EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF


          #include <pic18f1320.h>
          #include <xc.h>
          #include <delays.h>
          #include <adc.h>

          #define READ 0x00
          #define WRITE 0x01
          #define COOL_GAUGE 0X08
          #define METER 0X10
          #define FORM 0X0A
          #define USER_BUTTON 0X21
          #define ON 0X01
          #define OFF 0x00
          #define _XTAL_FREQ 4000000
          #define WASTE PORTBbits.RB3


          float PSICALC, PSIreading;
          int data[6];
          int i=0;
          int PSILIMIT = 40;
          void UART(void);
          void send(void);
          void genie_report_handler(void);
          void geniewrite_coolGauge(unsigned char index, unsigned char value);
          void geniewrite_meter(unsigned char index, unsigned char value);
          void main()
          {
          ADCON1 = 0b01111110;
          TRISA = 0x01;
          TRISB = 0x10;
          UART();
          OpenADC(
          ADC_FOSC_32 &
          ADC_RIGHT_JUST &
          ADC_4_TAD, ADC_CH0 &
          ADC_VREFPLUS_VDD &
          ADC_VREFMINUS_VSS &
          ADC_INT_OFF, 0b01111101);
          while(1)
          {
          ;
          }
          }
          void interrupt high_priority InterruptServiceHigh()
          {
          genie_report_handler();
          }
          void UART(void)
          {
          TRISBbits.TRISB4=1; //Make UART RX pin input
          TRISBbits.TRISB1=0; //Make UART TX pin output
          SPBRGH=0; //9600bps 4MHz Osc
          SPBRG=25;

          RCSTAbits.CREN=1; // 1 = Enables receiver
          RCSTAbits.SPEN=1; // 1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
          BAUDCTLbits.BRG16=0;// 16-bit Baud Rate Generator

          TXSTAbits.SYNC=0; //0 = Asynchronous mode
          TXSTAbits.BRGH=1; //1 = High speed
          TXSTAbits.SENDB=0;
          BAUDCTLbits.SCKP=0;
          PIE1bits.RCIE = 1;
          RCONbits.IPEN = 1;
          INTCONbits.GIE = 1;
          PIE1bits.TXIE = 1;
          }

          void genie_report_handler(void)
          {
          while(PIR1bits.RCIF == 1)
          {
          data[i] = RCREG;
          i++;
          if (i>=6)
          {

          i=0;
          }
          }

          }

          void geniewrite_coolGauge(unsigned char index, unsigned char value)
          {
          TXREG = WRITE; send();
          TXREG = COOL_GAUGE; send();
          TXREG = index; send();
          TXREG = 0x00; send();
          TXREG = value; send();
          TXREG = (WRITE ^ COOL_GAUGE ^ index ^ 0x00 ^ value); send();
          }
          void geniewrite_meter(unsigned char index, unsigned char value)
          {
          TXREG = WRITE; send();
          TXREG = METER; send();
          TXREG = index; send();
          TXREG = 0x00; send();
          TXREG = value; send();
          TXREG = (WRITE ^ METER ^ index ^ 0x00 ^ value); send();
          }
          void send(void)
          {
          TXSTAbits.TXEN=0;
          while(TXSTAbits.TRMT == 0)
          {
          TXSTAbits.TXEN=1; // enable transmission
          while(TXSTAbits.TRMT == 0 ) // wait here till transmit complete
          { NOP(); }
          }
          TXSTAbits.TXEN=0;
          }

          Comment


          • #6
            I've Changed over to this code for the receive portion


            /////////////
            void interrupt high_priority InterruptServiceHigh()
            {
            genie_report_handler();
            }
            void genie_report_handler(void)
            {
            while(PIR1bits.RCIF == 0);
            while(PIR1bits.RCIF == 1)
            {
            data[i] = RCREG;
            }
            i++;
            if (i>=6)
            {

            i=0;
            }
            }
            ///////////////

            But I am always stuck in the "void genie_report_handler(void)"

            What am I missing

            Comment


            • #7
              So This is where im at
              Im able to receive the 6 bytes but i get stuck at the "void genie_report_handler(void)"

              Any idea on what i need to change
              Attached Files

              Comment


              • #8
                Hi Brad,

                I am not very good at the PIC controller but I might have some help to offer. The following is a segment from the code above.

                PIE1bits.RCIE = 1; // for serial RX interrupt enable
                RCONbits.IPEN = 1; // for Enabling Priority Level on Interrupts
                INTCONbits.GIE = 1; // set the Global interrupt Enable which Enables all unmasked interrupts
                PIE1bits.TXIE = 1; // enables the EUSART Transmit Interrupt Enable bit


                Quotes from datasheet:
                "If interrupt priority levels are used, this will be either the GIEH or GIEL bit. High priority interrupt sources can interrupt a low priority interrupt. Low priority interrupts are not processed while high priority interrupts are in progress."

                Since the Priority enable interrupt is used. We need to set another bit from the INTCON register to enable use of the following code:

                void interrupt high_priority InterruptServiceHigh()
                {
                genie_report_handler();
                }

                To do this, try adding the following on the UART() code.

                INTCONbits.GIEL = 0; // Low priority interrupts allowed
                INTCONbits.GIEH = 1; // Interrupting enabled.

                Hope this helps a bit.

                Regards,
                Bryan

                Comment


                • #9
                  Hey Bryan

                  Thanks for helping

                  I've got that in my code from before

                  /////////////////////////////////////////////////
                  #pragma config WDT = OFF, OSC = XT, FSCM = OFF, IESO = OFF, LVP = OFF, MCLRE = OFF, STVR = OFF, DEBUG = OFF, WRT0 = OFF, WRT1 = OFF, CP0 = OFF, CP1 = OFF, CPD = OFF, BOR = OFF, WRTB = OFF, WRTC = OFF, WRTD = OFF, EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF

                  #include <pic18f1320.h>
                  #include <xc.h>
                  #include <delays.h>
                  #include <adc.h>

                  #define READ 0x00
                  #define WRITE 0x01
                  #define COOL_GAUGE 0X08
                  #define LED_DIGITS 0X0F
                  #define FORM 0X0A
                  #define USER_BUTTON 0X21
                  #define ON 0X01
                  #define OFF 0x00
                  #define _XTAL_FREQ 4000000
                  #define WASTE PORTBbits.RB3//setup pin18 as digital output

                  float PSICALC, PSIreading;//variables for the ADC
                  unsigned int EVENT, OBJECT, INDEX, MSB, LSB, CHECKSUM, START, STOP;
                  int PSILIMIT = 18;//Pressure limit
                  int PSIUP, PSIDOWN;
                  int data[6];
                  int i=0;
                  void genie_report_handler(void);
                  unsigned char receive(void);
                  void UART(void);//UART set up
                  void send(void);//transmit
                  void geniewrite_coolGauge(unsigned char index, unsigned char value);//coolgauge output
                  void geniewrite_Leddigits(unsigned char index, unsigned char value);//Leddigits outpur
                  void main()
                  {
                  ADCON1 = 0b01111110;
                  TRISA = 0x01;
                  TRISB = 0x10;
                  UART();
                  OpenADC(ADC_FOSC_32&ADC_RIGHT_JUST&ADC_4_TAD,ADC_CH0&ADC_VREFPLUS_VDD&ADC_VREFMINUS_VSS&ADC_INT_OFF, 0b01111101);//the adc for the pressure sensor
                  while(1)
                  {
                  ConvertADC();
                  while(BusyADC())
                  {
                  }
                  PSIreading = ReadADC();//take reading from pin 1
                  PSICALC = ((0.0707*(double)PSIreading- 22.013)+30);//calculated formula for pressure sensor
                  geniewrite_coolGauge(00,(int)PSICALC);//write to coolgauge
                  __delay_ms(60);//wait
                  geniewrite_Leddigits(00,(int)PSILIMIT);//Write the Limit to the LEDDIGITS
                  WASTE = 0;//0 set pin 18 as low, 1 to set high, will activate the solenoid.
                  }
                  }
                  void UART(void)
                  {
                  TRISBbits.TRISB4=1; //Make UART RX pin input
                  TRISBbits.TRISB1=0; //Make UART TX pin output
                  SPBRGH=0; //9600bps 4MHz Osc
                  SPBRG=25;
                  RCSTAbits.CREN=1; // 1 = Enables receiver
                  RCSTAbits.SPEN=1; // 1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
                  BAUDCTLbits.BRG16=0; // 16-bit Baud Rate Generator
                  TXSTAbits.SYNC=0; //0 = Asynchronous mode
                  TXSTAbits.BRGH=1; //1 = High speed
                  TXSTAbits.SENDB=0; //Send start/stop byte
                  BAUDCTLbits.SCKP=0; // Data transmit Polarity
                  PIE1bits.RCIE = 1; // receive interrupt enabled
                  PIE1bits.TXIE = 1; // Enable Transmit interrupt
                  RCONbits.IPEN = 1; // Enable priority levels on interrupts
                  INTCONbits.GIEL = 0; // Low priority interrupts allowed
                  INTCONbits.GIEH = 1; // Interrupting enabled.
                  }
                  void interrupt high_priority InterruptServiceHigh()
                  {
                  genie_report_handler();
                  }
                  void genie_report_handler(void)
                  {
                  while(PIR1bits.RCIF == 0);
                  while(PIR1bits.RCIF == 1)
                  {
                  data[i] = RCREG;
                  }
                  i++;
                  if (i>=6)
                  {

                  i=0;
                  }
                  PIE1bits.RCIE = 0;
                  }
                  void geniewrite_coolGauge(unsigned char index, unsigned char value)
                  {
                  TXREG = WRITE; send();
                  TXREG = COOL_GAUGE; send();
                  TXREG = index; send();
                  TXREG = 0x00; send();
                  TXREG = value; send();
                  TXREG = (WRITE ^ COOL_GAUGE ^ index ^ 0x00 ^ value); send();
                  }
                  void geniewrite_Leddigits(unsigned char index, unsigned char value)
                  {
                  TXREG = WRITE; send();
                  TXREG = LED_DIGITS; send();
                  TXREG = index; send();
                  TXREG = 0x00; send();
                  TXREG = value; send();
                  TXREG = (WRITE ^ LED_DIGITS ^ index ^ 0x00 ^ value); send();
                  }

                  void send(void)
                  {
                  TXSTAbits.TXEN=0;
                  while(TXSTAbits.TRMT == 0)
                  {
                  TXSTAbits.TXEN=1; // enable transmission
                  while(TXSTAbits.TRMT == 0 ) // wait here till transmit complete
                  { NOP(); }
                  }
                  TXSTAbits.TXEN=0;
                  }

                  So that's my entire code.

                  When I have the "void interrupt high_priority InterruptServiceHigh()
                  {
                  genie_report_handler();
                  }"
                  Commented out the transmit continues to work, But the receive obviously doesn't work anymore.
                  When I uncomment it then the receive works but nothing else does as it get stuck in the interrupt routine.

                  I'm simply trying to receive the "report event" on the buttons and have them increment the Leddigits. (as seen in the attachment)

                  The adc portion works great and same with my output from the PIC,

                  I'm just stuck on that receive part.
                  Its my last hurtle and its giving me a fight.
                  Attached Files

                  Comment


                  • #10
                    Surely
                    PIE1bits.RCIE = 0;
                    should be
                    PIE1bits.RCIE = 1;
                    Mark

                    Comment


                    • #11
                      But really you don't need to play with that bit,

                      You need to clear the IF bit for the receiver (IF vs IE, can be tricky)
                      Mark

                      Comment


                      • #12
                        Thanks ill give it a try and see what happens

                        Comment


                        • #13
                          Still stuck in the "void genie_report_handler(void)"

                          Im using the debugger and checking the registers

                          So ive noticed this and im not sure if its a problem or not
                          The PIR1 is for the Flag register
                          but in the watch for microchip they are all "E's" not "F's" in the watch
                          Attached Files

                          Comment


                          • #14
                            Really, you are beyond what we can help with here.

                            I suggest you try and get a terminal type session going with the PIC.

                            And then try some people on a Microchip forum.

                            (I'm sure they have some decent / simple / small serial RX interrupt code examples somewhere)
                            Mark

                            Comment


                            • #15
                              So I have figured it out.
                              All your app notes are entirely useless and dysfunctional for the XC8 code.
                              Everything you were trying to do in them makes no sense in any way.

                              I am now receiving the Report events and getting the Acknowledge byte continuously, as I should.
                              I am able to transmit to the LED Diggits and the coolgauge simultaneously and have the user buttons increment the LED Diggits through the use of interrupts on the PIC.

                              Just thought I would give you all some feedback on a product you say works.

                              Regards
                              Brad

                              Electrical Engineer Technologist

                              Comment

                              Working...
                              X