Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

problems with PWM and 16F628A

Status
Not open for further replies.

POWERMAN

New Member
Hello everybody,

I use PIC16F628A for driving 3 outputs in PWM and i meet some problems with my C code.
I want to control 3 differents PWM, for the moment i've just connect 2 switchs (up and down) for control PWM hard only.
I don't understand, because when i push up switch i've just 3 differents duty cycles (same when i push down) but only 2 when i up again, and i locked at the 3rd cycle.
My wish was to obtain 10% for each push in "up switch" and same for "down switch" progress.
I've fixed F=500Hz and that is good.
I joined my program (Hitech C).
I hope some assistance, thanks by advance.

Powerman.

Moved to correct forum - moderator!
 

Attachments

  • ecl_pwm.c
    9.8 KB · Views: 337
  • ecl_pwm.h
    2.2 KB · Views: 283
Last edited by a moderator:
People maybe able to help. Unfortunately, your files are unreadable. Try loading them into a text editor and saving them so that the end of line characters are inserted. Or, cut and paste them into a CODE tag.

Mike.
 
You're severely limiting your chance of a response by using C, most PIC programming is done in assembler.

However, many C compiler manufacturers have forums, you might try asking there?.
 
hi,

i respect you nigel but i'm not agree, assembler for me is out of date.

Sorry.

Pommie i try to insert in text editor:


pwm.c

//**********************
ushort Compteur62us ;
uchar Flag62us ;

ushort ValeurPwmS1 ;
ushort ValeurPwmS2 ;
ushort ValeurPwmS3 ;

uchar Valeur3Pas ;

uchar CompteurPression ;
uchar CombinaisonBPs ;


pwm.c

//*********************
void init_pic(void);
void interrupt traite_int(void);
void clock_pic(void);

void DelayMs(uchar cpt) ;
void init_var(void) ;

void init_pwm(void) ;
void stop_pwm(void) ;
void setDC_pwm(ushort dc) ;

uchar TestBPs(void) ;
void GestionBPs(void) ;

//***************************************************************

/****************************************************************
Timmings in ms
****************************************************************/
void DelayMs(uchar cpt)
{
ushort t ;
while (cpt != 0)
{
CLRWDT() ;
-- cpt ;
t = 112 ;
while (t !=0) -- t ;
}
}

/****************************************************************
interrupts
****************************************************************/
void interrupt traite_int(void)
{
if(TMR1IF)
{
TMR1IF = 0 ;
Flag62us = 1 ;
TMR1H = 0xFF ;
TMR1L = 0xC1 ; // 0xFFFF - 0xFFC1 = 62 => 62 x 1 µs = 62 µs
}

}

/****************************************************************
Init PIC
****************************************************************/
void init_pic(void)
{
// Configuration du module CCP
CCP1CON = 0x00 ; // module CCP1 désactivée

// Configuration du port B
RBPU = 0 ; // active pull up
RBIE = 0 ;

// Configuration des I/O
PwmS1 = 0 ; // à l'init. S1 = 0
PwmS2 = 0 ; // S2 = 0
PwmS3 = 0 ; // S3 = 0
TRISA = ConfigIOPortA ;
TRISB = ConfigIOPortB ;

// Timer 0 (8 bits) est utilisé pour le wachtdog à 2,3 s.
T0CS = 0 ; // Clock interne
PSA = 1 ; // timer0 = Wachtdog
PS2 = 1 ; // \
PS1 = 1 ; // => 111 + WDT => 18 ms x 128 = 2,304 s
PS0 = 1 ; // /

// Timer 1 (16 bits) est utilisé pour l'horloge: base de 62 µs. Quartz 4 Mhz => 1 instruction = 1 µs
T1CON = 0x00 ; // Prédivision de l'horloge par 1
TMR1H = 0xFF ;
TMR1L = 0xC1 ; // 0xFFFF - 0xFFC1 = 62 => 62 x 1 µs = 62 µs
TMR1ON = 1 ; // On lance le timer 1
TMR1IE = 1 ; // On autorise les interruptions du timer 1

// Autorisation des interruptions
PEIE = 1 ; // Autorisation des IT peripherique
GIE = 1 ; // Autorisation général des IT
}

/****************************************************************
Init var glob
****************************************************************/
void init_var(void)
{
Flag62us = 0 ;
Compteur62us = 0 ; // Raz compteur clock

ValeurPwmS1 = 0 ;
ValeurPwmS2 = 0 ;
ValeurPwmS3 = 0 ;

Valeur3Pas = 0 ;
}

/****************************************************************
Init PWM
****************************************************************/
void init_pwm(void)
{
CCP1CON = 0x00 ; // module off
TMR2 = 0 ; // raz timer2 value
PR2 = 0x7C ; // PR2 = 124 --> f = 500 Hz
CCPR1L = 0 ; // Duty cycle = 0 à l'init
TRISB3 = 0 ; // RB3 = output
T2CKPS1 = 1 ; // Prescaler = 1:16
T2CKPS0 = 1 ;
CCP1CON = 0x0C ; // Mode PWM 10 bits + init two LSBs of PWM duty cycle at 0
TMR2ON = 1 ; // Timer2 ON
}

