PWMx och PIC12F1572, men hur...?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Erik M
Inlägg: 1380
Blev medlem: 23 februari 2012, 18:34:39
Ort: Göteborg

PWMx och PIC12F1572, men hur...?

Inlägg av Erik M »

Efter diverse strul och besvär har jag fått någorlunda ordning på PWM med PIC12F683. Fortfarande grundligt irriterad på hur de åtta MSB och två LSB inte sitter ihop på något vettigt vis. Det är riktigt absurt vad som krävs för att få tom respektive full Duty Cycle. Nå, det är som det är med det. Får se vad för påhitt som går att trassla med vid byte till PIC12F1572...

Vad som finns att arbeta med är följande register och inställningar:
Screenshot_2016-07-04-18-38-53.jpg
Varje register och inställning är nog gott beskriven, vilket dock inte innebär att det går förstå spontant eller intuitivt hur allting hänger ihop.

Vad jag tror jag kommit fram till stannar vid att man kan välja mellan att signalen läses internt eller går ut till pinne.
Det vill säga...
OE: PWM Output Enable bit 1 = PWM output pin enabled 0 = PWM output pin disabled
Samt ett antal olika sätt rotera, starta, stoppa, interagera etc. Just nu information om än en intressant.


Hur alla dessa register sedan skall kombineras för att göra något man önskar - det är väl förborgade hemligheter. Fram tills dess att de inte är det - längre.
Men i detta nu är de just dylika hemligheter, för mig. :doh:


Hur går man tillväga för att skapa en standard PWM (PWMxMODE = 00) här?

Låt säga att Fosc är 16MHz, Period önskas vara 5us och en Duty Cycle om 25%, vad sätter man till vad?

Vi vet att:

Period = (PWMxPR + 1) * Prescale / PWMxCLK

Duty Cycle = (PWMxDC - PWMxPH) / (PWMxPR + 1)

Dock tas i dessa beräkningar ingen hänsyn till Fosc, vilket gör dem besynnerliga.
Och omöjliga att använda.

Eller ska det förstås att PWMxCLK = 1 / Fosc, i detta fall 62.5ns?

Vilket skulle ge Period * PWMxCLK = (5us * 62.5ns / Prescale) - 1 = PWMxPR
:humm:

Och sedan är det alla övriga register och inställningar...

Hur får man ihop något så enkelt som ovan? :wall:
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PWMx och PIC12F1572, men hur...?

Inlägg av sodjan »

Om jag hinner kan jag ta en koll senare. Jag misstänker
att man kan "torrsimma" och testa i MPSIM...

Men jag *gissar* att det bara är att läsa och ta en sak i taget... :-)
Erik M
Inlägg: 1380
Blev medlem: 23 februari 2012, 18:34:39
Ort: Göteborg

Re: PWMx och PIC12F1572, men hur...?

Inlägg av Erik M »

Det är för många olika saker som inte är beskrivna gentemot varandra, mer än principiellt.

Hur de olika avgränsningar fungerar går nästan att utläsa ur exempelvis FIGURE 22-4:STANDARD PWM MODE TIMING DIAGRAM.
Men det är just detta nästan som det blir för många.
Hade det varit med ett enda exempel skulle mycket varit vunnet.

Skulle uppskattas stort, Janne. :tumupp:

Att leta efter lämpliga snuttar kod på nätet är typ hopplöst.
Det mesta är skrivet i C, och inte ASM. Så dåligt med hjälp där.
Visst, det går säkert lösa ut, men lika gärna att det blir baklänges och fel.

Och jag har försökt ta det ett steg i taget.
Utan de första pusselbitarna på plats går det hopplöst långsamt att hitta de mönster som krävs för att få ihop det. Och det är för lätt att missa något ynka litet steg, som i sig sedan omöjliggör alltihop.

Vi har väl alla slitit vårt hår över det där lilla kommatecknet som är omöjligt finna ut att eller var det fattas... Om man sedan inte vet att det ens skall vara där... Då blir det besvärligt.
Senast redigerad av Erik M 4 juli 2016, 21:11:16, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PWMx och PIC12F1572, men hur...?

