• PicŪ Basic


  • 18F2331 Basic PWM Code

    Had a play with the Motor Control PWM module on the 18f2331. Here is some basic code that can switch PWM between PWM0 and PWM1 and ramp duty cycle up and down. Used it on a L6203 to change direction/speed on a 24V 35w Brushed gear motor. Might be helpful as a starter to somebody one day.

    John


    Code:
    ;-------------------------------------------------------------------------------
    ;**** Added by Fuse Configurator ****
    ; Use the Fuse Configurator plug-in to change these settings
    
    Device = 18F2331
    
    Declare Reminders Off
    @ CONFIG_REQ = 0 ; Override Compiler's configuration settings
    Asm-
    Config OSC = IRCIO    ;Internal oscillator block, port function on RA6 and port function on RA7
    Config FCMEN = OFF    ;Fail-Safe Clock Monitor disabled
    Config IESO = OFF    ;Internal External Switchover mode disabled
    Config PWRTEN = OFF    ;PWRT disabled
    Config BOREN = OFF    ;Brown-out Reset disabled
    Config BORV = 20    ;Reserved
    Config WDTEN = OFF    ;WDT disabled (control is placed on the SWDTEN bit)
    Config WDPS = 32768    ;1:32768
    Config WINEN = OFF    ;WDT window disabled
    Config PWMPIN = OFF    ;PWM outputs disabled upon Reset (default)
    Config LPOL = High    ;PWM0, 2, 4 and 6 are active-high
    Config HPOL = High    ;PWM1, 3, 5 and 7 are active-high
    Config T1OSCMX = On    ;Low-power Timer1 operation when microcontroller is in Sleep mode
    Config MCLRE = OFF    ;Disabled
    Config STVREN = OFF    ;Stack full/underflow will not cause Reset
    Config LVP = OFF    ;Low-voltage ICSP disabled
    Config Debug = OFF    ;Background debugger disabled; RB6 and RB7 configured as general purpose I/O pins
    Config CP0 = OFF    ;Block 0 (000200-000FFFh) not code-protected
    Config CP1 = OFF    ;Block 1 (001000-001FFF) not code-protected
    Config CPB = OFF    ;Boot Block (000000-0001FFh) not code-protected
    Config CPD = OFF    ;Data EEPROM not code-protected
    Config WRT0 = OFF    ;Block 0 (000200-000FFFh) not write-protected
    Config WRT1 = OFF    ;Block 1 (001000-001FFF) not write-protected
    Config WRTC = OFF    ;Configuration registers (300000-3000FFh) not write-protected
    Config WRTB = OFF    ;Boot Block (000000-0001FFh) not write-protected
    Config WRTD = OFF    ;Data EEPROM not write-protected
    Config EBTR0 = OFF    ;Block 0 (000200-000FFFh) not protected from table reads executed in other blocks
    Config EBTR1 = OFF    ;Block 1 (001000-001FFF) not protected from table reads executed in other blocks
    Config EBTRB = OFF    ;Boot Block (000000-0001FFh) not protected from table reads executed in other blocks
    Endasm-
    Declare Reminders On
    
    ;**** End of Fuse Configurator Settings ****
    ;-------------------------------------------------------------------------------
        Xtal 8
    
    'Set Internal Osc to 8Mhz
         OSCCON.4 = 1
         OSCCON.5 = 1
         OSCCON.6 = 1
    'Set up Ports    
         PORTA    = 0               'Clear PortA
         TRISA    = %11111111       'Set PortA to all Inputs
         PORTB    = 0               'Clear PortB
         TRISB    = 0               'Set PortB to all Outputs
         ANSEL0   = 0               'All Analogue pins digital
         PORTC    = 0               'Clear PortC
         TRISC    = 0               'Set PortC to all Outputs
    'PCPWM Initialise
         Dim PTPERVal As Word
         PTPERVal = 128
         PTPERL   = PTPERVal.LowByte
         PTPERH   = PTPERVal.HighByte
         PTCON0   = 0               'Postscale =1:1, Prescale =1:1.Free Running mode.
         PTCON1   = %10000000       'PWM time base is ON
         PWMCON0  = %00100001       'DS Page 179 .**See Note 1 below**)
         PWMCON1  = 1               'OVDCON synched to PWM time base
         DTCON    = 0               'Zero dead-time
    '***************************************************************************************************
    'According to Datasheet (P179) PWMCON0.3 needs setting for independent mode on PWM 0:1. In reality,
    'it seems to be PWMCON0.0 that needs setting.
    '***************************************************************************************************     
    'Assign Variables     
         Dim DUTY As Word
         DUTY = 0                  '10bit value for PWM (Resolution decreases with increasing frequency)
    
    'Load DUTY value into DUTY registers for PWM0 & PWM1     
         PDC0L = DUTY.LowByte 
         PDC0H = DUTY.HighByte
    
    'PWM output can be set manually for individual pins (PWM0-5 on a 18F2331)by enabling the relevant bits in the
    'OVDCOND register. 
    'The disabled PWM pins can idle low or high, by clearing or setting the relevant bit in the OVDCONS register   
    
        'PWM0 = PortB.0  Pin 21
        'PWM1 = PortB.1  Pin 22
        'PWM2 = PortB.2  Pin 23
        'PWM3 = PortB.3  Pin 24
        'PWM4 = PortB.5  Pin 26
        'PWM5 = PortB.4  Pin 25
    '***Note PWM 4 & 5 are as above, this is not a typo!****
      
         OVDCOND = %00000000     'All individual PWM outputs disabled initially.
         OVDCONS = %00000000     'All Pins set to idle low initially.
    'Added an extra loop to test something different.     
        ' goto loop1
         GoTo LOOP2
    '**********************************************************************************************************     
    LOOP1: 'Switches PWM from PWM0 to PWM1, with other pin at idle high. Works OK  Duty cycle fixed @ 512 (50%)
         OVDCOND = %00000001      'PWM active on PWM0 only
         OVDCONS = %00000010      'PWM1 idle high (Clear bit 2 for Idle low)
         High LATB.5              'Check to see if PortB.2-5 can be used for GPIO (Tested OK)
         DelayMS 2000
         OVDCOND = %00000010      'PWM active on PWM1 only
         OVDCONS = %00000001      'PWM0 idle high (Clear bit 1 for Idle low
         Low LATB.5
         DelayMS 2000
    GoTo LOOP1
    '**********************************************************************************************************
    
    '**********************************************************************************************************
    LOOP2: 'As LOOP1, but with varying Duty Cycle
    
    'Varying Duty Cycle on PWM0.Idle High on PWM1
         OVDCOND = %00000001      'PWM active on PWM0 only
         OVDCONS = %00000000      'PWM1 idle low (Set bit 2 for Idle low 
    'Ramp up on PWM0    
         For DUTY = 0 To 512
          PDC0L = DUTY.LowByte
          PDC0H = DUTY.HighByte
          DelayMS 6
         Next DUTY
         DelayMS 1000
    'Ramp Down on PWM0    
         For DUTY = 512 To 0 Step -1
          PDC0L = DUTY.LowByte
          PDC0H = DUTY.HighByte
          DelayMS 6
         Next DUTY
        
         DelayMS 500 'Allow motor time to stop
         
    'Varying Duty Cycle on PWM1. Idle High on PWM0    
         OVDCOND = %00000010      'PWM active on PWM1 only
         OVDCONS = %00000000      'PWM0 idle low (Set bit 1 for Idle low
    'Ramp up on PWM1    
         For DUTY = 0 To 512
          PDC0L = DUTY.LowByte
          PDC0H = DUTY.HighByte
          DelayMS 6
         Next DUTY
         DelayMS 1000
    'Ramp down on PWM1    
         For DUTY = 512 To 0 Step - 1
          PDC0L = DUTY.LowByte
          PDC0H = DUTY.HighByte
          DelayMS 6
         Next DUTY
         DelayMS 500   'Allow motor time to stop
    GoTo LOOP2
    This article was originally published in forum thread: 18F2331 Basic PWM Code started by pic-ignorant View original post