Fórum témák
- • Általános antennás kérdések, válaszok
- • Alternativ HE találkozó(k)
- • Szünetmentes táp javítása, élesztése
- • Rádióamatőrök topikja
- • Számítógép hiba, de mi a probléma?
- • Magas nyomású tisztító működése, javítása
- • Hangsugárzó építés, javítás - miértek, hogyanok
- • Milyen zsebrádiót vegyek,amivel a gyenge rádióadókat is tudom fogni?
- • Felajánlás, azaz ingyen elvihető
- • Nyák nyomtató kérdések
- • Elfogadnám, ha ingyen elvihető
- • Tápegység
- • Theremin
- • Börze
- • LCD TV probléma
- • Napelem alkalmazása a lakás energia ellátásában
- • Inverter javítás
- • Erősítő mindig és mindig
- • Crystal radio - detektoros rádió
- • V-FET és SIT erősítő kapcsolások
- • XBOX kiegészítők, javítások átalakítások
- • Elektromos fűnyíró probléma
- • Digitális mérleg
- • Parkside akkuk javìtása
- • Briggs töltés
- • Erősítő építése elejétől a végéig
- • Vásárlás, hol kapható?
- • 3D nyomtatás
- • Laptop javítás, tuning
- • Kapcsolóüzemű táp 230V-ról
- • Érdekességek
- • Transzformátor készítés, méretezés
- • Elektromos kerékpár, robogó házilag
- • Relé kérdés
- • PIC - Miértek, hogyanok haladóknak
- • Erősítőhöz való hangsugárzó védelem (koppanásgátló)
- • Autórádió (fejegység) problémák, kérdések, válaszok
- • Arduino
- • Oszcilloszkóp, avagy hogyan kell használni?
- • Analóg oszcilloszkóp javítása
- • Akkumulátor töltő
- • Dansk 3f-T3535, és minden, ami vele kapcsolatos
- • Klíma szervizelés, javítás
- • PC-ről vezérlés
- • Labortápegység készítése
- • Videoton EA 6383 s (tuning)
- • Rossz pénztárgép
- • Androidos okos telefonok
- • METEX műszer
- • Villámdetektor
- • Kaputelefon
- • Elektromos távirányítós kapunyitó
- • Forrasztópáka fűtés probléma
- • Mosógép vezérlők és általános problémáik
- • LC mérő
» Több friss téma
|
A 8 bites PIC-ek timer-ének 16 bites mód haszálatakor a felső byte történő írása két részletben történik meg. A pdf 19.6 timer1 16-Bit Read/Write Mode (és a Figure 19-3. timer1 16-Bit Read/Write Mode Block Diagram ábra) leírja, ill. szemlélteti ezt. Az MSB ténylegesen csak akkor íródik be, ha utána az LSB-t is írod.
Sziasztok,
Tudna valaki segíteni.
A PIC18F47Q10 típusú kontrollerrel gyűlt meg a bajom. A timer1 16bites számláló legfelső bitjét kéne "1"-be állítani, de valamiért nem működnek az eddigi megszokott dolgok (bit_set(timer1H, 7), #bit, ..) csak a set_timer1(32768); és nem tudom mi a gond.
Az adatlap szerint - ami új ismeret - eleve be lehet állítani, hogy 8 vagy 16 bites működési módja legyen (RD1 bit) a számlálónak. Lehet, hogy ez a gond, mert hiába próbálom beállítani a 0x0FCD regiszter (timer1H) 7. bitjét, az sehogy se sikerül...
Ha valaki tud használható segítséget adni azt nagyon megköszönném...
Köszönöm.
Kiegészítés:
A PWM kitöltési tényezőjét a Timer3 interrup-jában állítom. A Timer 3 jó értéket ad.
void PWM_2_duty(unsigned char P2)
{
//P1DC1 = (2UL*P1TPER+2)*PWM_DUTY/100;
P2DC1 = (unsigned long int)P2;
}
void PWM_2_init(unsigned long int Fcy, unsigned long int PWM_2_Frekvencia){
//setup output pins
LATBbits.LATB8=0;
TRISBbits.TRISB8 = 0;
//setup PWM ports
PWM2CON1 = 0; //clear all bits (use defaults)
PWM2CON1bits.PMOD1 = 0; //PWM1Ly,PWM1Hy are in independent running mode
PWM2CON1bits.PEN1L = 0; //PWM1L1 NORMAL I/O
PWM2CON1bits.PEN1H = 1; //PWM1H1 PWM OUTPUT
//PWM mode and prescaler
//PWM1, MOTORS 0,1,2
P2TCON = 0; //clear all bits (use defaults)
P2TCONbits.PTMOD = 0b00; //Free-runing mode
// P1TCONbits.PTCKPS = 0b11; // 1:64 prescaler
P2TCONbits.PTCKPS = 0b00; // 1:1 prescaler
//setup desired frequency by setting period for 1:64 prescaler
// P1TPER = ((Fcy / (64 * PWM_Frekvencia)) - 1);
P2TPER = ((Fcy / (PWM_2_Frekvencia)) - 1);
//PWM_duty((unsigned int)(2UL*P1TPER+2)*0.5);
}
void PWM_2_start()
{
P2TMR = 0;
P2TCONbits.PTEN = 1;
}
void PWM_2_stop()
{
P2TMR = 0;
P2TCONbits.PTEN = 0;
}
És a main C-ben meghívom az PWM_2_init -et, és a timer3 interruptban:
void __attribute__((__interrupt__, no_auto_psv)) _T3Interrupt(void)
{
/* Interrupt Service Routine code goes here */
IFS0bits.T3IF = 0; // Clear Timer3 Interrupt Flag
////Ide kell a PWM kitöltési tényezoje
if (t3_szamlalo<255)
{
t3_szamlalo+=1;
}
else
{
t3_szamlalo =(unsigned long int)0;
}
P2DC1 =(unsigned long int)t3_szamlalo;
}
A hozzászólás módosítva: Márc 14, 2022
8 bites AVR-rel biztos nem lehet üzembiztosra, mert egyszerre történik az analóg komparátor, vagy négyszög jel esetén az INT0 megszakítás, az UART vétel megszakításával, valahogy összeakadnak mert nincs se prioritás, semmi, ja és még a millis() micros() hoz alapból fut a timer0, meg az oszcillátorhoz a timer1 de az itt nem zavar be.
Ebben az esetben valóban nem lesz jó, mert kezelni kell az érzékelőket is. Ami neked jó lehet, az az időzítő megszakítása:
/*
* Arduino 101: timer and interrupts
* 2: timer1 overflow interrupt example
* created by RobotFreak
*/
#define ledPin 13
void setup()
{
pinMode(ledPin, OUTPUT);
// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 34286; // preload timer 65536-16MHz/256/2Hz
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
}
ISR(timer1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{
TCNT1 = 34286; // preload timer
digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}
void loop()
{
// your program here...
}
A kódot nem én írtam, csak idemásoltam Forrás
Interrupttal is ki lehet küszöbölni a prellt könnyen:
Konfigurálsz egy timert, hogy mondjuk 50 milliszekundumonként fusson le (nagyjából, nem kell pontosnak lennie).
Ezt írod az interruptba:
static uint8_t prevSample=0;
ISR(timer1_ovf)
{
uint8_t sample=PINA&_BV(3);
if(sample==prevSample) // prellmentesites
{
if(sample!=0)
{
PORTB|=_BV(5);
}else
{
PORTB&=~_BV(5);
}
}
prevSample=sample;
}
Azért is jó ez a megoldás, mert a CPU terhelése állandó lesz, a másik elvben "éheztetheti" a többi taszkot, ha a bemenet sokáig prellezik. A hozzászólás módosítva: Dec 27, 2021
Tiszta jitter mentes a jele, meg rezgőkörrel már leszinuszosítottam, egy DDS modul lett volna ott de nem találom.
Az ardu csak a timer0 használja, timer1, timer2 szabad A hozzászólás módosítva: Okt 29, 2021
Gondolod hogy csak úgy mérek valamit és kijelentem, hogy az a hálózat frekvenciája? Min kellene elgondolkoni?
Nem kell semmilyen extra mérésben gondolkodni. 12 VAC, optocsatoló ( 6N137). A kimenet, némi szűrés után, a PIC komparátorára csatlakoztatva, az a timer1 kapuzását indítja, állítja. timer1 pedig 500 ns-os felbontásra állítva.
Nem a miértre, hanem a mennyire voltam kíváncsi. A kapott értékek jól összecsengenek az online adatokkal. Az érdekesség számomra annyi, hogy sokkal jobban ingadozik, mint gondoltam.
Ha jól emlékszem, abban a kontrollerben ( PIC18F46K22) összesen hét Timer van: Timer0, timer1, 3, 5 és Timer2, 4, 6.
Kösd át SPI-re a meghajtó IC-ket, sokat spórólhatsz az erőforrásokkal.
Sok RF modul jól működik, mondhatni remek ár/érték arányt képviselnek a szegmensben. Ugyanakkor a µs-os pontosságú időméréshez ezek messze-messze nem alkalmasak. Semmi sem garantálja hogy a késleltetés állandó és fix, ezek az RF modulok nem ilyen feladathoz lettek tervezve. Ráadásul 9600-as Baud mellett egy bájt kb. 1 ms idő alatt jön ki egy TX lábon. A logikai áramkörös, RF modulos történet szerintem eleve zsákutca.
Infra (lézeres) kapu -> kábel -> mikrokontroller.
Pl. egyszerű 8 bites PIC mikrokontrollerrel, 32 MHz-es órajel mellett, timer1 segítségével könnyen elérhető a 250 ns-os felbontás is.
Nagyot!
PIC16F1825, CCP modul, Compare mode: toggle output on match. Ha a timer1 előosztója 2, 4 vagy 8, akkor a kimenet folyamatosan alacsony szinten van. Akkor működik a kimenet váltogatása, ha a timer1 előosztója 1:1. Régi téma: Bővebben: Link. Tud valaki megoldásról?
Ezt a programot Githubon találtam ( Link ) , ezen már tudom változtatni a PWM frekijét, az viszont jó kérdés hogy a kimeneti freki mekkora? Ami másik fura hogy a szkópon néha mintha nem ellenfázisú jelet mutatna hanem azonost? Ez lehet a szkópom egyik mérőkábelének hibája is de lehet a kódé, az előző fix 50hz-es kódnál stabil volt a képem, itt ugrál kicsit.
A0 a bemenet a potmétertől 10-13-as láb az SPWM jel kimenet, elvileg ellenfázisban egymással.
#include <avr/io.h>
#include <avr/interrupt.h>
#define LookupEntries (512)
//Varible declaration
static int microMHz = 16; // Micro clock frequency
static int freq; // Sinusoidal frequency
static long int period; // Period of PWM in clock cycles. 1600 gives 10KHz.
static unsigned int lookUp[LookupEntries];
static char theTCCR1A = 0b10000010; //varible for TCCR1A
static unsigned long int phaseinc, switchFreq;
static double phaseincMult;
//Function prototypes
int setFreq(int _freq);
int setSwitchFreq(int sfreq);
void registerInit(void);
void setup(){
Serial.begin(9600);
setSwitchFreq(10000);
setFreq(50);
registerInit();
}
void loop(){
/*
// Un-comment inorder to read from A1 to change the switching frequency, note that if you have a noisey potentiometer the
// it will disrupt the signal as the lookup table needs to be regenerated everytime the switing frequency is changed
int sensorValue = analogRead(A1);
static int sensorValue2;
if(sensorValue > sensorValue2*1.01 || sensorValue < sensorValue2*0.99){
sensorValue2 = sensorValue;
setSwitchFreq(map(sensorValue, 0, 1023, 1000, 19000));
Serial.println(switchFreq);
Serial.print(phaseinc>>23);
Serial.print(".");
Serial.print(phaseinc&0x007FFFFF);
Serial.print("\n");
}*/
// Value read in from A0 changes the frequency of the sine wave
int sensorValue = analogRead(A0);
static int sensorValue2;
if(sensorValue > sensorValue2*1.01 || sensorValue < sensorValue2*0.99){
sensorValue2 = sensorValue;
setFreq(map(sensorValue, 0, 1023, 5, 300));
Serial.print(phaseinc>>23);
Serial.print(".");
Serial.print(phaseinc&0x007FFFFF);
Serial.print("\n");
}
}
ISR(timer1_OVF_vect){
static unsigned long int phase, lastphase;
static char delay1, trig = LOW;
phase += phaseinc;
if(delay1 > 0){ // toggle the output pins one ISR call after phase has overflowed
theTCCR1A ^= 0b10100000;// Toggle connect and disconnect of compare output A and B.
TCCR1A = theTCCR1A;
delay1 = 0;
}
else if((phase>>31 != lastphase>>31) && !(phase>>31)){ //if phase has overflowed . . .
delay1++;
trig = !trig;
digitalWrite(13,trig); // pin can be used as triggre on oscilloscope
}
lastphase = phase;
OCR1A = OCR1B = lookUp[phase >> 23];
}
int setFreq(int _freq){
if(_freq < 0 || _freq > 1000){ // returns 0 if the frequency value is invalid
return 0;
} else {
freq = _freq;
phaseinc = (unsigned long int) phaseincMult*_freq;
return 1; // returns 1 if freqency set sucessfully
}
}
int setSwitchFreq(int sfreq){
double temp;
if(sfreq <= 0 || sfreq > 20000){
return 0;
} else {
switchFreq = sfreq;
period = microMHz*1e6/sfreq;
cli(); //disable global interupts while lookup table is made
TCCR1A = 0b00000010; //disconnect compare A and B while lookup table is generated
for(int i = 0; i < LookupEntries; i++){ // Generating the look up table.
temp = sin(i*M_PI/LookupEntries)*period;
lookUp[i] = (int)(temp+0.5); // Round to integer.
}
//sindevisions*decimalbits/1MHz =
//1024*2^23/1e6 = 8,589.934592
phaseincMult = (double) period*8589.934592/microMHz;
phaseinc = (unsigned long int) phaseincMult*freq;
TCCR1A = theTCCR1A; // reconnect compare outputs
sei(); //re-enable interupts now that table has been made
return 1;
}
}
void registerInit(void){
// Register initilisation, see datasheet for more detail.
TCCR1A = theTCCR1A; // 0b10000010;
/*10 clear on match, set at BOTTOM for compA.
00 compB disconected initially, toggled later to clear on match, set at BOTTOM.
00
10 WGM1 1:0 for waveform 15.
*/
TCCR1B = 0b00011001;
/*000
11 WGM1 3:2 for waveform 15.
001 no prescale on the counter.
*/
TIMSK1 = 0b00000001;
/*0000000
1 TOV1 Flag interrupt enable.
*/
sei(); // Enable global interrupts.
// Set outputs pins.
DDRB = 0b00000110; // Set PB1 and PB2 as outputs.
pinMode(13, OUTPUT); // Set trigger pin to output
}
Még azt is meg lehetne oldani, hogy a timer1 működik ugyanilyen frekvenciával, mnt most és a táblázat tökéletes lesz. De a megszakítást, ami a frekvenciát állítja, azt átdrótozni a timer2-re. Sajnos, az csak 8 bites, ezért vélhetőleg nem tudod majd olyan finoman állítani a frekit. Ha szükséges a freki nagyon finom állítása, akkor át kell állni olyan MCU-ra amiben van 2 darab 16 bites timer. ( atmega328pb, lgt8f328p, esetleg atmega2560)
Sziasztok.
Van egy programom ami SPWM jelet állít elő az arduino 2 kimenetén, egymással ellenfázisban. ![](/pic/smile/smile.gif)
Olyan kérdésem volna hogy ha átírom hogy A0 bemeneten a szokásos potméteres szabályozással 2hz-200hz közt tudjam változtatni az SPWM frekvenciáját, akkor az nem lenne már túl sok számítás az arduino részére?
A két kimenet a 9-es és 10-es PWM lábon jön le.
A kódot lentebb beillesztem.
#include <avr/io.h>
#include <avr/interrupt.h>
// Look up tables with 200 entries each, normalised to have max value of 1600 which is the period of the PWM loaded into register ICR1.
int lookUp1[] = {
50 ,100 ,151 ,201 ,250 ,300 ,349 ,398 ,446 ,494 ,
542 ,589 ,635 ,681 ,726 ,771 ,814 ,857 ,899 ,940 ,
981 ,1020 ,1058 ,1095 ,1131 ,1166 ,1200 ,1233 ,1264 ,1294 ,
1323 ,1351 ,1377 ,1402 ,1426 ,1448 ,1468 ,1488 ,1505 ,1522 ,
1536 ,1550 ,1561 ,1572 ,1580 ,1587 ,1593 ,1597 ,1599 ,1600 ,
1599 ,1597 ,1593 ,1587 ,1580 ,1572 ,1561 ,1550 ,1536 ,1522 ,
1505 ,1488 ,1468 ,1448 ,1426 ,1402 ,1377 ,1351 ,1323 ,1294 ,
1264 ,1233 ,1200 ,1166 ,1131 ,1095 ,1058 ,1020 ,981 ,940 ,
899 ,857 ,814 ,771 ,726 ,681 ,635 ,589 ,542 ,494 ,
446 ,398 ,349 ,300 ,250 ,201 ,151 ,100 ,50 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0};
int lookUp2[] = {
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
50 ,100 ,151 ,201 ,250 ,300 ,349 ,398 ,446 ,494 ,
542 ,589 ,635 ,681 ,726 ,771 ,814 ,857 ,899 ,940 ,
981 ,1020 ,1058 ,1095 ,1131 ,1166 ,1200 ,1233 ,1264 ,1294 ,
1323 ,1351 ,1377 ,1402 ,1426 ,1448 ,1468 ,1488 ,1505 ,1522 ,
1536 ,1550 ,1561 ,1572 ,1580 ,1587 ,1593 ,1597 ,1599 ,1600 ,
1599 ,1597 ,1593 ,1587 ,1580 ,1572 ,1561 ,1550 ,1536 ,1522 ,
1505 ,1488 ,1468 ,1448 ,1426 ,1402 ,1377 ,1351 ,1323 ,1294 ,
1264 ,1233 ,1200 ,1166 ,1131 ,1095 ,1058 ,1020 ,981 ,940 ,
899 ,857 ,814 ,771 ,726 ,681 ,635 ,589 ,542 ,494 ,
446 ,398 ,349 ,300 ,250 ,201 ,151 ,100 ,50 ,0};
void setup(){
// Register initilisation, see datasheet for more detail.
TCCR1A = 0b10100010;
/*10 clear on match, set at BOTTOM for compA.
10 clear on match, set at BOTTOM for compB.
00
10 WGM1 1:0 for waveform 15.
*/
TCCR1B = 0b00011001;
/*000
11 WGM1 3:2 for waveform 15.
001 no prescale on the counter.
*/
TIMSK1 = 0b00000001;
/*0000000
1 TOV1 Flag interrupt enable.
*/
ICR1 = 1600; // Period for 16MHz crystal, for a switching frequency of 100KHz for 200 subdevisions per 50Hz sin wave cycle.
sei(); // Enable global interrupts.
DDRB = 0b00000110; // Set PB1 and PB2 as outputs.
pinMode(13,OUTPUT);
}
void loop(){; /*Do nothing . . . . forever!*/}
ISR(timer1_OVF_vect){
static int num;
// change duty-cycle every period.
OCR1A = lookUp1[num];
OCR1B = lookUp2[num];
if(++num >= 200){ // Pre-increment num then check it's below 200.
num = 0; // Reset num.
}
}
A segítséget megköszönném, mert a Timer kezelése gondot okoz. Próbáltam már, de nem sikerült. Váltottam egy olyan kontrollerre, amiben van belső órajel: PIC16F627A.
Ez volna a program __delay paranccsal. Ami a Proteus 8 szimulációval jól is működik, de csak 20 Mhz-nél. Ha sokkal alacsonyabb, akkor a másodpercek lassabban telnek. A valóságban pedig minden összevisszaság van. Ki van kommentelve a Timer-es próbálkozásom.
A program (még PIC16F718-ra):
#include <xc.h>
#define _XTAL_FREQ 20000000 //define crystal frequency to 20MHz
// CONFIG
#pragma config FOSC = RC // Oscillator Selection bits (RC oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define gomb RA0
int k=0;
int z=3;
int t;
int n=1;
void main() {
ADCON1 = 0x0F; //digitális bemenet és nem analóg
TRISB = 0x00; //Port-B as Output
TRISA = 0x01; //RA as input
//T1CON = 0x30; //Timer beállítás. ki kell számolni 1 sec alatti m?veletek számát: XTAL_FREQ/4/Prescaler= 1 sec alatti m?veletszám
// megszakítások beállítása
/* PIE1bits.TMR1IE=1; // timer1 megszak. engedélyezés
PIR1bits.TMR1IF=0; // timer1 megszakításjelz? törlése
INTCONbits.PEIE=1; // periféria megszak. engedélyezés
INTCONbits.GIE=1; */ // globális megszak. engedélyezés
// TMR1H=0x0B; Feltöltés 16 bit-es timernél a fels? és als? 8 bitet külön adjuk meg. Vagy hexadec vagy rendes számmal.
//TMR1L=0xDB; Innen fog indulni egyesével felfelé a számláló és FFFF-nél túlcsordul, akkor indul 0-ról vagy újabb feltöltésnél onnantól
//TMR1=3035;
/*T1CONbits.TMR1ON=0; //Timer nem indul
PIR1bits.TMR1IF=0; //Nincs túlcsordulva*/
while (1)
{
if (gomb==1)
{
__delay_ms(300);
if (gomb==1)
{__delay_ms(2000);
if (gomb==1)
{ PORTBbits.RB6=1;
__delay_ms(1000);
PORTBbits.RB6=0;
__delay_ms(1000);
PORTBbits.RB6=1;
// T1CONbits.TMR1ON=1;
z=0;
while (n)
{__delay_ms(1000);
// if (PIR1bits.TMR1IF==1) //ha túlcsordult
// { PIR1bits.TMR1IF=0;
z=z+1;
if (gomb==1) {n=0;}
}
// T1CONbits.TMR1ON=0;
PORTBbits.RB6=0;
}
// n=1;
}
else
{
PORTBbits.RB3=1;
// T1CONbits.TMR1ON=1;
k=0;
while (k<z+2)
{
__delay_ms(1000);
//if (PIR1bits.TMR1IF==1) //ha túlcsordult
// { PIR1bits.TMR1IF=0;
k=k+1;
if (k==1)
{
PORTBbits.RB5=1;
}
if (gomb==1)
{PORTBbits.RB5=0;}
if (k==z+1)
{
PORTBbits.RB5=0;
}
if (k==z+2)
{
PORTBbits.RB3=0; }
}
//T1CONbits.TMR1ON=0;
}
}
else
{PORTBbits.RB3=0;
PORTBbits.RB5=0;
PORTBbits.RB6=0;}
}
}
Működés:
A nyomógombra egy relé meghúz, majd 1 sec múlva egy másik is behúz. 3 sec múlva a második elenged és ezután 1 sec múlva az első is elenged.
Ha hosszan nyomjuk a gombot, akkor egy LED felvillan és onnantól számolja a másodperceket, ha ismét megnyomjuk a gombot, akkor leáll. Ezt az időt azért számolja, mert innentől kezdve a második relé már nem 3 sec-ig fog behúzva lenni, hanem eddig a megváltoztatott ideig.
Köszönöm!!
Sziasztok!
Ezt a programot szeretném UPP628-as programozóval beégetni:
#include <xc.h>
#define _XTAL_FREQ 2097120 //define crystal frequency to 20MHz
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (RC oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define gomb RA0
int k=0;
int z=3;
int t;
int n=1;
void main() {
ADCON1 = 0x0F; //digitális bemenet és nem analóg
TRISB = 0x00; //Port-B as Output
TRISA = 0x01; //RA as input
T1CON = 0x30; //Timer beállítás. ki kell számolni 1 sec alatti m?veletek számát: XTAL_FREQ/4/Prescaler= 1 sec alatti m?veletszám
// megszakítások beállítása
/* PIE1bits.TMR1IE=1; // timer1 megszak. engedélyezés
PIR1bits.TMR1IF=0; // timer1 megszakításjelz? törlése
INTCONbits.PEIE=1; // periféria megszak. engedélyezés
INTCONbits.GIE=1; */ // globális megszak. engedélyezés
// TMR1H=0x0B; Feltöltés 16 bit-es timernél a fels? és als? 8 bitet külön adjuk meg. Vagy hexadec vagy rendes számmal.
//TMR1L=0xDB; Innen fog indulni egyesével felfelé a számláló és FFFF-nél túlcsordul, akkor indul 0-ról vagy újabb feltöltésnél onnantól
//TMR1=3035;
T1CONbits.TMR1ON=0; //Timer nem indul
PIR1bits.TMR1IF=0; //Nincs túlcsordulva
while (1)
{
if (gomb==1)
{
__delay_ms(300);
if (gomb==1)
{__delay_ms(2000);
if (gomb==1)
{ PORTBbits.RB6=1;
__delay_ms(1000);
PORTBbits.RB6=0;
__delay_ms(1000);
PORTBbits.RB6=1;
// T1CONbits.TMR1ON=1;
z=0;
while (n)
{__delay_ms(1000);
// if (PIR1bits.TMR1IF==1) //ha túlcsordult
// { PIR1bits.TMR1IF=0;
z=z+1;
if (gomb==1) {n=0;}
}
// T1CONbits.TMR1ON=0;
PORTBbits.RB6=0;
}
n=1;
}
PORTBbits.RB3=1;
T1CONbits.TMR1ON=1;
k=0;
while (k<z+2)
{
if (PIR1bits.TMR1IF==1) //ha túlcsordult
{ PIR1bits.TMR1IF=0;
k=k+1;}
if (k==1)
{
PORTBbits.RB5=1;
}
if (gomb==1)
{PORTBbits.RB5=0;}
if (k==z+1)
{
PORTBbits.RB5=0;
}
if (k==z+2)
{
PORTBbits.RB3=0;
}
}
T1CONbits.TMR1ON=0;
}
}
}
A program szépen lefordult, az égetés után azt írja "Konfig word hiba".
Az ellenőrzésre pedig ezt:
"Kód hiba itt:0x0000 Kiolvasva 0x3FFF, ellenőrizva: 0x2FF2"
Mi lehet az oka?
Köszönöm!
Az lehet a gond, hogy a tmr1 tovább számol a TMR1IF beállítása után, de a program megint csak a 3035=65536-62500 -at tölti bele, azaz néhány számlálás elveszik másodpercenként.
A jó módszer a TMR1 aktuális értékéhez való hozzáadás lenne, ami nem egyszerű a 16 bites érték és a módosítás közbeni alsó byte átfordulás miatt. (ld.timer1 Errata).
Jobb lett volna a TMR2 -t használni. Vele nem lehet 1s időt előállítani, de ha hozzáteszünk egy szoftver számlálót, akkor meg lehet csinálni.
A Te megoldásod nem működik nálam, de a tőletek kapott segítségekből összeraktam a saját elképzelésemet és ez így tökéletes. Most még csak annyit tud, hogy az egyik kimenet a nyomógombra azonnal magas lesz, egy másik csak később. A többi szükséges verziót már össze tudom hozni. Köszönöm!
#include <xc.h>
#define _XTAL_FREQ 20000000 //define crystal frequency to 20MHz
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (RC oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define gomb RA0
int k=0;
void main() {
ADCON1 = 0x0F;
TRISB = 0x00; //Port-B as Output
TRISA = 0xFF; //RA as input
T1CON = 0x30;
// megszakítások beállítása
/* PIE1bits.TMR1IE=1; // timer1 megszak. engedélyezés
PIR1bits.TMR1IF=0; // timer1 megszakításjelző törlése
INTCONbits.PEIE=1; // periféria megszak. engedélyezés
INTCONbits.GIE=1; */ // globális megszak. engedélyezés
TMR1H=0xD9;
TMR1L=0xDB;
T1CONbits.TMR1ON=0;
PIR1bits.TMR1IF=0;
while (1)
{
if (gomb==1)
{
PORTBbits.RB3=1;
T1CONbits.TMR1ON=1;}
if (PIR1bits.TMR1IF==1)
{ PIR1bits.TMR1IF=0;
TMR1H=0xD9;
TMR1L=0xDB;
k=k+1;
if (k==30)
{
PORTBbits.RB5=1;
}
}
}
}
Nem ártana engedélyezni a megszakításokat (a while(1) ciklus előtt).
// megszakítások beállítása
PIE1bits.TMR1IE=1; // timer1 megszak. engedélyezés
PIR1bits.TMR1IF=0; // timer1 megszakításjelző törlése
INTCONbits.PEIE=1; // periféria megszak. engedélyezés
INTCONbits.GIE=1; // globális megszak. engedélyezés
Továbbá ha regiszterek bitjeire hivatkozol, akkor ne felejtsd el odaírni azt hogy 'bits', mint ahogy az a fenti példában is látható. A hozzászólás módosítva: Ápr 20, 2021
Ha ilyen nagy időközönként kell bármit csinálnia, akkor szerintem a legegyszerűbb ha olyan PIC-et használsz aminél a timer1-et lehet külön külső kvarcról hajtani. Ha erre teszel egy 32,764 kHz-es óra kvarcot akkor alapból 2 másodpercenként generál megszakítást. 2 másodperc rengeteg idő, közben csinálhat mást a PIC.
pinMode (9, OUTPUT);
pinMode (10, OUTPUT);
TCCR1A = 0;
TCCR1B = 0;
TCCR1A = _BV(WGM11) | _BV(COM1A1) | _BV(COM1B1);
TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(CS12) | _BV(WGM12);
ICR1 = 31249; //periódus idő, 2 másodperc
OCR1A = 15000; //D9 kitöltés
OCR1B = 15000; //D10 kitöltés
Az ICR1 regiszter a periódus időt határozza meg. 65535-nél nagyobb nem lehet. Az kicsit több, mint 4 másodperces periódus időt tesz ki. Most 2 másodpercre van állítva. Az OCR1x regiszter a két kimenet PWM értékét tartalmazza. Maximum értéke az ICR1 lehet.
Max 4,19 másodperces periódus idő a maximum, amit tud a timer1 16 MHz-es órajel mellett fast PWM-ben, 1024-es előosztó mellett. Fázis korrekt PWM-ben a dupláját. Ha ennél is hosszabb periódus idő kell, akkor már az MCU órajel előosztóját is osztásra kell állítani, ami lassítja a műveletek elvégzését. De azzal cirka 2145 másodperces periódus időt lehet elérni. Ha ennél is nagyobb periódus idő kell, akkor már le kell cserélni lassabbra a kvarcot.
A timer1 megszakítás engedélyezve van de ez nincs kezelve sehol. Biztos ami biztos, kapcsold ki a teszt idejére. Nem vagyok benne biztos, hogy összehasonlító (compare) módban biztosan nem keletkezik ott megszakítás, lévén egy külön modul, csak éppen kapcsolódik másik modulhoz is, jelen esetben.
compare: összehasonlít
A komparátort kis hazánkban analóg összehasonlítóra használjuk, az adatlapban is kétféle elnevezés van: Comparator és Compare module. Ne keverd a kettőt.
Te váltogatni akarod a LAT regisztert, ezért kell azt olvasni és módosítani. Ha azt akarod invertálni, akkor azt is kell olvasni, nem egy másikat, még ha összefüggés is van a kettő közt. A hozzászólás módosítva: Dec 22, 2020
Hát, nem is tudom. Amit írtál kódot az gyakorlatilag ugyanaz. LAT -al írok PORT -al olvasok (így tanultam).
Amúgy a PORT regisztert soha nem írom, csak beolvasom az épp aktuális jelszintet.
Ha a LAT -ból olvasok az csak a pufferből olvassa vissza a beállított szintet, nem pedig a valós jelszintet adja vissza. De lehet rosszul tudom, Te vagy a szaki ![](/pic/smile/smile.gif)
Bemásolom az egészet hátha felfedezel valami extra hibát:
/************ 8MHz külső kristállyal **********/
#include <xc.h>
#include <pic18f27k40.h>
#include "config.h"
/************ Globális változók ***********/
volatile unsigned int cnt = 0;
/*************** Deklarációk **************/
void init_base(void);
void init_interrupt(void);
void init_tmr1(void);
void __interrupt(high_priority) Isr(void);
void main(void) {
init_base();
init_interrupt();
init_tmr1();
/************** Főprogram *************/
while(1){
}
return;
}
/***************** Alapbeállítások ****************/
void init_base(void){
// Az összes lábat analógról digitálisra állítom
ANSELA = 0;
ANSELB = 0;
ANSELC = 0;
// Az összes lábat kimenetnek állítom be
TRISA = 0;
TRISB = 0;
TRISC = 0;
// Az összes láb jelszintjét alacsonyra állítom
LATA = 0;
LATB = 0;
LATC = 0;
}
/**************** Megszakítás beállításai ***************/
void init_interrupt(void){
INTCONbits.GIE_GIEH = 1; // Globális megszakítás engedélyezve
INTCONbits.PEIE_GIEL = 1; // Perifériás megszakítás engedélyezve
INTCONbits.IPEN = 0; // Megszakítások prioritása letiltva
PIE4bits.TMR1IE = 1; // timer1 megszakítás engedélyezve
PIE6bits.CCP1IE = 1; // Komparátor modul megszakítás engedélyezve
}
/***************** timer1 beállításai ***************/
void init_tmr1(void){
T1CONbits.ON = 0; // timer1 kikapcsolása a beállítások előtt
T1CONbits.CKPS = 0b11; // Előosztó 1:8
T1CONbits.RD16 = 1; // 16 bites mód beállítása
TMR1CLKbits.CS = 0b0001; // Órajelforrás Fosc/4
TMR1 = 0; // Számláló kezdőérték nullázása
/* 8 MHz -es kristállyal 500ns -onként fogja léptetni a számlálót. Ha 1:1 az előosztó.
* 8 lépés 1us.
* Ha 1:8 az előosztó, akkor 4us-onként lépteti a számlálót.
* A számláló 16 bites akkor 65535-ig tud számolni. 2500 lépés 10ms, akkor a komparátor
* regisztereit 2500-ra kell állítani. Ez a CCPR1H és a CCPR1L. */
CCP1CONbits.EN = 0; // CCP1 letiltása a beállítások előtt
//CCP1CONbits.MODE = 0b1011; // CCP1 Compare mód beállítása "Pulse output; clear TMR1"
CCP1CONbits.MODE = 0b0010; // CCP1 Compare mód beállítása "Toggle output" váltogatja a kimenetet
CCPR1 = 2500; // Komparálási érték beállítása.
CCP1CONbits.EN = 1; // CCP1 indítása a beállítások után
T1CONbits.ON = 1; // timer1 indítása a beállítások után
}
/*************** Megszakításkor lefutó függvény ***************/
void Isr(void){
// Ha a komparátor okozott megszakítást
if(PIR6bits.CCP1IF){ // Eltelt 10ms
PIR6bits.CCP1IF = 0; // Törlöm a megszíktást jelző bitet
/*cnt++;
if(cnt == 50){
LATCbits.LATC2 = ~PORTCbits.RC2;
cnt = 0;
}*/
}
// Ha timer1 okozott megszakítást
if(PIR4bits.TMR1IF){
//LATCbits.LATC2 = 1;
// Komparátor módban a timer1 soha nem fog túlcsordulni, mert az összehasonlításkor
// ha megegyeznek a beállított értékek akkor automatikusan törlődik a számláló
// lenullázódik és kezdődik a számolás előlről.
}
}
Tehát, ez a kód, ami fagy, vagy újraindulást eredményez néha. A kód még közel sem kész, a hardver konfigurálásához használom (használnám) egyenlőre.
Szerk: ha a megszakítást nem tiltom le az LCD kezelése előtt, akkor az enkóder első kattanására befagy. A 13-as lábon lévő LED-et azért villogtatom, hogy lássa, van-e fagyás.
#include <Adafruit_MCP4728.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
Adafruit_MCP4728 mcp;
LiquidCrystal_I2C lcd(0x26, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
byte A = 0;
volatile unsigned int lepes = 0;
unsigned int lepesv = 1;
unsigned int szam = 0;
void setup() {
analogReference(EXTERNAL);
mcp.begin();
lcd.begin(16, 2);
lcd.setCursor(4, 0);
lcd.print("F\x01mkeres\x07");
delay(1000);
lcd.clear();
DDRB |= _BV (2);
DDRB |= _BV (3);
DDRB |= _BV (4);
DDRD |= _BV (0);
DDRD |= _BV (1);
DDRB |= _BV (1);
DDRD &= ~_BV (7);
DDRD &= ~_BV (4);
PORTD |= _BV (4);
PORTD |= _BV (7);
DDRB |= _BV (5);
lcd.clear();
mcp.setChannelValue(MCP4728_CHANNEL_A, 4095, MCP4728_VREF_INTERNAL, MCP4728_GAIN_2X);
mcp.setChannelValue(MCP4728_CHANNEL_B, 4095, MCP4728_VREF_INTERNAL, MCP4728_GAIN_2X);
mcp.setChannelValue(MCP4728_CHANNEL_C, 1024, MCP4728_VREF_INTERNAL, MCP4728_GAIN_2X);
mcp.setChannelValue(MCP4728_CHANNEL_D, 3066, MCP4728_VREF_INTERNAL, MCP4728_GAIN_2X);
Wire.setClock(300000);
PCICR = 0b00000100;
PCMSK2 = 0b10010000;
}
void loop() {
delay(1000);
PORTB |= _BV (5);
delay(1000);
PORTB &= ~_BV (5);
PCICR = 0;
PCIFR = 0;
lcd.setCursor(0, 0);
lcd.print(lepes);
lcd.print(" ");
lcd.print(szam);
delay(1);
PCICR = 0b00000100;
if (lepes != lepesv) {
if (lepes >= 4) {
lepes = 0;
}
if (lepes == 0) {
timer10();
}
if (lepes == 1) {
timer15();
}
if (lepes == 2) {
Timer20();
}
if (lepes == 3) {
Timer25();
}
lepesv = lepes;
}
}
void Timer25() {
PCICR = 0;
PCIFR = 0;
lcd.setCursor(0, 1);
lcd.print("25kHz");
delay(1);
PCICR = 0b00000100;
PORTB &= ~_BV (2);
PORTB &= ~_BV (3);
PORTB &= ~_BV (4);
int setgnd = 0;
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCCR3A = 0;
TCCR3B = 0;
TCCR3A = 0;
TCCR3B = 0;
TCCR1A = _BV(WGM11) | _BV(COM1A1);
TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(WGM12);
OCR1A = 319;
TCNT1 = setgnd;
TCCR3A = _BV(WGM31) | _BV(COM3A1);
TCCR3B = _BV(WGM33) | _BV(CS30) | _BV(WGM32);
ICR3 = 639;
OCR3A = 319;
TCNT3 = setgnd;
TCCR4A = _BV(WGM41) | _BV(COM4A1);
TCCR4B = _BV(WGM43) | _BV(CS40) | _BV(WGM42);
ICR4 = 639;
OCR4A = 319;
TCNT4 = setgnd;
interrupts();
}
void Timer20() {
PCICR = 0;
PCIFR = 0;
lcd.setCursor(0, 1);
lcd.print("20kHz");
delay(1);
PCICR = 0b00000100;
PORTB |= _BV (2);
PORTB &= ~_BV (3);
PORTB &= ~_BV (4);
int setgnd = 0;
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCCR3A = 0;
TCCR3B = 0;
TCCR3A = 0;
TCCR3B = 0;
TCCR1A = _BV(WGM11) | _BV(COM1A1);
TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(WGM12);
OCR1A = 399;
TCNT1 = setgnd;
TCCR3A = _BV(WGM31) | _BV(COM3A1);
TCCR3B = _BV(WGM33) | _BV(CS30) | _BV(WGM32);
ICR3 = 799;
OCR3A = 399;
TCNT3 = setgnd;
TCCR4A = _BV(WGM41) | _BV(COM4A1);
TCCR4B = _BV(WGM43) | _BV(CS40) | _BV(WGM42);
ICR4 = 799;
OCR4A = 399;
TCNT4 = setgnd;
interrupts();
}
void timer15() {
PCICR = 0;
PCIFR = 0;
lcd.setCursor(0, 1);
lcd.print("15kHz");
delay(1);
PCICR = 0b00000100;
PORTB |= _BV (2);
PORTB |= _BV (3);
PORTB &= ~_BV (4);
int setgnd = 0;
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCCR3A = 0;
TCCR3B = 0;
TCCR3A = 0;
TCCR3B = 0;
TCCR1A = _BV(WGM11) | _BV(COM1A1);
TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(WGM12);
OCR1A = 532;
TCNT1 = setgnd;
TCCR3A = _BV(WGM31) | _BV(COM3A1);
TCCR3B = _BV(WGM33) | _BV(CS30) | _BV(WGM32);
ICR3 = 1065;
OCR3A = 532;
TCNT3 = setgnd;
TCCR4A = _BV(WGM41) | _BV(COM4A1);
TCCR4B = _BV(WGM43) | _BV(CS40) | _BV(WGM42);
ICR4 = 1065;
OCR4A = 532;
TCNT4 = setgnd;
interrupts();
}
void timer10() {
PCICR = 0;
PCIFR = 0;
lcd.setCursor(0, 1);
lcd.print("10kHz");
delay(1);
PCICR = 0b00000100;
PORTB |= _BV (2);
PORTB |= _BV (3);
PORTB |= _BV (4);
int setgnd = 0;
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCCR3A = 0;
TCCR3B = 0;
TCCR3A = 0;
TCCR3B = 0;
TCCR1A = _BV(WGM11) | _BV(COM1A1);
TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(WGM12);
OCR1A = 799;
TCNT1 = setgnd;
TCCR3A = _BV(WGM31) | _BV(COM3A1);
TCCR3B = _BV(WGM33) | _BV(CS30) | _BV(WGM32);
ICR3 = 1599;
OCR3A = 799;
TCNT3 = setgnd;
TCCR4A = _BV(WGM41) | _BV(COM4A1);
TCCR4B = _BV(WGM43) | _BV(CS40) | _BV(WGM42);
ICR4 = 1599;
OCR4A = 799;
TCNT4 = setgnd;
interrupts();
}
ISR(PCINT2_vect) {
A = A + ((PIND & _BV (4)) == 0) << 1;
A = A + ((PIND & _BV (7)) == 0) << 1;
A = A << 2;
if (A == 136) lepes--;
if (A == 144) lepes++;
szam++;
}
A hozzászólás módosítva: Dec 17, 2020
Sziasztok!
Mi a baj az alábbi kóddal? A rand() -al nem stimmel valami? Ha kiveszem a kódból akkor lefut rendesen hiba nélkül, de ha ott van akkor hibát jelez.
//megszakításkor lefutó függvény
void myHighISR(void){
/* Ha Timer0 okozta a megszakítást */
if(INTCONbits.T0IF){
// Eltelt 1ms
INTCONbits.T0IF = 0; // A tulcsordulást jelző bitet 0-ra állítom
TMR0 = 131; // Timer0 beállítása hogy honnan induljon.
t0_cnt++; // 1ms -onként léptetem a számlálót
if(t0_cnt >= 1000){
// Eltelt 1s
t1 = 65511 + ( rand() % 10 ); // Beállítom az új random frekvenciát
}
}
/* Ha timer1 okozta a megszakítást */
if(PIR1bits.TMR1IF){
PIR1bits.TMR1IF = 0; // A tulcsordulást jelző bitet 0-ra állítom
GPIObits.GP5 = ~GPIObits.GP5; // A kimeneti láb szintjét megfordítom.
TMR1 = t1; // timer1 beállítása hogy honnan induljon.
}
}
Be van includolva az stdlib.h. Ha jól tudom abban van a rand definíciója. A hozzászólás módosítva: Okt 19, 2020
Próbálom a timer1-et beállítani de nem teljesen tiszta minden. Bemásolom az eddigi kódom, majd nézzétek meg hogy jó-e:
void main(void) {
ANSEL = 0x0; // az összes analóg kimenet letiltva. Digitálisra állítva.
ADCON0bits.ADON = 0; // A/D átalakító letiltva. Nem fogyaszt áramot.
TRISIObits.TRISIO5 = 0; // A GP5-ös láb kimenet
PIE1bits.TMR1IE = 1; // timer1 megszakítást engedélyező bit bekapcsolva
INTCONbits.GIE = 1; // Globális megszakítás engedélyezése
INTCONbits.PEIE = 1; // Periféria megszakítás engedélyezése
T1CONbits.TMR1GE = 0; // 6.bit. Tiltókapu kikapcsolva. timer1 állandóan működik.
T1CONbits.T1CKPS1 = 0; // 5.bit. Előosztó első bitje
T1CONbits.T1CKPS0 = 1; // 4.bit. Előosztó második bitje. Ez így 1:2 -es osztási arány
T1CONbits.T1OSCEN = 0; // 3.bit. timer1 oszcillátor kikapcsolva
T1CONbits.nT1SYNC = 0; // 2.bit. Külső órajelszinkroizálónak most nincs szerepe
T1CONbits.TMR1CS = 0; // 1.bit. Belső órajel kiválasztása
T1CONbits.TMR1ON = 0; // 0.bit. timer1 még nincs bekapcsolva
GPIObits.GP5 = 1; // GP5 kimenet magas szintű
return;
}
Csak magamnak részleteztem ennyire tanulás céljából. Tudom hogy sokkal egyszerűbben is meg lehet oldani, de nekem ez így most átláthatóbb mintha binárisan adtam volna meg a T1CON-t.
Az egyik kérdésem az lenne, hogy a timer1 beállításai így jók-e? A másik hogy ha megszakítás érkezik akkor a PIR1 - TMR1IF bitet kell ellenőrizni? Vagyis nem non-stop pörgetek egy while-t, hanem ha megszakítás történik akkor a proci "szól" a programnak és lefut egy szubrutin ahol ellenőrzöm a TMR1IF bitet?
Nem próbáltam de nem tűnik űtrechnikának. A másodlagos oszcillátort (Secondary oscillator) kell bekapcsolni és megmondani a timer1-nek, hogy az órajel onnan jön. Egy trükk van, ha másodpercenkénti megszakítást szeretnél: a Timer 1 számlálóregisztereit fel kell tölteni minden megszakítás után, különben csak két másodpercenként kapsz megszakítást.
tmr1h = 0x80;
tmr1l = 0x00;
Az órakvarc 23 768 Hz-en működik, a Timer 1 regiszterei viszont 65 535-ig számolnak (2^16).
Nem értem az egész koncepciót, esetleg te nem érted a SW PWM lényegét. Legfőképpen az kérdés számomra, miért akarsz két szoftveres PWM-et használni, amikor van egy PWM modul is a kontrollerben. Utóbbi kb. 0 erőforrást eszik a kontroller idejéből.
Ha a Timer0 és timer1 órajelét külső forrásra állítod, akkor külön kell biztosítanod az órajelüket.
Sziasztok, el netes kalkulátor alapján összeraktam egy elég gyors timert mert 100-300ns-ot kellene mérnem és az a problémám hogy a főprogramom csak egyszer fut le. Valamit nem jól konfiguráltam esetleg? Egy leegyszerűsített részét beillesztem ide. #define ledPin 13
void setuptimer1() {
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 1;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS11);
TIMSK1 |= (1 << OCIE1A);
interrupts();
}
void setup() {
pinMode(ledPin, OUTPUT);
setuptimer1();
Serial.begin (9600);
}
void loop() {
Serial.println ("A");
}
ISR(timer1_COMPA_vect) {
digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}
Megkövetlek. Felületesen olvastam el. Túlzottan a timerből indultam ki. Szoftveresen kompenzálja.
Le is teszteltem:
volatile unsigned long ezred = 0;
void setup() {
Serial.begin(115200);
noInterrupts();
TCCR1A = 0x2;
TCCR1B = 0x1A;
TIMSK1 = 0x2;
ezred = millis();
interrupts();
}
ISR(timer1_COMPA_vect) {
ezred++;
}
void loop() {
Serial.println(millis());
Serial.println(ezred);
Serial.println("###");
delay(1000);
}
|
|