Inlägg av sodjan »

Att "översätta" C till motsvarande ASM bör inte vara något problem,
så länge som exemplen bara använder direkta register, inga "libbar".
Har du hitta något alls till dessa nyare modeller?
Erik M
Inlägg: 1380
Blev medlem: 23 februari 2012, 18:34:39
Ort: Göteborg

Re: PWMx och PIC12F1572, men hur...?

Inlägg av Erik M »

Inte ännu, jag läser och begrundar databladet än.
Fångar en liten ynka bit i taget och försöker ge den ett sammanhang.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PWMx och PIC12F1572, men hur...?

Inlägg av sodjan »

Alltså:

> Det mesta är skrivet i C...

Som vad t.ex.? Vad är det du syftar på?
Erik M
Inlägg: 1380
Blev medlem: 23 februari 2012, 18:34:39
Ort: Göteborg

Re: PWMx och PIC12F1572, men hur...?

Inlägg av Erik M »

Den kod man hittar att gå vidare från är oftast skriven i C.
Jag skulle föredra ASM.

Hm... Rotar just runt borta hos MicroChip - är deras MPLAB Code Configurator hjälpsam?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46974
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: PWMx och PIC12F1572, men hur...?

Inlägg av TomasL »

Nej, den är avsedd för C och MPLABX för att konfigurera bl.a. de olika periferienheterna och lite annat.
The MPLAB Code Configurator is a free graphical programming environment that generates seamless, easy to understand C code that is inserted into your project. Using an intuitive interface it enables and configures a rich set of peripherals and functions. It is integrated into MPLAB X IDE to provide a powerful and easy to use development platform.
Varför inte gå över till C istället, fasiken så mycket bekvämare.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PWMx och PIC12F1572, men hur...?

Inlägg av sodjan »

MCC genererar C kod, men det kan ju som jag sa vara till hjälp ändå.
Det är ju samma register oavsett om man kör C eller ASM, bara att
göra samma sak i ASM...

Testade att sätta up PWM1 i MCC och fick nedanstående.
Kört med 32 MHz, Standard-PWM, clock-source FOSC, Independent-run,
period 1000 ns, Phase 0, offset 62.5 ns (default), Duty 50%.

Jag tycker att koden är väldigt tydlig och ren och bör inte vara något
problem att överföra till ASM. Man får förutom en grundinställning enligt
vad man valde i MCC, även färdiga funktioner för att ändra inställningar.
Ser himla trevligt ut, måste jag säga...

Kod: Markera allt


/**
  PWM1 Generated Driver File

  @Company
    Microchip Technology Inc.

  @File Name
    pwm1.c

  @Summary
    This is the generated driver implementation file for the PWM1 driver using MPLAB(c) Code Configurator

  @Description
    This header file provides implementations for driver APIs for PWM1.
    Generation Information :
        Product Revision  :  MPLAB(c) Code Configurator - 3.15.0
        Device            :  PIC12F1572
        Driver Version    :  1.0
    The generated drivers are tested against the following:
        Compiler          :  XC8 1.35
        MPLAB             :  MPLAB X 3.20
*/

/*
    (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this
    software and any derivatives exclusively with Microchip products.

    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
    WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
    PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION
    WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.

    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
    BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
    FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
    ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
    THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.

    MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE
    TERMS.
*/

/**
  Section: Included Files
*/

#include <xc.h>
#include "pwm1.h"

/**
  Section: PWM1 APIs
*/

