hello,
I tested the soluce with 2 timers
Timer0 interrupt every 40µS
Timer1 interrupt every 20mS
ADC reading is done inside Timer1 interrupt ,wich arme Output RA4 to 1 and Output RA2 to 0
Timer0 count until it reach the value of ADC divided by 2 .. so 0 to 512
and some limits are applide on duty value : mini=10 and maxi=490
During my test i observed that signal overtimes 20mS at maxi=400 instead to keep inside 20mS at 490 value ...
I tested it using Logic Anlayser of Pickit2 .. see results..
I search why this difference ...
20mS = 40µS * 500 ! 20% of difference with value 400 !
i find out the problem: it was because i reloaded TMR0 16 bits value at the end of interrupt instead of beginning..
so i added some extra times elapsed by instruction inside this interrupt... so time was > 40µS !
Just moved relaoding of timer0 in the beginning of interrupt
and Now i can cover a duty value from 10 to 490 and good result.. check with oscilloscope..
and output RA2 is complementary of output RA4..
Be carreful RA4 is open collector output.
the code in MikroC with 18F258 at 20Mhz
Code:
// 1 aout 2014
//MikroC Pro C for PIC version 6.40 enregistree!
// PIC18F258 28 pins
#include "built_in.h" // for Hi Lo ..etc
#define Versus "140801"
#define PROCESSOR 18F258
#define POWER_SUPPLY DC_5V
#define FOSC 10.0 // MHz
#define BAUD 19200 // UART1
#define CLS 12
#define CR 13
#define LF 10
#define TAB 9
#define BACK 8
#define Beep 7
#define Separator 0x20 // space
const code char mesg0[]="Mikroc pro 6.40 18F258+ IT UART1 + IT Timer0 & Timer1\n\r";
const code char mesg1[]="Version : "Versus"\n\r";
const code char * Messages[]={mesg0,mesg1};
unsigned char buffer[80];
unsigned char Tampon[32];
int Flag_Buffer;
unsigned int i1;
int Index1;
unsigned int CptErr;
volatile unsigned int Count0;
volatile volatile unsigned int Count1;
unsigned int Count2;
volatile int Flag_Timer1;
volatile int Flag_Timer2;
volatile unsigned int Duty;
int i,j,k,l;
unsigned char TEXTE[96];
unsigned char * txt;
sbit Led_Rouge at LATA4_bit;
sbit Led_Blanche at LATA2_bit;
void Init_Hardware(void) ;
void Read_Msg_Eeprom( int depuis);
void Write_Msg_Eeprom( int Adr,const char * d1) ;
void Init_Timer0(void);
void Init_Timer1 (void);
void CRLF(void) ;
void Raz_Buffer(void) ;
void UART1_Write_CText(const char *txt);
void strConstRamCpy(unsigned char *dest, const code char *source);
//---- EEPROM PIC bytes ================
void Save_Msg_To_EEPROM(unsigned char * adrx, unsigned char *ptr1);
void PrintOut_Eeprom_Msg(unsigned char PtrE); // for 16Fxxxxx
void Interrupt_High() iv 0x0008 ics ICS_AUTO
{
unsigned char c1;
if ( (TMR0IE_bit==1) && ( TMR0IF_bit==1))
{
TMR0L= 0xAA;
TMR0H=0xFF;
Count0++;
if( Count0 >= Duty)
{
TMR0ON_bit=0; // stop
Count0=0;
TMR0IE_bit=0; // interdit IT
// led tiree au +5V allumee
LATA.RA4=0;
LATA.RA2=1;
}
TMR0IF_bit=0;
}
if ( (RCIE_bit) && ( RCIF_bit))
{
c1 = UART1_Read(); // c1=RCREG; NE MARCHE PAS !!
// traitement separe des erreurs de COM
if (RCSTA.OERR==1) // voir parag 16.1.26 p273
{
RCSTA.CREN = 0 ;
RCSTA.CREN = 1 ;
c1 = UART1_Read();
c1 = UART1_Read();
CptErr++;
}
if(RCSTA.FERR==1 )
{
RCSTA.SPEN = 0 ;
RCSTA.SPEN= 1 ;
CptErr++;
}
if (c1==CR)
{
Flag_Buffer=1;
//PIE1.RCIE=0 ; //interdit IT Reception UART
buffer[i1]=0;
Index1=i1;
i1=0;
c1=0;
}
else
{
Flag_Buffer=0;
buffer[i1]=c1;
Index1=i1;
i1++;
}
}
// ------ timer 1 ----------------
if ( (TMR1IE_bit==1) && ( TMR1IF_bit==1))
{
// led eteinte car tiree au +5V car RA4 collecteur ouvert
Duty=ADC_Read(0) ;
LATA.RA4=1;
LATA.RA2=0; // sortie complementaire
// CHS2_bit=0; CHS1_bit=0; CHS0_bit=0;
// Duty=ADC_Get_Sample(0);
Duty=Duty >>1;
if(Duty<10) Duty=10;
if(Duty>490) Duty=490;
TMR1H= 0x9E; // Hi (40535); // 40535 * 4 *0.2 =20 000µS 20mS @20Mhz
TMR1L= 0x57; // Lo (40535);
PIR1.TMR1IF=0;
TMR0ON_bit=1;
TMR0IE_bit=1;
}
}
You can remove all UART part .. it is just for cheking the behavior of ADC..
You can see that MCU can do other job.. in particular : waiting 1 seconde
and signal is allways actif..