C语言 使用 PIC 18 PWM 控制直流电机



我使用 PIC 18 微控制器通过 PWM 控制直流电机的速度。我已经设法使用下面的代码让它旋转。我已经测试过我的H桥是100%功能的。

但是,当我打开电路时,12V 到电机,5V 到逻辑,我使用我的 RS232 通信模块向电路发送命令(我已经测试过并且它正确接收和传输),程序重置,工作台电源上的电流降至 0A。有时电机会轻微抽搐,几乎就像它试图旋转一样,但随后停止了。

有什么想法我可能出错吗?

/* 
 * File:   serial.c
 * Author: Chris Lombaard
 *
 * Created on September 13, 2013, 2:39 PM
 */
#pragma config FOSC = INTIO7    // Oscillator Selection bits (Internal oscillator block, CLKOUT function on OSC2)
#pragma config PLLCFG = OFF     // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = ON    // Primary clock enable bit (Primary clock is always enabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
#pragma config PWRTEN = OFF     // Power-up Timer Enable bit (Power up timer disabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 190       // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)
#pragma config WDTEN = OFF       // Watchdog Timer Enable bits (WDT is always enabled. SWDTEN bit has no effect)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
#pragma config CCP2MX = PORTC1  // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON      // PORTB A/D Enable bit (PORTB<5:0> pins are configured as analog input channels on Reset)
#pragma config CCP3MX = PORTB5  // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = ON      // HFINTOSC Fast Start-up (HFINTOSC output and ready status are not delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0   // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTD2   // ECCP2 B output mux bit (P2B is on RD2)
#pragma config MCLRE = EXTMCLR  // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled if MCLRE is also 1)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
#pragma config CP0 = OFF        // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
#pragma config WRT0 = OFF       // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
#pragma config EBTR0 = OFF      // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)
#include <P18F45K22.h>
#include <xc.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000
#define length(x) (sizeof(x) / sizeof(x[0]))    //Length of array
void writeUART(const unsigned char string[]);
void setup(void);
void inputCheck(void);
void stepF(void);
void stepB(void);
unsigned char buffer[8] = {''};
unsigned char prevPos = 0;
unsigned char currPos = 0;
unsigned char bufferLength;
unsigned char direction = 0;
unsigned char speed = 0;
unsigned char isSetup = 0;

