Jag pillade lite med det här ikväll, och det blev ju helt ok! Och simplistiskt, fyra rader kod i Isr-rutinen är allt, i main ligger det bara en tom while-loop. Totalt är det 32 rader kod, inklusive includes, { och }. Jag vet dock inte riktigt hur jag räknade när jag fick maxfrekvensen 62500 Hz, jag får upp den i 36697 Hz, om jag kalibrerar oscillatorn bara 31250 Hz.
Edit: Nu är det sent och jag är trött, men jag hade ju uppenbarligen tänkt lite fel, jag räknade ut hur många halvperioder det blir, inte helperioder. Så det verifierar ju bara att kalibreringsvärdet är hyffsat korrekt, d.v.s. mina uppmätta 31250 Hz som blir exakt 62500 halvperioder. 62500*16*4=4.000.000
Men det duger gott för det jag ska ha det till! På skopet får jag ut stabil och fin fyrkantsvåg. Det var helt klart bra att skippa att utnyttja de två lägsta bitarna från ADCn.
Nu ska det bara fixas ett kort och en låda.
Edit: Lika bra att lägga ut koden.
Kod: Markera allt
#define _LEGACY_HEADERS
#include "Pulseout.h"
void main(void)
{
Init();
while(1)
{
}
}
void Init(void)
{
/*Comment out if using simulator, ICD2, or ICE2000*/
#asm
call 0x3FF //Load Factory Calibration Value Into OSCCAL
bsf _STATUS,5 //BANK1
movwf _OSCCAL
#endasm
ANSEL = 0b00010001; // Select AN0
ADCON0 = 0b00000001; //Configure A/D - Select AN0, Left justified & enables A/D
TRISIO = PulseTris; // GPIO 3 output, GPIO 0,1,2,4,5,6,7 inputs
OPTION = TMRPRESCALE; // Timer0 internal clock, Prescaler assigned to WDT
GPIO = Off;
CMCON = 0x07; // //Turn Off Comparator Peripheral
VRCON = CLEAR;
TMR0 = CLEAR; //Clear Timer0
IOCB3 = CLEAR; //GP3 Interrupt On Pin Changed Disabled
T0IE = SET; //Timer0 Overflow Interrupt Enabled
T0IF = CLEAR; //Clear Timer0 Overflow Interrupt Flag
GIE = SET; //Enable All Interrupts
return;
}
void interrupt Isr(void)
{
PULSEOUT = PULSEOUT ^ 1; // Toggle the output.
TMR0 = ADRESH; //Set TMR0 register to the value from the ADC.
T0IF = CLEAR; //Clear Timer0 Interrupt Flag
GODONE = SET; //When ADC > 252, one ADC conversion will be done every other interrupt. This does not matter.
return;
}
Man kan tycka att det vore mer effektivt att läsa ur ADC'n bara ibland, men de extra instruktionerna gör att man förlorar lite tid, och alltså får en lägre högsta frekvens. Men det fungerar alldeles utmärkt som det är nu, frekvensen är tvärstabil helt utan synbara fluktuationer även när jag ställer skopet på väldigt kort tid per ruta.
Och include-filen:
Kod: Markera allt
#ifndef _Pulseout
#define _Pulseout
#include <htc.h>
__CONFIG(UNPROTECT & BORDIS & MCLRDIS & PWRTEN & WDTDIS & INTIO); //No code protection, Don't use BOD, No MCLR-reset, or WDT,
//use PWR-on tmr, disable WDT, and internal oscillator with GP4
// as I/O.
//Defines
#define PULSEOUT GPIO2
#define TMRPRESCALE 0b10001000 //TMR0 with /16 prescaler
#define SET 1
#define CLEAR 0
#define PulseTris 0b00111011
#define Off 0
//Global Variable Declarations
// No variables needed :)
//Function Prototypes
void Init(void);
#endif
Angående INTIO i konfigurationsbitarna så testade jag att dra ut klockfrekvensen på GP4 med INTCLK, men det överlagrar klockfrekvensen med ca 500 mV på utgångssignalen :/ Eftersom jag inte behöver en så hög frekvens ut som 1 MHz så kör jag med INTIO tills vidare.
Edit ytterligare igen:
Någon som har tips på en bra koppling för utgångsbuffer med kortslutningsskydd? Jag funderade på att göra en kombo, en utgång där signalen är +5 V mot COM, och en open collector. Antingen gör man utgångarna kortslutningsskyddade, eller så väljer man en väldigt billig utgångstrissa och gör den lätt bytbar