/****************************************************************
stop PWM
****************************************************************/
void stop_PWM(void)
{
RB3 = 0 ;
TMR2ON = 0 ;
CCP1CON = 0x00 ;
}

/****************************************************************
load duty cycle PWM [0-1023] -> [0-100%]
****************************************************************/
void setDC_PWM(ushort dc)
{
CCP1CON = CCP1CON & 0b11001111 ; // clear CCP1CON<5:4>
CCP1CON = CCP1CON | ((dc << 4) & 0b00110000) ; // set the two LSBs duty cycle
CCPR1L = dc >> 2 ; // set the eight MSBs duty cycle
}

/****************************************************************
management clock PIC
****************************************************************/
void clock_pic(void)
{
Flag62us = 0 ;

// ValeurPwmSx [0-256]
// Compteur62us [0-256]

if (ValeurPwmS1 == 0) PwmS1 = 0 ;
else
{
if (Compteur62us == 0) PwmS1 = 1 ;
else if (Compteur62us == ValeurPwmS1) PwmS1 = 0 ;
}

if (ValeurPwmS2 == 0) PwmS2 = 0 ;
else
{
if (Compteur62us == 0) PwmS2 = 1 ;
else if (Compteur62us == ValeurPwmS2) PwmS2 = 0 ;
}

Compteur62us = Compteur62us + 8 ;

if (Compteur62us == 256) Compteur62us = 0 ; // période = 2 ms

}

/****************************************************************
Tests switchs
*****************************************************/
uchar TestBPs(void)
{
CompteurPression = 0 ;
CombinaisonBPs = AUCUNE ;

while (!BoutonUp)
{
DelayMs(10) ;
++CompteurPression ;
if (!BoutonDown) CombinaisonBPs = UP_ET_DOWN ;
else CombinaisonBPs = UP ;
if (CompteurPression > 200) break ; // expiration
}

while (!BoutonDown)
{
DelayMs(10) ;
++CompteurPression ;
if (!BoutonUp) CombinaisonBPs = UP_ET_DOWN ;
else CombinaisonBPs = DOWN ;
if (CompteurPression > 200) break ; // expiration
}

return(CombinaisonBPs) ;
}

/****************************************************************
management switchs
****************************************************************/
void GestionBPs(void)
{
switch (CombinaisonBPs)
{
case UP :
if (CompteurPression > 100)
{
if (ValeurPwmS1 < 256) ValeurPwmS1 = ValeurPwmS1 + 8 ;
if (ValeurPwmS2 < 256) ValeurPwmS2 = ValeurPwmS2 + 8 ;
if (ValeurPwmS3 < 256) ValeurPwmS3 = ValeurPwmS3 + 2 ;
}
else
{
if (ValeurPwmS1 < 256) ValeurPwmS1 = ValeurPwmS1 + 32 ;
if (ValeurPwmS1 < 256) ValeurPwmS2 = ValeurPwmS2 + 32 ;
if (ValeurPwmS1 < 256) ValeurPwmS3 = ValeurPwmS3 + 8 ;
}
break ;
case DOWN :
if (CompteurPression > 100)
{
if (ValeurPwmS1 > 7) ValeurPwmS1 = ValeurPwmS1 - 8 ;
if (ValeurPwmS2 > 7) ValeurPwmS2 = ValeurPwmS2 - 8 ;
if (ValeurPwmS3 > 7) ValeurPwmS3 = ValeurPwmS3 - 2 ;
}
else
{
if (ValeurPwmS1 > 31) ValeurPwmS1 = ValeurPwmS1 - 32 ;
if (ValeurPwmS1 > 31) ValeurPwmS2 = ValeurPwmS2 - 32 ;
if (ValeurPwmS1 > 31) ValeurPwmS3 = ValeurPwmS3 - 8 ;
}
break ;
case UP_ET_DOWN :
if (CompteurPression > 100)
{
switch (Valeur3Pas)
{
case 0 :
Valeur3Pas = 50 ; // 50%
ValeurPwmS1 = 128 ;
ValeurPwmS2 = 128 ;
ValeurPwmS3 = 128 ;
break ;
case 50 :
Valeur3Pas = 100 ; // 100%
ValeurPwmS1 = 256 ;
ValeurPwmS2 = 256 ;
ValeurPwmS3 = 256 ;
break ;
case 100 :
Valeur3Pas = 0 ; // 0%
ValeurPwmS1 = 0 ;
ValeurPwmS2 = 0 ;
ValeurPwmS3 = 0 ;
break ;
}
}
break ;
}

// S1 est mis à jour par ValeurPwmS1 --> Timer1
// S2 est mis à jour par ValeurPwmS2 --> Timer1
// S3 est mis à jour par ValeurPwmS3 --> PWM

setDC_PWM((ValeurPwmS3 * 4)-1) ; // on se ramène à l'échelle [0-1023]

while (TestBPs() != AUCUNE) CLRWDT() ; // attent le relâchement

Compteur62us = 0 ;

}