char main(void){
    if(isSetup == 0){
        setup();
        writeUART("ERD 320 Practical 2 ----- Group 1n");
        writeUART("JC Lombaard - 11028786n");
        writeUART("VFDC Henriques - 11100232n");
        writeUART("William Reeler - 11228866n");
        writeUART("FAN POSITION: 1");
        PORTDbits.RD1 = 1;
        PORTDbits.RD0 = 0;
        PORTCbits.RC3 = 0;
        PORTCbits.RC0 = 0;
        PORTAbits.RA6 = 0;
    }
    while(1){
        if(PORTEbits.RE1 == 1)
            stepB();
        if(PORTEbits.RE0 == 1){
            writeUART("nFan calibrated!n");
            break;
        }
    }
    bufferLength = 0;
    while (1);
    return (EXIT_SUCCESS);
}
void interrupt high_priority isr_high(void) {
    if(PIR1bits.RC1IF == 1){
        if(RCREG1 == 'n'){
            buffer[bufferLength++] = '';
            bufferLength = 0;
            inputCheck();
        }else{
            buffer[bufferLength++] = RCREG1;
            PIR1bits.RC1IF = 0;
        }
    }
}
void interrupt low_priority isr_low(void){
    PIR1bits.TMR2IF = 0;
    TMR2 = 0;
}
void inputCheck(void) {
    const unsigned char commands[11][3] = {"S0", "S1", "S2", "S3", "S4", "P1", "P2", "P3", "P4", "R", "F"};
    unsigned char choice = 0;
    for(; choice < 11; choice++)
        if (strcmp(buffer, commands[choice]) == 0){
            break;
        }
    switch(choice){        
        case 0:
            writeUART("FAN SPEED: 0% DC");
            PORTA = 0b00111111;
            speed = 0;
            if(direction == 0){
                CCPR1L = 0x00;
            }else{
                CCPR2L = 0x00;
            }
          break;
        case 1:
             writeUART("FAN SPEED: 10% DC");
             PORTA = 0b00000110;
             speed = 0b01101110 ;
            if(direction == 0){
                CCPR1L = 0b11010000 ;
                __delay_ms(100);
                CCPR1L = 0b01101110 ;
            }else{
                CCPR2L = 0b11010000 ;
                __delay_ms(100);
                CCPR2L = 0b01101110 ;
            }
          break;
        case 2:
            writeUART("FAN SPEED: 30% DC");
            PORTA = 0b01011011;
            speed = 0b10001100;
            if(direction == 0){
                CCPR1L = 0b11010000;
                __delay_ms(100);
                CCPR1L = 0b10001100;
            }else{
                CCPR2L = 0b11010000 ;
                __delay_ms(100);
                CCPR2L = 0b10001100 ;
            }
          break;
        case 3:
            writeUART("FAN SPEED: 60% DC");
            PORTA = 0b01001111;
            speed = 0b10101101;
            if(direction == 0){
                CCPR1L = 0b11010000 ;
                __delay_ms(100);
                CCPR1L = 0b10101101 ;
            }else{
                CCPR2L = 0b11010000 ;
                __delay_ms(100);
                CCPR2L = 0b10101101 ;
            }
          break;
        case 4:
            writeUART("FAN SPEED: 90% DC");
            PORTA = 0b01100110;
            speed = 0b11010000 ;
            if(direction == 0){
                CCPR1L = 0b11010000;
            }else{
                CCPR2L = 0b11010000;
            }
          break;
        case 5:
          currPos = 1;
          if(prevPos > currPos){
              for(int i = prevPos+1; i  > currPos; i--)
                stepB();
          }else{
          }
          writeUART("FAN POSITION: 1");
          PORTDbits.RD1 = 1;
          PORTDbits.RD0 = 0;
          PORTCbits.RC3 = 0;
          PORTCbits.RC0 = 0;
          prevPos = currPos;
          break;
        case 6:
          prevPos = currPos;
          currPos = 2;
          if(prevPos > currPos){
              for(int i = prevPos+1; i  > currPos; i--)
                stepB();
          }else{
              for(int i = currPos+1; i  > prevPos; i--)
                stepF();
          }
          writeUART("FAN POSITION: 2");
          PORTDbits.RD1 = 0;
          PORTDbits.RD0 = 1;
          PORTCbits.RC3 = 0;
          PORTCbits.RC0 = 0;
          prevPos = currPos;
          break;
        case 7:
          prevPos = currPos;
          currPos = 3;
          if(prevPos > currPos){
              for(int i = prevPos+1; i  > currPos; i--)
                stepB();
          }else{
              for(int i = currPos+1; i  > prevPos; i--)
                stepF();
          }
          writeUART("FAN POSITION: 3");
          PORTDbits.RD1 = 0;
          PORTDbits.RD0 = 0;
          PORTCbits.RC3 = 1;
          PORTCbits.RC0 = 0;
          prevPos = currPos;
          break;
        case 8:
          prevPos = currPos;
          currPos = 4;
          if(prevPos > currPos){
              for(int i = prevPos+1; i  > currPos; i--)
                stepB();
          }else{
              for(int i = currPos+1; i  > prevPos; i--)
                stepF();
          }
          writeUART("FAN POSITION: 4");
          PORTDbits.RD1 = 0;
          PORTDbits.RD0 = 0;
          PORTCbits.RC3 = 0;
          PORTCbits.RC0 = 1;
          prevPos = currPos;
          break; 
        case 9:
            direction = 1;
            CCP1CON = 0b00000000;
            CCP2CON = 0b00111100;
            CCPR2L = speed;
            writeUART("FAN DIRECTION: REVERSED");
          break;
        case 10:
            direction = 0;
            CCP1CON = 0b00111100;
            CCP2CON = 0b00000000;
            CCPR1L = speed;
            writeUART("FAN DIRECTION: FORWARD");
          break;
        default:
          break;
    }
}
void stepF(void){
    for(int i = 0; i < 1; i++){
        PORTB = 0b0001;
        __delay_ms(100); //Delay between transitions
        PORTB = 0b0010;
        __delay_ms(100); //Delay between transitions
        PORTB = 0b0100;
        __delay_ms(100); //Delay between transitions
        PORTB = 0b1000;
        __delay_ms(100); //Delay between transitions
    }
}
void stepB(void){
    for(int i = 0; i < 1; i++){
        PORTB = 0b1000;
        __delay_ms(100); //Delay between transitions
        PORTB = 0b0100;
        __delay_ms(100); //Delay between transitions
        PORTB = 0b0010;
        __delay_ms(100); //Delay between transitions
        PORTB = 0b0001;
        __delay_ms(100); //Delay between transitions
    }
}
void defaultPos(void){
    PORTB = 0b1000;
    __delay_ms(100); //Delay between transitions
    PORTB = 0b0100;
    __delay_ms(100); //Delay between transitions
    PORTB = 0b0010;
    __delay_ms(100); //Delay between transitions
    PORTB = 0b0001;
    __delay_ms(100); //Delay between transitions
}
void writeUART(const unsigned char string[]){
    for(unsigned char j = 0; j < strlen(string); j++){
        TXREG1 = string[j];
        __delay_us(1000);
    }
}
void setup(void){
    isSetup = 1;
    //PORTC
    PORTC = 0x00;
    LATC = 0x00;
    TRISC = 0xC0; //Set RC6 & RC7 as inputs for EUSART
    TRISCbits.RC6 = 0;
    TRISCbits.RC7 = 1;
    ANSELC = 0x00;
    //PORTD
    PORTD = 0x00;
    LATD = 0x00;
    TRISD = 0x00;
    ANSELD = 0x00;
    //PORTE
    PORTE = 0x00;
    LATE = 0x00;
    TRISEbits.RE0 = 1;
    TRISEbits.RE1 = 1;
    ANSELE = 0x00;
    //PORTB
    PORTB = 0x00;
    LATB = 0x00;
    TRISB = 0x00;
    ANSELB = 0x00;
    PORTA = 0x00;
    LATA = 0x00;
    TRISA = 0x00;
    ANSELA = 0x00;
    //Oscillator
    OSCCON = 0b01011100; //4 MHz oscillator
    //EUSART
    TXSTA1bits.BRGH = 1; //Highspeed baudrate
    BAUDCON1bits.BRG16 = 0;
    SPBRG1 = 12; //Baudrate of 19230 (FOSC = 4 MHz, BRGH = 1, BRG16 = 0)
    TXSTA1bits.SYNC = 0; //Asynchronous
    RCSTA1bits.SPEN = 1; //Enable rx & tx pins as serial pins
    RCSTA1bits.CREN = 1; //Enable continuous reception, enable receiver
    TXSTA1bits.TXEN = 1; //Enable transmitter
    TXREG1 = 0x00;
    RCREG1 = 0x00;
    //Interrupts
    RCONbits.IPEN = 1; //Enable priorities
    INTCONbits.GIE_GIEH = 1; //Enable high priority interrupts
    INTCONbits.PEIE_GIEL = 1; //Enable low priority interrupts
    PIE1bits.TMR2IE = 1;
    IPR1bits.TMR2IP = 0;
    PIE1bits.RC1IE = 1; //Enable RX interrupt
    PIR1bits.RC1IF = 0; //Clear interrupt flag
    IPR1bits.RC1IP = 1; //High priority for RX interrupts
    //PWM
    PR2 = 0b11111001 ;
    T2CON = 0b00000100; //1 KHz pulse frequency on CCP1 pin
    CCPR1L = 0x00;
    CCPR2L = 0x00;
    CCP1CON = 0b00111100;
    CCP2CON = 0b00000000;
    TMR2 = 0;
}

一些建议,

  • 示波器?
  • 使用灯泡而不是直流电机进行测试,电流和电压降更小
  • 这闻起来像硬件问题

最新更新