void PWM1_Initialize(void)
{
    // set the PWM1 to the options selected in the User Interface

     //PHIE disabled; DCIE disabled; OFIE disabled; PRIE disabled; 
    PWM1INTE = 0x00;

     //PHIF cleared; OFIF cleared; DCIF cleared; PRIF cleared; 
    PWM1INTF = 0x00;

     //PS No_Prescalar; CS FOSC; 
    PWM1CLKCON = 0x00;

     //LDS reserved; LDT disabled; LDA do_not_load; 
    PWM1LDCON = 0x00;

     //OFM independent_run; OFS reserved; OFO match_incrementing; 
    PWM1OFCON = 0x00;

     //PWM1PHH 0; 
    PWM1PHH = 0x00;

     //PWM1PHL 0; 
    PWM1PHL = 0x00;

     //PWM1DCH 0; 
    PWM1DCH = 0x00;

     //PWM1DCL 16; 
    PWM1DCL = 0x10;

     //PWM1PRH 0; 
    PWM1PRH = 0x00;

     //PWM1PRL 31; 
    PWM1PRL = 0x1F;

     //PWM1OFH 0; 
    PWM1OFH = 0x00;

     //PWM1OFL 1; 
    PWM1OFL = 0x01;

     //PWM1TMRH 0; 
    PWM1TMRH = 0x00;

     //PWM1TMRL 0; 
    PWM1TMRL = 0x00;
    
     //MODE standard_PWM; POL active_hi; OE enabled; EN enabled; 
    PWM1CON = 0xC0;
}    


void PWM1_Start(void)
{
    PWM1CONbits.EN = 1;		
}

void PWM1_Stop(void)
{
    PWM1CONbits.EN = 0;		
}

bool PWM1_CheckOutputStatus(void)
{
    return (PWM1CONbits.OUT);		
}

void PWM1_LoadBufferSet(void)
{
    PWM1LDCONbits.LDA = 1;		
}

void PWM1_PhaseSet(uint16_t phaseCount)
{
    PWM1PHH = (phaseCount>>8);        //writing 8 MSBs to PWMPHH register
    PWM1PHL = (phaseCount);           //writing 8 LSBs to PWMPHL register
}

void PWM1_DutyCycleSet(uint16_t dutyCycleCount)
{
    PWM1DCH = (dutyCycleCount>>8);	//writing 8 MSBs to PWMDCH register
    PWM1DCL = (dutyCycleCount);	//writing 8 LSBs to PWMDCL register		
}

void PWM1_PeriodSet(uint16_t periodCount)
{
    PWM1PRH = (periodCount>>8);	//writing 8 MSBs to PWMPRH register
    PWM1PRL = (periodCount);	//writing 8 LSBs to PWMPRL register		
}

void PWM1_OffsetSet(uint16_t offsetCount)
{
    PWM1OFH = (offsetCount>>8);	//writing 8 MSBs to PWMOFH register
    PWM1OFL = (offsetCount);	//writing 8 LSBs to PWMOFL register		
}

uint16_t PWM1_TimerCountGet(void)
{
    return ((PWM1TMRH<<8) | PWM1TMRL);       		
}

bool PWM1_IsOffsetMatchOccured(void)
{
    return (PWM1INTFbits.OFIF);		
}

bool PWM1_IsPhaseMatchOccured(void)
{
    return (PWM1INTFbits.PHIF);	
}

bool PWM1_IsDutyCycleMatchOccured(void)
{
    return (PWM1INTFbits.DCIF);		
}

bool PWM1_IsPeriodMatchOccured(void)
{
    return (PWM1INTFbits.PRIF);		
}

/**
 End of File
*/
Erik M
Inlägg: 1380
Blev medlem: 23 februari 2012, 18:34:39
Ort: Göteborg

Re: PWMx och PIC12F1572, men hur...?

Inlägg av Erik M »

TomasL ~ Verkar ju perfekt för att generera SFR-kod.

Någonstans på vägen från C över till HEX månne man kan se hur det ser ut i ASM...?
Redan i MPLAB kan man ju generera config word.
Egentligen märkligt, eller jag som inte grävt tillräckligt för att hitta det, att MPLAB inte ger samma möjlighet som exempelvis FlowCode vad gäller att mer eller mindre grafiskt kunna ange var man vill ha en funktion i funktion, direkt på raden i koden.

Suveränt Janne, stort tack. :tumupp:
Och det är som du säger - klart och tydligt vad som skall ställas in till vad.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PWMx och PIC12F1572, men hur...?