/****************************************************************
main program
****************************************************************/
main()
{
CLRWDT() ;

// init registres
init_pic();
// init variables globales
init_var() ;

// init PWM hard
init_pwm() ;
setDC_PWM((ValeurPwmS3 * 4)-1) ;

while(1)
{
// raffraichi le watchdog
CLRWDT() ;

// gestion 62 µs
if (Flag62us) clock_pic();

// gestion des boutons poussoirs
if (TestBPs() != AUCUNE) GestionBPs() ;
}
}


regards
 
and pwm.h


pwm.h

/*====================================================================
-----= Predefined instructions =-----
====================================================================*/
// Predefined instructions
#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit))
#define NOP() asm(" nop")
#define FALSE 0
#define TRUE !FALSE
#define BYTE unsigned char /* sizeof(BYTE) must == 1 */
#define uchar unsigned char
#define ushort unsigned short
#define ulong unsigned long

// Descriptions des différentes entrées et sorties
static bit PwmS1 @ PORTBIT(PORTA, 6) ; // sortie S1 PWM
static bit PwmS2 @ PORTBIT(PORTA, 7) ; // sortie S2 PWM
static bit PwmS3 @ PORTBIT(PORTB, 3) ; // sortie S3 PWM
static bit BoutonUp @ PORTBIT(PORTB, 6) ; // entrée poussoir UP
static bit BoutonDown @ PORTBIT(PORTB, 7) ; // entrée poussoir DOWN

// Remarque: 1 = input, 0 = output
#define ConfigIOPortA 0x3F // RA6 et RA7 = PWM outputs, other in input
#define ConfigIOPortB 0xFF // port B input

#define AUCUNE 0x00
#define UP 0x01
#define DOWN 0x02
#define UP_ET_DOWN 0x03
 
Maybe but majority is rarely the reference for me.
C is more portable and more readable.
In assembler, if you change µC you learn assembler again, in C not.

C is more efficient for complex program, no?
 
POWERMAN said:
Maybe but majority is rarely the reference for me.
C is more portable and more readable.
In assembler, if you change µC you learn assembler again, in C not.

And every C compiler is different!, the portability of C is GREATLY exaggerated, and is particularly non-portable for micro-controllers.

However, it is HUGELY more portable than assembler!.

C is more efficient for complex program, no?

Depends on your programming skills?, and the number of proven routines you have available - and also on your definition of 'efficient' - a competent C programmer, with a good working knowledge of assembler on the target device, could certainly write large programmes far faster than in pure assembly.
 
i'm agree.:)

In my case, write in C is more practical.

In my program, i suspect variables init or wrong calculation, i would like your opinion.
I don't think a mistake for pwm use, i have read more and more your tutorial and Microchip specs, but without result...

regards.
 
Hi Nigel,

finally i've found a mistake here:

void GestionBPs(void)
{
switch (CombinaisonBPs)
{
case UP :
if (CompteurPression > 100)<----- 100 is too high, with 1 it's OK.

Thanks.
 
POWERMAN said:
Hi Nigel,

finally i've found a mistake here:

void GestionBPs(void)
{
switch (CombinaisonBPs)
{
case UP :
if (CompteurPression > 100)<----- 100 is too high, with 1 it's OK.

It's all those curly brackets in C, it's just SO confusing! :p

Anyway, I'm pleased you found your fault!.
 
This code is very suspicious
Code:
else
{
if (ValeurPwmS1 < 256) ValeurPwmS1 = ValeurPwmS1 + 32 ;
if (ValeurPwmS1 < 256) ValeurPwmS2 = ValeurPwmS2 + 32 ;
if (ValeurPwmS1 < 256) ValeurPwmS3 = ValeurPwmS3 + 8 ;
}

should probably be

Code:
else
{
if (ValeurPwmS1 <= 256-32) ValeurPwmS1 = ValeurPwmS1 + 32 ;
if (ValeurPwmS2 <= 256-32) ValeurPwmS2 = ValeurPwmS2 + 32 ;
if (ValeurPwmS3 <= 256-8) ValeurPwmS3 = ValeurPwmS3 + 8 ;
}

ditto in the other place
 
Nigel Goodwin said:
It's all those curly brackets in C, it's just SO confusing! :p

Anyway, I'm pleased you found your fault!.
i agree , and what is void ? no need explaining , its just weird thats all
Nigel thanks for the link :)
 
williB said:
a question : could one , set up a stack in ram?

I'm agree with Nigel, in C stack control is a problem, so i look with debugger for monitor it.
Have you an exemple for use a stack in ram?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top