Hjälp med 16F1937
Re: Hjälp med 16F1937
I verkligheten kommer det att komma från en utgång på en OP som kommer vara en komparator. Just nu när jag testar så har jag bara en tråd kopplad till fem volt som jag trycker ner i en kopplings list. Så den är full med studs och annat skit tyvärr ja. Så förhoppningsvis är detta orsak till ett jag tycker det verkar trigga på fel flank.
Ang att inte hoppa ur interuptet såg jag också iocbf flaggan kan nollas. Ska prova det när jag kommer hem ikväll. Provade också simulatorn. Nu känner jag mig rätt osäker på hur den skall användas och tydas men stegar jag genom koden rad för rad gör den precis vad den skall både med och utan iocbf flaggan nollad. Så jag känner mig rätt osäker på simulatorn just nu iaf.
Ang att inte hoppa ur interuptet såg jag också iocbf flaggan kan nollas. Ska prova det när jag kommer hem ikväll. Provade också simulatorn. Nu känner jag mig rätt osäker på hur den skall användas och tydas men stegar jag genom koden rad för rad gör den precis vad den skall både med och utan iocbf flaggan nollad. Så jag känner mig rätt osäker på simulatorn just nu iaf.
Re: Hjälp med 16F1937
För att det ska gå så måste simulatorn även kunna simulera externa signaler.
Det framgår inte om "gör precis vad den ska" inkluderar interrupt hanteringen.
Ja, jag misstänkte att du har en sladd. Då får du kanske 10-20 kompletta
flanker i båda riktningarna varje gång du "duttar". Processon är tillräckligt
snabb för att se dessa som helt separata signaler.
Det framgår inte om "gör precis vad den ska" inkluderar interrupt hanteringen.
Ja, jag misstänkte att du har en sladd. Då får du kanske 10-20 kompletta
flanker i båda riktningarna varje gång du "duttar". Processon är tillräckligt
snabb för att se dessa som helt separata signaler.
Re: Hjälp med 16F1937
Trevligt! 
(Och allt så här långt har ju faktiskt stått i databladet...
)

