PIC18 burned output

Discussion in 'Embedded Systems and Microcontrollers' started by adrenalina, Oct 14, 2014.

  1. adrenalina

    Thread Starter Active Member

    Jan 4, 2011
    78
    3
    Hello everyone. I have a circuit to control a dc motor using a DRV8837 and a PIC18F13K22. I am using the ECCP peripheral to output 2 pwm signals to control the motor speed and direction.

    The circuit was working perfectly until one output stopped working. It won't output the pwm signal (RC2) and I tried writing to the bit in the latch register and port register, but it won't output a 1.

    Does anybody know what could've cuased this issue? It has happened on 2 boards, I'm assuming there is some kind of voltage spike on that pin somehow.

    I attach a schematic. Thanks in advance.
     
  2. tshuck

    Well-Known Member

    Oct 18, 2012
    3,531
    675
    I can't imagine a spurious voltage on those input pins.

    One thing that sticks out is that you have a series resistor with Vpp, and no pullup to Vdd- which can (will) lead to problems (though it may not explain what you are seeing).

    Also, there are sometimes problems with relying on reset values as default values for variables and registers - explicitly initialize them if you need them a specific value.

    Without seeing your code, it's impossible to say you've initialized things properly.
     
  3. adrenalina

    Thread Starter Active Member

    Jan 4, 2011
    78
    3
    In the image the pull up on reset is not there, but on the circuit it is there.

    In the ISR its simply reading the bytes coming in from the I2C communication.
    The ECCP registers are initialized int PWM_Init and PWM_Set is to change the pwm and direction.
    The main loop is reading the data received through I2C and writing the PWM values.
    Code (Text):
    1. #include "Config.h"
    2. #include <p18f13k22.h>
    3.  
    4.  
    5. /*
    6. * Outputs:
    7. * - RC4 - PWM1 (Pin 3) (P1B)
    8. * - RC2 - PWM2 (Pin 11) (P1D)
    9. *
    10. * Communication:
    11. * - RB6 - SCL (I2C) (Pin 8)
    12. * - RB4 - SDA (I2C) (Pin 10)
    13. */
    14. //#define TEST
    15. volatile unsigned char i2c_reg_address;
    16. volatile unsigned char i2c_data;
    17. volatile unsigned char I2C_byte_count;
    18. volatile unsigned char i2c_data_count;
    19. volatile unsigned char i2c_data_ready;
    20.  
    21. void I2C_Init(void);
    22. void PWM_Set(unsigned char duty_cycle, unsigned char direction);
    23. void PWM_Init(void);
    24.  
    25. #pragma interrupt high_isr
    26. void high_isr(void){
    27.     unsigned char x = 0;
    28.  
    29.     // Check if interrupt was caused by I2C
    30.     if(PIR1bits.SSPIF == 1) {
    31.         if(!SSPSTATbits.D_NOT_A) {
    32.             I2C_byte_count = 0;
    33.             if(SSPSTATbits.BF){
    34.                 x = SSPBUF;
    35.             }
    36.         }
    37.         else {
    38.             I2C_byte_count++;
    39.  
    40.             if(SSPSTATbits.BF) {
    41.                 if(I2C_byte_count == 1){
    42.                     i2c_reg_address = SSPBUF;
    43.                 }
    44.                 else if(I2C_byte_count == 2) {
    45.                     i2c_data = SSPBUF;
    46.                     PIE1bits.SSPIE= 0;      // Disable MSSP Interrupt
    47.                 }
    48.                 else {
    49.                     x = SSPBUF;
    50.                 }
    51.             }
    52.         }
    53.         SSPCON1bits.SSPOV = 0;
    54.  
    55.     }
    56.     PIR1bits.SSPIF = 0;     // Clear interrupt flag
    57.     SSPCON1bits.CKP = 1;
    58.     //INTCONbits.GIEH = 1;    // Renable interrupts
    59. }
    60.  
    61. #pragma code high_vector = 0x08
    62. void high_interrupt(void) {
    63.     _asm GOTO high_isr _endasm
    64. }
    65. #pragma code
    66.  
    67.  
    68. void main(void) {
    69.     unsigned char register_address = 0;
    70.     unsigned char data = 0;
    71.     unsigned int i =0;
    72.     unsigned char motor_duty_cycle = 0;
    73.     unsigned char motor_direction = 0;
    74.  
    75.     ANSELHbits.ANS11 = 0;   // Analog function disabled
    76.     TRISBbits.TRISB5 = 1;   // RB5 set as input
    77.  
    78.     TRISCbits.RC4 = 0;      // RC4 set as output
    79.  
    80.     ANSELbits.ANS6 = 0;     // Analog function disabled
    81.     TRISCbits.RC2 = 0;      // RC2 set as output
    82.  
    83.     TRISBbits.TRISB7 = 1;    // RB7 set as input
    84.  
    85.     LATCbits.LATC2 = 0;
    86.     LATCbits.LATC4 = 0;
    87.  
    88.     I2C_Init();
    89.     PWM_Init();
    90.  
    91.     PWM_Set(60, 1);
    92.     for(i = 0; i < 1000; i++){}
    93.     PWM_Set(60, 2);
    94.     for(i = 0; i < 1000; i++){}
    95.     PWM_Set(0,0);
    96.  
    97.     while(1){
    98.         // If a stop bit was last detected transmission is over
    99.         // and data can be read.
    100.         if(!PIE1bits.SSPIE) {
    101.             INTCONbits.GIEH = 0;    // Disable interrupts
    102.             register_address = i2c_reg_address;
    103.             data = i2c_data;
    104.             INTCONbits.GIEH = 1;    // Enable interrupts
    105.             PIE1bits.SSPIE= 1;      // Enable MSSP Interrupt
    106.         }
    107.  
    108.         if(register_address == 0x01) {
    109.             motor_duty_cycle = data;
    110.             PWM_Set(motor_duty_cycle, motor_direction);
    111.         }
    112.         else if(register_address == 0x02) {
    113.             motor_direction = data;
    114.             PWM_Set(motor_duty_cycle, motor_direction);
    115.         }
    116.         else{
    117.         }
    118.     }
    119. }
    120.  
    121. void I2C_Init() {
    122.      // I2C Configuration
    123.     ANSELHbits.ANS10 = 0;   // Analog function disabled
    124.     TRISBbits.TRISB4 = 1;   // RB4 set as input
    125.  
    126.     TRISBbits.TRISB6 = 1;   // RB6 set as input
    127.  
    128.     SSPCON1bits.SSPM = 0x6; // I2C Slave mode, 7-bit address
    129.     SSPADD = 0b1011110 << 1;     // Slave address (0x5E)
    130.     SSPCON1bits.CKP = 1;
    131.     SSPCON2bits.SEN = 1;    // Clock stretching enabled
    132.  
    133.     // Interrupt configuration
    134.     PIR1bits.SSPIF = 0;     //Clear MSSP interrupt flag
    135.     IPR1bits.SSPIP = 1;     // MSSP interrupt is high priority
    136.     RCONbits.IPEN  = 1;     // Enable Interrupt priority
    137.     PIE1bits.SSPIE= 1;      // Enable MSSP Interrupt
    138.     INTCONbits.GIEH = 1;    // Enable High priority interrupts
    139.  
    140.  
    141.     SSPCON1bits.SSPEN = 1;   // Enable I2C
    142. }
    143.  
    144. void PWM_Init(){
    145.     // CCPR1L pwm duty cycle
    146.     //PWM Configuration
    147.     CCP1CONbits.CCP1M = 0b1100; // PWM mode, all outputs active high
    148.     CCP1CONbits.P1M = 0b00;     // Single output, ouputs controlled by steering
    149.     CCP1CONbits.DC1B = 0;       // LSBs of 10-bit PWM are 0, using 8-bit PWM
    150.     PSTRCONbits.STRSYNC = 1;    // Output steering update on next PWM period
    151.     //PSTRCONbits.STRB = 1;       // Output PWM on P1B(RC4)
    152.  
    153.     // PWM Period = 4 * Tosc * (PR2+1) * (TMR2 prescale value)
    154.     // PWM period = 4 * 16MHz * 250 * 16
    155.     // PWM period = .001s or 1000kHz
    156.     //T2CONbits.T2CKPS = 0b10;    // Prescaler 16
    157.  
    158.     // Setting right now prescaler to 1 because clock is running at 1 MHz
    159.     T2CONbits.T2CKPS = 0b00;
    160.     PR2 = 249;
    161.     T2CONbits.TMR2ON = 1;       // Turn on timer 2
    162.  
    163.     CCPR1L = 0;
    164. }
    165.  
    166. void PWM_Set(unsigned char duty_cycle, unsigned char direction){
    167.     if(direction == 0){
    168.         CCPR1L = 0;
    169.     }
    170.     else if(direction == 1){
    171.         PSTRCONbits.STRB = 0;
    172.         CCPR1L = duty_cycle;
    173.         PSTRCONbits.STRD = 1;
    174.     }
    175.     else {
    176.         PSTRCONbits.STRD = 0;
    177.         CCPR1L = duty_cycle;
    178.         PSTRCONbits.STRB = 1;
    179.     }
    180. }
     
  4. tshuck

    Well-Known Member

    Oct 18, 2012
    3,531
    675
    Your initializations look fine.

    How are you verifying that the output is not working? Oscilloscope? Multimeter? LED?

    In your cycle through the PWM outputs after initialization, the PWM period is longer than the time than you allow the PWM output to be steered to a particular pin. Since you've also set the steering to update on the next PWM period (STRSYNC=1), you'd never see it with this testbench.

    Is this the code that was intermittently failing in a board?

    Have you verified the I2C comms independently?

    Did you try separate code to validate the output of the pins in question?
     
  5. adrenalina

    Thread Starter Active Member

    Jan 4, 2011
    78
    3
    I did the following to measure the outputs using a multimeter. RC2 does measure the 1, but C2 is at 0. I also tried by writing directly to the port register, but it stills outputs 0. I also looked at the pwm using an oscilloscope and RC4 does give the pwm, but RC2 does not.

    Code (Text):
    1.  ANSELHbits.ANS11 = 0;   // Analog function disabled
    2.     TRISBbits.TRISB5 = 1;   // RB5 set as input
    3.  
    4.     TRISCbits.RC4 = 0;      // RC4 set as output
    5.  
    6.     ANSELbits.ANS6 = 0;     // Analog function disabled
    7.     TRISCbits.RC2 = 0;      // RC2 set as output
    8.  
    9.     TRISBbits.TRISB7 = 1;    // RB7 set as input
    10.  
    11.     LATCbits.LATC2 = 1;
    12.     LATCbits.LATC4 = 1;
     
  6. tshuck

    Well-Known Member

    Oct 18, 2012
    3,531
    675
    Was this from a fresh configuration (e.g. brand new code)? It's possible that the ECCP module will override any LATx I/O function while it's active.

    I don't suppose you have a bare breakout board for your QFN package that you can test on, separate from the populated boards, do you?
     
Loading...