Inlägg av sodjan »

Totalt skapas 6 filer, 3 C-filer och 3 h-filer.
C filerna är för grundinställningar (som inte har direkt med PWM att göra),
pin-konfiguration (delvis styrs av PWM definitioner) samt PWM filen ovan.

H-filen för PWM innehåller också lite mer dokumentation för de olika
hjälp-funktionerna.

(Exempel koden till PWM_Stop() har ett litet fel... :-) )

Kod: Markera allt

/**
  PWM1 Generated Driver API Header File

  @Company
    Microchip Technology Inc.

  @File Name
    pwm1.h

  @Summary
    This is the generated header file for the PWM1 driver using MPLAB(c) Code Configurator

  @Description
    This header file provides APIs for driver for PWM1.
    Generation Information :
        Product Revision  :  MPLAB(c) Code Configurator - 3.15.0
        Device            :  PIC12F1572
        Driver Version    :  1.0
    The generated drivers are tested against the following:
        Compiler          :  XC8 1.35
        MPLAB             :  MPLAB X 3.20
*/

/*
    (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this
    software and any derivatives exclusively with Microchip products.

    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
    WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
    PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION
    WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.

    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
    BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
    FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
    ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
    THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.

    MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE
    TERMS.
*/

#ifndef _PWM1_H
#define _PWM1_H

/**
  Section: Included Files
*/