(Och allt så här långt har ju faktiskt stått i databladet...

Re: Hjälp med 16F1937
nu till nästa steg. PWM styra ett RC servo med hjälp av knappar.
Det skall skapas en 50 Hz signal med två olika dutycycles. Servot är kopplat till en vanlig GPIO utgång men skulle antagligen varit kopplad till en CCP utgång förstår jag nu.
O andra sidan vad jag kan förstå kan man inte skapa en så låg frekvens mha av PWM modulen utan jag får väl ändå göra det med mjukvara.
Tanken är att trycker jag på UPP knappen skall den sända ett 50Hz pulståg med viss duty i ca 1,5s. Hur åstadkommer jag detta enklast?
MikroC har inbyggd delay_ms() funktion men den är helt oanvändbar när man vill skriva exakta tider.
Då antar jag att ngn form av timer krävs men jag har aldrig använt dessa innan.
Det skall skapas en 50 Hz signal med två olika dutycycles. Servot är kopplat till en vanlig GPIO utgång men skulle antagligen varit kopplad till en CCP utgång förstår jag nu.
O andra sidan vad jag kan förstå kan man inte skapa en så låg frekvens mha av PWM modulen utan jag får väl ändå göra det med mjukvara.
Tanken är att trycker jag på UPP knappen skall den sända ett 50Hz pulståg med viss duty i ca 1,5s. Hur åstadkommer jag detta enklast?
MikroC har inbyggd delay_ms() funktion men den är helt oanvändbar när man vill skriva exakta tider.
Då antar jag att ngn form av timer krävs men jag har aldrig använt dessa innan.
Re: Hjälp med 16F1937
För just RC-servo styrning så är PWM modulen inte helt perfekt.
PWM modulen är normalt tänkt för högre frekvenser än 50 Hz och
i alla fall i äldre processorer var det svårt att konfigurera för så
pass läg frekvens.
Timers is-the-shit.
Timers hör till de enklare enheterna, jag skulle säga att de är
enklare än t.ex PWM modulen att konfigurera.
1. Starta en timer (med interrupt) med en lämplig frekvens.
2. I timer-ISR'en, räkna och fippla med en I/O pinne så att du får önskad signal.
Låt timern snurra t.ex 100 gånger snabbare en perioden (20 ms). Då får
du 100 olika steg. Nu ville du ju bara ha två "ändlägen", men principen
är ungefär densamma. Visst, för enbart två lägen kan man göra det
lite enklare, men en timer är i alla fall rätt väg.
PWM modulen är normalt tänkt för högre frekvenser än 50 Hz och
i alla fall i äldre processorer var det svårt att konfigurera för så
pass läg frekvens.
Timers is-the-shit.

Timers hör till de enklare enheterna, jag skulle säga att de är
enklare än t.ex PWM modulen att konfigurera.
1. Starta en timer (med interrupt) med en lämplig frekvens.
2. I timer-ISR'en, räkna och fippla med en I/O pinne så att du får önskad signal.
Låt timern snurra t.ex 100 gånger snabbare en perioden (20 ms). Då får
du 100 olika steg. Nu ville du ju bara ha två "ändlägen", men principen
är ungefär densamma. Visst, för enbart två lägen kan man göra det
lite enklare, men en timer är i alla fall rätt väg.
Re: Hjälp med 16F1937
Perfekt, då får jag chans att lära mig timers. Jag kollar på det och sen lär jag väl komma med halvintelligenta frågor.
Re: Hjälp med 16F1937
En fråga. Jag har ju redan et interupt definierat som är kopplad till en pinne.
Kommer detta timerinteruptet kunna vara i konflikt med den andra?
Kommer detta timerinteruptet kunna vara i konflikt med den andra?
- SeniorLemuren
- Inlägg: 8427
- Blev medlem: 26 maj 2009, 12:20:37
- Ort: Kristinehamn
Re: Hjälp med 16F1937
Tidigare föreslog jag att du skulle använda dig av volatile när det gällde "volatile bit k=0;" Kanske det funkade ändå utan den deklarationen denna gång. Läs gärna här (avsnittet Interrupt service routines), varför volatile måste användas i vissa fall om du inte redan känner till det.
Re: Hjälp med 16F1937
Du har bara en ISR. Men i den får du testa vilken xxxIF flagga som är satt och sedan antingen "serva" IOC eller timern. Sedan avslutar du ISR'en och om den andra IF flaggan också är satt så kommer den att anropas direkt igen.
Re: Hjälp med 16F1937
SeniorLemuren skrev:Tidigare föreslog jag att du skulle använda dig av volatile när det gällde "volatile bit k=0;" Kanske det funkade ändå utan den deklarationen denna gång. Läs gärna här (avsnittet Interrupt service routines), varför volatile måste användas i vissa fall om du inte redan känner till det.
Ska läsa def tack.
Det fungerade utan i detta fallet.. det var iocbf som inte nollades. När detta blev gjort funkade interuptet som det skulle
Re: Hjälp med 16F1937
Ungefär (på rak arm, helt otestat, men visar principen):
Kod: Markera allt
void interrupt(){
if (IOCIF) {
SERVO=0;
BUZZ=1;
delay_ms(100);
BUZZ=0;
k=1;
BACKLIGHT=0;
<clear IOC interrupt flags...>
}
if (TMR1IF) {
<do whatever is needed at timer1 rollover...>
}
}
Re: Hjälp med 16F1937
Såhär har jag gjort för tillfället men PWM utgången funkar inte. Den är noll. Tankevurpa är nog orsaken 

Kod: Markera allt
/*
Manöverpanel till fjärrvärme Pic16F1937, intern 8MHz OSC, extern MCLR
*/
#define BUZZ PORTC.F3 //Name ports
#define SERVO PORTD.F1
#define BACKLIGHT PORTC.F2
sbit PWM_OUT at RD0_bit;
int k=0;
char *text1;
char *text2;
//LCD module connection
sbit LCD_RS at RA0_bit;
sbit LCD_EN at RA1_bit;
sbit LCD_D4 at RA2_bit;
sbit LCD_D5 at RA3_bit;
sbit LCD_D6 at RA4_bit;
sbit LCD_D7 at RA5_bit;
sbit LCD_RS_Direction at TRISA0_bit;
sbit LCD_EN_Direction at TRISA1_bit;
sbit LCD_D4_Direction at TRISA2_bit;
sbit LCD_D5_Direction at TRISA3_bit;
sbit LCD_D6_Direction at TRISA4_bit;
sbit LCD_D7_Direction at TRISA5_bit;
//End LCD module connection
void initMain(){
TRISA=0b00000000;
TRISB=0b00110011;
TRISC=0b11000000;
TRISD=0b00000000;
TRISE=0b00000000;
LCDCON=0b00000000;
ANSELA=0;
ANSELB=0;
INTCON=0b10111000;
IOCBP=0b00000001;
TMR0=180;
LCD_Init();
LCD_Cmd(_LCD_CURSOR_OFF);
LCD_Cmd(_LCD_CLEAR);
if(k!=1){
BUZZ=1;
delay_ms(50);
BUZZ=0;
//BACKLIGHT=1;
Lcd_out(1,1,"Remote Heater");
Lcd_out(2,1,"Sp-E 2014");
}
}
void interrupt(){
if(INTF==1){
SERVO=0;
k=1;
BACKLIGHT=0;
}
if(TMR0IF==1){
PWM_OUT=1;
Delay_ms(2);
PWM_OUT=0;
}
INTCON=0b00000000; //Nolla interupt för att det inte ska loopa hela tiden
}
void main() {
initMain();
while(1){
if(k==1){ //Hör till interuptet
BUZZ=1;
delay_ms(50);
BUZZ=0;
Lcd_out(1,1,"Servo Error!!!");
Lcd_out(2,1,"Reset panel!!!");
while(1){
SERVO=0;
BACKLIGHT=0;
BUZZ=0;
}
}
else if(Button(&PORTB, 5,1,0)||Button(&PORTB, 4,1,0)){
BACKLIGHT=1;
}
else if(Button(&PORTB, 5,1,1)&&Button(&PORTB, 4,1,1)){
BACKLIGHT=0;
}
}
}
Re: Hjälp med 16F1937
Hej!
Du ska nolla den aktuella IF flaggan i resp del av interrupt().
Sen så är jag osäker på om man måste skriva registret också...
Något i stil med:
Annars finns det en risk att nollat fel flaggor och missar interrupt.
Om t.ex INTF sätts medan du bearbetar TMR0IF så missas INTF...
Jag ser inte att du har satt upp "REGISTER 20-1: OPTION_REG: OPTION REGISTER".
Bl.a TMR0CS, PSA och PS<2:0> bör sättas så som du vill ha dom.
Sen så bara en kosmetisk detalj...
Istället för:
INTCON=0b10111000;
så tycker jag att detta är lättare att läsa (utan att behöva slå upp INTCON i databladet):
INTCON=0;
INTCON.GIE=1;
INTCON.TMR0IE=1;
INTCON.INTE=1;
INTCON.IOCIE=1;
Sen saknas nog:
OPTION.TMR0CS=0; //Timer0 Clock Source Select bit, Internal instruction cycle clock
OPTION.PSA=0; //Prescaler is assigned to the Timer0 module
Du ska nolla den aktuella IF flaggan i resp del av interrupt().
Sen så är jag osäker på om man måste skriva registret också...
Något i stil med:
Kod: Markera allt
void interrupt(){
if(INTCON.INTF==1){
SERVO=0;
k=1;
BACKLIGHT=0;
INTCON.INTF=0;
}
if(INTCON.TMR0IF==1){
PWM_OUT=1;
Delay_ms(2);
PWM_OUT=0;
INTCON.TMR0IF=0;
}
}
Om t.ex INTF sätts medan du bearbetar TMR0IF så missas INTF...
Jag ser inte att du har satt upp "REGISTER 20-1: OPTION_REG: OPTION REGISTER".
Bl.a TMR0CS, PSA och PS<2:0> bör sättas så som du vill ha dom.
Sen så bara en kosmetisk detalj...
Istället för:
INTCON=0b10111000;
så tycker jag att detta är lättare att läsa (utan att behöva slå upp INTCON i databladet):
INTCON=0;
INTCON.GIE=1;
INTCON.TMR0IE=1;
INTCON.INTE=1;
INTCON.IOCIE=1;
Sen saknas nog:
OPTION.TMR0CS=0; //Timer0 Clock Source Select bit, Internal instruction cycle clock
OPTION.PSA=0; //Prescaler is assigned to the Timer0 module
Re: Hjälp med 16F1937
Nu har jag satt de bitarna jag tycker verkar rätt i optionreg registret. Men det är tyst på PWM utgången
Har jag INTCON.INTF=0; INTCON.TMR0IE=0; satt i ISR så kan jag knappt generera det externa intruptet, bara väldigt sällan och då kan det typ helhänga sig på ngt sätt innan den går in och skriver servo error.
Har jag dem bortkommenterade och har INTCON=0b00000000; så funkar externa interuptet som det ska men fortfarande inget som händer på PWM_out.
Har testat att i main bara toggla PWm_OUT och det funkar så porten är iaf rätt definierad. Jag kan inte sambandet på var det blir fel
Har jag INTCON.INTF=0; INTCON.TMR0IE=0; satt i ISR så kan jag knappt generera det externa intruptet, bara väldigt sällan och då kan det typ helhänga sig på ngt sätt innan den går in och skriver servo error.
Har jag dem bortkommenterade och har INTCON=0b00000000; så funkar externa interuptet som det ska men fortfarande inget som händer på PWM_out.
Har testat att i main bara toggla PWm_OUT och det funkar så porten är iaf rätt definierad. Jag kan inte sambandet på var det blir fel
Kod: Markera allt
/*
Manöverpanel till fjärrvärme Pic16F1937, intern 8MHz OSC, extern MCLR
*/
#define BUZZ PORTC.F3 //Name ports
#define SERVO PORTD.F1
#define BACKLIGHT PORTC.F2
sbit PWM_OUT at RD0_bit;
int k=0;
char *text1;
char *text2;
//LCD module connection
sbit LCD_RS at RA0_bit;
sbit LCD_EN at RA1_bit;
sbit LCD_D4 at RA2_bit;
sbit LCD_D5 at RA3_bit;
sbit LCD_D6 at RA4_bit;
sbit LCD_D7 at RA5_bit;
sbit LCD_RS_Direction at TRISA0_bit;
sbit LCD_EN_Direction at TRISA1_bit;
sbit LCD_D4_Direction at TRISA2_bit;
sbit LCD_D5_Direction at TRISA3_bit;
sbit LCD_D6_Direction at TRISA4_bit;
sbit LCD_D7_Direction at TRISA5_bit;
//End LCD module connection
void initMain(){
TRISA=0b00000000;
TRISB=0b00110011;
TRISC=0b11000000;
TRISD=0b00000000;
TRISE=0b00000000;
LCDCON=0b00000000;
CPSCON0=0b00000000;
ANSELA=0;
ANSELB=0;
INTCON=0b10111000;
IOCBP=0b00000001;
OPTION_REG=0b00100111;
TMR0=180;
LCD_Init();
LCD_Cmd(_LCD_CURSOR_OFF);
LCD_Cmd(_LCD_CLEAR);
if(k!=1){ //Kontroll att main inte körs efter interupt
BUZZ=1;
delay_ms(50);
BUZZ=0;
//BACKLIGHT=1;
Lcd_out(1,1,"Remote Heater");
Lcd_out(2,1,"Sp-E 2014");
}
}
void interrupt(){
if(INTF==1){
SERVO=0;
k=1;
BACKLIGHT=0;
INTCON.INTF=0;
}
if(TMR0IF==1){
PWM_OUT=1;
Delay_ms(2);
PWM_OUT=0;
INTCON.TMR0IF=0;
}
//INTCON=0b00000000; //Nolla interupt för att det inte ska loopa hela tiden
}
void main() {
initMain();
while(1){
if(k==1){ //Hör till interuptet
BUZZ=1;
delay_ms(50);
BUZZ=0;
Lcd_out(1,1,"Servo Error!!!");
Lcd_out(2,1,"Reset panel!!!");
while(1){
SERVO=0;
BACKLIGHT=0;
BUZZ=0;
}
}
else if(Button(&PORTB, 5,1,0)||Button(&PORTB, 4,1,0)){
BACKLIGHT=1;
}
else if(Button(&PORTB, 5,1,1)&&Button(&PORTB, 4,1,1)){
BACKLIGHT=0;
}
}
}
Senast redigerad av newbadboy 5 juni 2014, 14:29:14, redigerad totalt 1 gång.
Re: Hjälp med 16F1937
> INTCON.TMR0IE=0;
"Enable" flaggan måste vara satt!
Du kanske menade INTCON.TMR0IF=0; (?).
Jag skulle ta och skala ner det hela till enbart ett litet
testprogram som enbart sätter upp en timer och ett
interrut för den.
Om det nu inte bara var TMR0IE...
"Enable" flaggan måste vara satt!
Du kanske menade INTCON.TMR0IF=0; (?).
Jag skulle ta och skala ner det hela till enbart ett litet
testprogram som enbart sätter upp en timer och ett
interrut för den.
Om det nu inte bara var TMR0IE...