#include <xc.h>
#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus  // Provide C++ Compatibility

    extern "C" {

#endif

/**
  Section: PWM Module APIs
*/

/**
  @Summary
    Initializes the PWM1

  @Description
    This routine initializes the Initializes the PWM1.
    This routine must be called before any other PWM routine is called.
    This routine should only be called once during system initialization.

  @Preconditions
    None

  @Param
    None

  @Returns
    None

  @Comment
    

  @Example
    <code>
    
    </code>
*/
void PWM1_Initialize(void);

/**
  @Summary
    This function starts the PWM1.

  @Description
    This function starts the PWM1 operation.
    This function must be called after the initialization of PWM1.

  @Preconditions
    Initialize  the PWM1 before calling this function.

   @Param
    None

  @Returns
    None

  @Example
    <code>
    // Initialize PWM1 module

    // Start PWM1
    PWM1_Start();

    // Do something else...
    </code>
*/
void PWM1_Start(void);

/**
  @Summary
    This function stops the PWM1.

  @Description
    This function stops the PWM1 operation.
    This function must be called after the start of PWM1.

  @Preconditions
    Initialize  the PWM1 before calling this function.

  @Param
    None

  @Returns
    None

  @Example
    <code>
    // Initialize PWM1 module

    // Start PWM1
    PWM1_StartTimer();

    // Do something else...

    // Stop PWM1;
    PWM1_Stop();
    </code>
*/
void PWM1_Stop(void);


/**
  @Summary
    This function used to check output status of PWM1.

  @Description
    Check output status of PWM1 as High or Low.    

  @Preconditions
    Start the PWM1 before calling this function.

  @Param
    None

  @Returns
    true - Output High.
	false - Output Low.

  @Example
    <code>
    
    </code>
*/
bool PWM1_CheckOutputStatus(void);

/**
  @Summary
    This function is used to load buffer of PWM1 at the end of period.

  @Description
    load buffer of PWM1 at the end of period.

  @Preconditions
     Initialize  the PWM1 before calling this function.

  @Param
    None

  @Returns
    None

  @Example
    <code>
    
    </code>
*/
void PWM1_LoadBufferSet(void);

/**
  @Summary
    Load required 16 bit phase count

  @Description
    Set the expected phase count

  @Preconditions
    None

  @Param
    Pass 16 bit phase count

  @Returns
    None

  @Example
    <code>
    
    </code>
*/
void PWM1_PhaseSet(uint16_t phaseCount);

/**
  @Summary
    Load required 16 bit Duty Cycle

  @Description
    Set the expected Duty Cycle

  @Preconditions
    None

  @Param
    Pass 16 bit Duty Cycle

  @Returns
    None

  @Example
    <code>
    
    </code>
*/
void PWM1_DutyCycleSet(uint16_t dutyCycleCount);

/**
  @Summary
    Load required 16 bit Period

  @Description
    Set the expected Period

  @Preconditions
    None

  @Param
    Pass 16 bit Period

  @Returns
    None

  @Example
    <code>
    
    </code>
*/
void PWM1_PeriodSet(uint16_t periodCount);

/**
  @Summary
    Load required 16 bit Offset

  @Description
    Set the expected Offset

  @Preconditions
    None

  @Param
    Pass 16 bit Offset

  @Returns
    None

  @Example
    <code>
    
    </code>
*/
void PWM1_OffsetSet(uint16_t offsetCount);

/**
  @Summary
    Read measured Timer count

  @Description    
    Read the measured Timer count
 * 
  @Preconditions
    None

  @Param
    None

  @Returns
    Return 16 bit Timer count

  @Example
    <code>
    
    </code>
*/
uint16_t PWM1_TimerCountGet(void);

/**
  @Summary
    Returns status of Offset interrupt flag bit (OFIF ).

  @Description    
    When PWMTMR = PWMOF value offset flag sets.

  @Preconditions
    None

  @Param
    None

  @Returns
    true - PWMTMR >= PWMOF value
    false - PWMTMR < PWMOF value

  @Example
    <code>
    
    </code>
*/
bool PWM1_IsOffsetMatchOccured(void);

/**
  @Summary
    Returns status of Phase interrupt flag bit (PHIF ).

  @Description    
    When PWMTMR = PWMPH value, Phase flag sets.

  @Preconditions
    None

  @Param
    None

  @Returns
    true - PWMTMR count is >= PWMPH value
    false - PWMTMR count is < PWMPH value

  @Example
    <code>
    
    </code>
*/
bool PWM1_IsPhaseMatchOccured(void);

/**
  @Summary
    Returns status of DutyCycle interrupt flag bit (DCIF ).

  @Description    
    When PWMTMR = PWMDC value DutyCycle flag sets.

  @Preconditions
    None

  @Param
    None

  @Returns
    true - PWMTMR count is >= PWMDC value
    false - PWMTMR count is < PWMDC value

  @Example
    <code>
    
    </code>
*/
bool PWM1_IsDutyCycleMatchOccured(void);

/**
  @Summary
    Returns status of Period interrupt flag bit (PRIF ).

  @Description    
    When PWMTMR = PWMPR value offset flag sets.

  @Preconditions
    None

  @Param
    None

  @Returns
    true - PWMTMR count is >= PWMPR value
    false - PWMTMR count is < PWMPR value

  @Example
    <code>
    
    </code>
*/
bool PWM1_IsPeriodMatchOccured(void);

#endif	/* PWM1_H */
/**
 End of File
*/
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PWMx och PIC12F1572, men hur...?

Inlägg av sodjan »

En sak att notera är att det är väldigt enkelt att installera plugins som MCC.
Det görs inne i MPLABX via menyn Tools->Plugins. Sen "Available Plugins"
och markera MCC. Nerladdning och installation sker av MLPABX och det
blir tillgängligt direkt utan omstart.
Erik M
Inlägg: 1380
Blev medlem: 23 februari 2012, 18:34:39
Ort: Göteborg

Re: PWMx och PIC12F1572, men hur...?

Inlägg av Erik M »

PWM1_StopTimer ? :humm:
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PWMx och PIC12F1572, men hur...?

Inlägg av sodjan »

Japp... :-)
Ska ju vara PWM_Start(), så klart.
Bad cut-n-paste...
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46974
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: PWMx och PIC12F1572, men hur...?

Inlägg av TomasL »

Redan i MPLAB kan man ju generera config word.
Vilket är något man aldrig någonsin skall använda (dvs sätta configen i IDEn, dessutom borttaget ur MPLABX)
Skriv svar