ICD bits -- ADC and 16F886 E/SP.

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
I ran into a road block.
How do you set the bits in ICSPDAT and ICSPCLK.
I have the ICD enabled in config.
What will happen if I set them as Inputs in TRISB

And about the comparator.....
Code:
  ANSEL = 0x1F;                      // AN0 to AN4 as Analog Inputs.
  CM1CON0 = 0x07;                    // Comparator 1 off
  CM2CON0 = 0x07;                    // Comparator 2 off
  TRISA = 0xFF;                      // Port A as Inputs
  TRISB = 0xDC;                      // TrisB 'b11011100'
  TRISC = 0x00;                      // Port C as Outputs
I plan to use the ADC.
Am I on the right track here.
uC is 16F886 E/SP
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
If you are using the ICSP pins for programming only, all you have to worry about is that the shared circuits are compatible (see the ICSP stuff at Microchip). Once the chip is programmed in then non-debug mode, the pins are just like any others.

If you are using the ICSP pins in the debug mode (CONFIG : DEBUG/ ==0), you can't use the pins for anything else while you are debugging- just set the TRIS to 1 and be done with it. Is not recommended that you have any other circuitry on the pins (you can but you have to be careful). Of course, this means that when you release the code (with the debugger turned off) you have a couple of floating inputs and that's not good. My solution is to have a compile-time switch for DEBUG/RELEASE that re-configures the two pins as output-0 when RELEASE is selected.

If you need the pins in your release version it gets a bit more involved. In those cases, I put some non important thing on the lines (status LED, mode jumpers etc) with ICSP compatible isolation. For example if you had a jumper that selected an operating mode, you could locate it on an ICSP pin. For DEBUG, pull the jumper and use another compile time switch to manually select the jumper value for your debug session. For RELEASE, turn on the weak pullup and read the pin for the jumper value.

Example:
C:
#define ManualJumperValue 1 // change and rebuild to simulate jumper in/out

bit JumperIn(void)
{
#ifdef DEBUG
      return(ManualJumperValue);
  #else
      return(PORTB & 0x80);
  #endif
}
That kind of thing. I collect all of the IO routines in their own file and all of the configuration stuff in a master config file that can be edited as required. I also have a second config file for RELEASE versions. When building for release, it replaces all of the debug stuff that I've been messing with with all of the values for a normal release version. That way, I can be stupid and forgetful without worrying about resetting all of the debug stuff back to a proper RELEASE version.

Note that MPLAB will provide a command line defined value (__DEBUG or something like that..) according to the project/toolbar settings. MikroC may do that as well but personally, I use my own definition in the config file. Just as easy and the syntax never changes.

Finally, you can confirm your builds by using the #warning directive to send a message to the build output window:
C:
#ifdef DEBUG
    #warning ("Project built for DEBUGGING.")
  #endif
My code has lots of this kind of stuff and is quite a chatterbox when building for non-release targets.


Hope that helps.
 
Last edited:

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
ooops ! Never realized I was in the wrong forum. :oops: My bad. Had a lotta work when I decided to ask ahead. Thanks Scott.

Egad ! I ask a simple thing and you made my head spin :eek:.
May be I am hungry. :p Long day.
I will go thru the post at home ( with in an hour ) and when my stomach is full, I might get this thru my head.

PS. The Debug pin is for debug only. Nothing is connected to it and never will be. I showed the schema in the other thread. About using the ICSP.
You can say the setting here


By the way how are my comparator values ?
 

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
So I started to write.
First just to see if the buzzer and LCD is working.
As usual it did not. It was Programing and verifying OK.
So Put the PIC back into EasyPIC. Did not help. It was going haywire.

So I rewrote like this to test the PIC

Code:
void initIO(){
  ANSEL = 0x00;
  CM1CON0.C1ON = 0;  // Disable comparator 1
  CM2CON0.C2ON = 0;  // Disable comparator 2
  PORTA = 0;  // Clear Ports
  PORTB = 0;  // Clear Ports
  PORTC = 0;  // Clear Ports
  TRISA = 0x00;
  TRISB = 0x00;
  TRISC = 0x00;
}
void main(){
  initIO();  // Initiate I/O's

  while(1){
  PortA = ~PortA;
  PortB = ~PortB;
  PortC = ~PortC;
  delay_ms(1000);
  PortA = ~PortA;
  PortB = ~PortB;
  PortC = ~PortC;
  delay_ms(1000);
  }
}
Funny part is PORTA and PORTC are flashing
PORTB 's RB7 and 6 are flashing while RB 5 to 0 are lit o_O

I tried 3 pc of PIC. Still the same.
I do not understand what I am doing wrong :confused:
One more thing. I had disable the debug to get it working
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
re: #4
I do not understand what I am doing wrong PORTB 's RB7 and 6 are flashing while RB 5 to 0 are lit
You need to set ANSELH to make PORTB digital.
One more thing. I had disable the debug to get it working
If debug is enabled you have to be connected to a debugger and build for debugging. When DEBUG/ is 0 in config, it expects a debugger to be present... I think in MikroC you have to change the config bits AND the programmer settings to switch from debug to stand-alone mode. I don't have the MicroICD so don't know.
Other than that it should be OK.

re: #3
For the 887, set CxON in CMxCON0 to 0 to disable the comparators. Other PICs use the 0x7 figure.
If you are dedicating the ICSP pins to ICSP, leave them as inputs for now. We'll have to look up to see if DEBUG/ in config overrides the port settings. I always just switch them like I described. The docs are a bit fuzzy on that point. To find out for sure, set it up for debug with the ICSP inputs high and confirm it works. Then change RB7/6 to output 0 in your code, rebuild and see if it still debugs. If so, then leave the code that way. Otherwise use a debug/release switch.

Good luck.
 
Last edited:

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
Thanks John. :D
I will take a whip at it tonight.
I figured I need the "ANSELH" for 887 not for 886. :oops:

I still got tons to learn about this. :(

Still....
887 has a lotta Analog ports but 886 has only 5. Why ANSELH ??
Crap...! I checked just now and it has lot more than 5 Analog. Silly me.:oops:
I will try ANSELH.
 

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
Works like a Charm John, Thank you.
ICSP works too. You were right about starting the debugger.
Managed to get the LCD startup info and buzzer working.
I believe I would need to use ur timer method to make delays. But for now I will try to finish the whole code with delays. If it works without using up the PIC space. OK
If not I might need a help in figuring out multiple delays using the timers.
 

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
I knew I would run into issues if I started to use LCD and delays.
I am not even at 10% and the LCD is giving jumbled characters. I have had issues before on another project and it is sitting there today.
@JohnInTX
So I thought why not try the approach John showed in the Led strip project.
So here I am asking for the best approach.
I thought of this.
Use interrupt to drive buzzer as before, and provide the delays.
Use the interrupt to Update LCD every 100ms.
The delay part this time is a bit complicated as I need delays for 2 seconds but I believe there is a way even though I dunno yet.

What do you think John ?
I am going to look at the Led strip and use the same approach to use IRQ.
I am a bit lost as these two PIC's are very different.
Still before starting I asking if the approach is OK.

A little details.
The LCD displays 2 msg one after the other. Each for 2 secs. That is only at startup.
A little of beeping goes on as before.
(I did the above normally and it is eating up of 25% ROM I think or is it RAM. The LCD is 16X2 in 4 bit mode.)

Then the program starts.
It first does a system check.
Check for supply levels and battery. Each using ADC.
A fault will hold the program and will alarm.
Results will be displayed in LCD.
 

JohnInTX

Joined Jun 26, 2012
4,787
What do you think John ?
The same as I always think... when I am found actually thinking, that is.
As we did in those other things, the PWM dimmer and the controller with multiplexed LED displays, start with a system TIK generated by an interrupt-driven timer. I recommend TIMER2/PR2 because it generates interrupts without intervention/resetting the timer etc.
Once that is done, break each task into its own function. If a task requires timing e.g. flash an LED then it gets its own timer derived from the system TIK. Each time its called it examines its timer to see if its time to change the LED state. If not, it exits immediately and waits for the next time it is called. If its time to change, it changes the LED, reloads the timer then exits immediately. Recall the way we did the various timed tasks in main of the PWM/LED dimmer.
All other functions, ADC, LCD display, button debounce/input etc. similarly get their OWN little function or set of functions or state machine implemented with a switch statement depending on how complicated their task is. But they all conform to the rule - ALL timing is done using timers derived from the system TIK, never a dumb delay().
One concession to the rules we can make for now is the LCD display. You probably want to use MikroC's libraries for that. Keep in mind, though, that those routines are 'blocking' i.e. they will dumb_delay as required. You probably can get away with those for now if all of the other stuff is non-blocking. It may be enough. If not, we can re-write the LCD stuff to conform. For now, don't worry about it.
 

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
I thought the MikroC LCD routine is using delays as I see the memory getting used up. Was not sure.
There only 3 buttons, (RESET, System Checking and Battery Change) So not used always. May be once in a blue moon.
5 ADC, reading Voltage and puts a respective high output to the relays when needed.
The LCD, Displaying Voltage or System operation or Fault.

OK then. I will see if I can start up the TIMER2 on this baby.
hmmm..TIMER0 is 8 bit, TIMER1 is 16bit and TIMER2 is 8 bit

PS. What you said makes sense now on the problem I had. Too much LCD messages with mikroC routine is messing up the characters.

That project was on hold since no one could provide a solution to me. You were not here then John.
After this I will try to use this method and see if that works
 
Last edited:

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
So I tried after looking tht led strip one.
Like you said I tried with TMR2 it was tricky as it was not located like 12F629 :oops:
But I managed to write it & program. Nothing happened. No pee pee....soooo to show u, I tried, I saved the project as it were and changed the settings to TMR0 and saved as a separate name again . TMR0 is beeping. I am doing the beep first to make sure.
When it beeped I knew it works and every time I press the reset it beeps.
So I searched the TMR2 file and friggin' thing is saved as TMR0.. :eek: both file the same. I have no freakin' idea how that happened.
So I am posting the beeping (TMRo) code
C:
********** PIC Configuration ************

--------------------------------------------------------------------------------
********** IO Configuration ************
RA0 as AN0 - Senses Vbatt      -- Battery Voltage Monitor ADC in.
RA1 as AN1 - Senses Charge_CS  -- Battery Charge Current Monitor ADC in.
RA2 as AN2 - Senses MainPSU_OK -- Main Power Supply 18V to 19.5V Monitor ADC in.
RA3 as AN3 - Senses SubPSU_OK  -- 13.5V PSU Monitor ADC in.
RA4 not used.
RA5 as AN4 - Senses Charger_OK -- Senses the Charger output Monitor ADC in.
RA6 as Digital In - System check Switch - Active high.
RA7 as Digital In - Battery Change Switch - Active high.
RB0 as Digital Out - Active High output - Float Charging Signal.
RB1 as Digital Out - Active High output - Charger Switch on Signal.
RB2 not used.
RB3 not used.
RB4 as Digital In - Senses AC_OK -- Active High Signal.
RB5 as Digital Out - Active High output - AC_ON Signal.
RB6 as PGC for Debugging.
RB7 as PGD for Debugging.
RC0 to LCD RS
RC1 to LCD Enable
RC2 to LCD D4
RC3 to LCD D5
RC4 to LCD D6
RC5 to LCD D7
RC6 as Digital Output -- Buzzer Output
RC7 as Digital Output -- LCD Backlit Enable.
------------------------------------------------------------------------------*/
// ****** LCD Configuration ************
sbit LCD_RS at RC0_bit;
sbit LCD_EN at RC1_bit;
sbit LCD_D4 at RC2_bit;
sbit LCD_D5 at RC3_bit;
sbit LCD_D6 at RC4_bit;
sbit LCD_D7 at RC5_bit;
sbit LCD_RS_Direction at TRISC0_bit;
sbit LCD_EN_Direction at TRISC1_bit;
sbit LCD_D4_Direction at TRISC2_bit;
sbit LCD_D5_Direction at TRISC3_bit;
sbit LCD_D6_Direction at TRISC4_bit;
sbit LCD_D7_Direction at TRISC5_bit;
// End of LCD Connections.

// Control bit Assignments.
sbit Sys_Check at RA6_bit;
sbit Batt_Change at RA7_bit;
sbit Float_Charge at RB0_bit;
sbit Charger_On at RB1_bit;
sbit AC_OK at RB4_bit;
sbit AC_On at RB5_bit;
//sbit Buzzer at RC6_bit;
sbit Backlit at RC7_bit;
// Flags for above
bit Sys_Ch, Batt_Ch, Float_Ch, AC__OK, AC__ON, Batt_Status, Check_Battery;
bit SoundBEEPER;
// End of Control bit Assignments.

// Variables
char *Vout = "00.00";
unsigned int Vbatt, VbattTemp;
unsigned char msec5PreScaler, BeepTimer_5ms, PORTCing;
/******* PROGRAM CONFIGURATION **********/
#define Beepermask   0x40    // Buzzer @ RC6
#define Backlitmask  0x80    // Baacklit @ RC7
#define TMR0period_us 150
#define TMR0reload 256-TMR0period_us
#define msec5PSset 5000/TMR0period_us

// Beeper pattern. Bit mapped variable gets shifted right each BeepTIK.
// If LSbit==1 beeper sounds for one BeepTIK.If 0, beeper is off for that TIK.
// By scattering bits in BeepPattern, patterns and different beep times can be
// generated.
typedef unsigned int BeepPatternType;
BeepPatternType BeepPattern;
#define BeepCtrlmask ((BeepPatternType) 1)// tests LSbit in char or int or long
#define BeepTIK_ms 25 // ms per tik - Beep duration
#define BeepTimerSet (BeepTIK_ms / 5) //
// Beeper patterns for int..commented the ones I do not use
//#define Beep_OFF 0b0000000000000000 // no beep (copy/paste for new pattern)
#define Beep_Short1 0b0000000000000001 // 1 short beep--->Switch press Normal
#define Beep_Short2 0b000000000000101 // 2 short beeps-->Innitial On beep
#define Beep_Long1 0b0000000011111111 // 1 long beep---->ON OFF beep
//define Beep_Long2 0b0000111100001111 // 2 long beeps
//#define Beep_Alarm 0b0101010101010101 // 8 short beeps



/********  ISR *************************/
void interrupt(){
    TMR0 += TMR0reload;
    INTCON.T0IF = 0;                   // Clear TMR interrupt flag

//-------------Service Buzzer -----------/
    if(SoundBEEPER)
       PORTCing ^= Beepermask;
      else
       PORTCing &= ~Beepermask;
       PORTC = PORTCing;
//-------------Service Derived Timer ----/
/*Prescaler counts msec5PSset interrupts to make a 5msec period.
   From that, as many timers can be created as desired. Set the timer
   to the number of IRQ periods to time. The timer will run to 0 and stop.
    Poll the timer, when its 0, time is out. Do something, reload and go.*/
    if(msec5PreScaler == 0){ // iff prescaler ran out..
       msec5PreScaler = msec5PSset; // reset it and run timer(s)
          if(BeepTimer_5ms) // If Beem timer is > 0
             BeepTimer_5ms--; // decrement beep timer
   }
    else // else
       msec5PreScaler--; // decrement 5 msec prescaler
// IRQ service
}
/******** Tone *************************/
void setBeepPattern(BeepPatternType p){
      BeepPattern = p;
      BeepTimer_5ms = 0;
}

/******** Whole System Checking Routine ************/

void main(){
    INTCON = 0;                        // Ckear IRQ's
    PIE1 = 0;
    PIE2 = 0;
    OPTION_REG = 0x88;                 // No pullups

    ANSEL = 0x0F;                      // RA <0:4> as Analog Inputs
    ANSELH = 0x00;                     // Rest of Analog as Digitla I/O
    CM1CON0 = 0x07;                    // Disable comparator 1
    CM2CON0 = 0x07;                    // Disable comparator 2

    PORTA = 0;                         // Clear Ports
    PORTB = 0;                         // Clear Ports
    PORTCing = 0;                      // Clear PORT C shadow
    PORTC = 0;                         // Clear Ports
    TRISA = 0xFF;                      // PortA as Inputs
    TRISB = 0xDC;                      // PortB 'b11011100'
    TRISC = 0x00;                      // PortC as Outputs

    Sys_Ch = 0;                        // Clear Flag bit
    Batt_Ch = 0;                       // Clear Flag bit
    Float_Ch = 0;                      // Clear Flag bit
    AC__OK = 0;                        // Clear Flag bit
    AC__ON = 0;                        // Clear Flag bit
    Batt_Status = 0;                   // Clear Battery Status flag
    Check_Battery = 0;
    soundBEEPER = 0;
    msec5PreScaler = 0;
    BeepTimer_5ms = 0;
// -------- Start TMR2 IRG  ------------------

    TMR0 = 0;                          // Clear TMR0
    INTCON.T0IF = 0;                   // Clear TMR0 interrupt flag
    INTCON.T0IE = 1;                   // Enable TMR0 Interrupt
    INTCON.GIE = 1;                    // Enable Global Interrupt
    Backlit = 1;
    setBeepPattern(Beep_Short2);


   while(1){                             // While
//------------------- GENERATE BEEP PATTERN --------------------
// Shifts BeepPattern each time period turning beeper on/off in pattern
          if(BeepTimer_5ms == 0){ // time to do something?
          if(BeepPattern != 0){ // more to do?
          if(BeepPattern & BeepCtrlmask) // yes, beep on/off according
          // to bit in pattern
          soundBEEPER = 1; // Beep
          else
          soundBEEPER = 0; // Else don't beep
          BeepTimer_5ms = BeepTimerSet; // then reload timer
          BeepPattern = BeepPattern >> 1; // shift it right for
          } // next pattern bit
          else
          soundBEEPER = 0; // no bits in pattern, turn it off
}
}
}
See the " Backlit output" is at RC7, buzzer at RC6
With the TMR2 version no sound but LCD backlit turn on.
With TMR0 version sound is OK but backlit flickers and goes off.

I like to know how to setup the TMR2. I think it is located in the PIR register. Or am I wrong.:(
I like to know cause you told me to use the TMR2 :D
 
Last edited:

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
My PIC is set at 8Mhz.
TMR0period is at 150us
I am trying to figure out the buzzer Freq. This part still escapes my head
 

JohnInTX

Joined Jun 26, 2012
4,787
If TMR0period is 150us, then the buzzer period is 2*that = 300us and the freq is therefore 3333Hz because the raw drive to the beeper is just toggling the buzzer output at the interrupt rate. IIRC, you picked that for max beep sound, yes? If so that's our basic interrupt rate.
To make it go with Timer2, you'll have to of course disable the TMR0 interrupt stuff and enable TMR2's stuff, easy enough. TMR2 is a free running 8 bit timer that generates a period by comparing its count to PR2.
At 8MHz, you have a 500ns Tcyc (period into the timer chain)... Dragging out the Lil Professor I get:
PreScaler = 1
PostScaler = 10
PR2 = 30 (decimal)
for 150usec period that will generate your buzzer freq. All other timers will be derived from this as we did before.
To start, I would get that working (comment out the rest of the stuff for now), force the buzzer ON and drag out that fancy Rigol scope of yours to confirm that you have a 300us period into the buzzer (2* the interrupt rate). Once you get that, we'll deal with the other stuff..
Meanwhile, I'll review that 'Easy'7 of yours.
Best,
RJO
 

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
The same as I always think... when I am found actually thinking, that is..
Hmmm ! I wonder how you would be sitting and thinking :D

Just so that I got everything...!
8Mhz = > 8/4 = 2Mhz (Tcyc) => 1/2MHz = 500ns period . Got it.

So If I chose to change the buzzer freq, that will effect the IRQ timing, right ?

Oki doki..let's see if I can do what you asked.
Disable all TMR0 stuff and enable all TMR2 stuff. Force the buzzer on and RIGOL the bugger !! :oops: Err, Buzzer.:p
 

JohnInTX

Joined Jun 26, 2012
4,787
So If I chose to change the buzzer freq, that will effect the IRQ timing, right ?
Yes, if the buzzer is to be driven as we did in your PWM dimmer project. BUT! Thinking now, unlike that PIC, the '886 has a hardware PWM. Personally, I'd use that - set it at 50% duty cycle at the freq desired then just turn the PWM on/off. The PWM uses TMR2 so the system TIK goes to one of the other timers and gets set at a more reasonable 1ms - 10ms.
That way, you get more control over the buzzer (play tunes if you like!) without changing the basic IRQ system TIK.
I'd do that.
 

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
I like that but this is not a "Tunes one"
I will try that in some other project. This I like to go on with just beeping..Louder than usual.
 

JohnInTX

Joined Jun 26, 2012
4,787
I like that but this is not a "Tunes one"
I will try that in some other project. This I like to go on with just beeping..Louder than usual.
Fair enough, I was kind of joking anyway. But the point is still valid, if you can use the hardware PWM that relieves some constraints on the rest of the program by not having to interrupt as often. But on your Easy7, the buzzer can be driven by the RC2 (PWM output) pin. If you want, start with the way we did it before (150us interrupts) and if it becomes a problem, fire up the hardware PWM. I would use the original timer setup if you go with the fast interrupt method.. That way, you can migrate to the PWM/TMR2 with minimal rewrite of the system TIK stuff.
 

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
Point taken. :)
But the PCB is already made and the PIC is in the circuit. I am using the EasyPIC ICSP with the PCB ICSP header. Just bread board jumper cables. I am programing the PIC in the circuit.
So the buzzer is set up at RC6 and if I changed that I need to change the PCB. Too much time you know :(

I checked. The buzzer is pretty loud at 150us.
Now I am trying to change it TMR2.
Will take some time. :D
 

Thread Starter

R!f@@

Joined Apr 2, 2009
9,918
C:
/******* PROGRAM CONFIGURATION **********/
#define Beepermask   0x40    // Buzzer @ RC6
#define Backlitmask  0x80    // Baacklit @ RC7
#define TMR0period_us 150
#define TMR0reload 256-TMR0period_us
#define msec5PSset 5000/TMR0period_us

// Beeper pattern. Bit mapped variable gets shifted right each BeepTIK.
// If LSbit==1 beeper sounds for one BeepTIK.If 0, beeper is off for that TIK.
// By scattering bits in BeepPattern, patterns and different beep times can be
// generated.
typedef unsigned int BeepPatternType;
BeepPatternType BeepPattern;
#define BeepCtrlmask ((BeepPatternType) 1)// tests LSbit in char or int or long
#define BeepTIK_ms 25 // ms per tik - Beep duration
#define BeepTimerSet (BeepTIK_ms / 5) //
// Beeper patterns for int..commented the ones I do not use
//#define Beep_OFF 0b0000000000000000 // no beep (copy/paste for new pattern)
#define Beep_Short1 0b0000000000000001 // 1 short beep--->Switch press Normal
#define Beep_Short2 0b000000000000101 // 2 short beeps-->Innitial On beep
#define Beep_Long1 0b0000000011111111 // 1 long beep---->ON OFF beep
//define Beep_Long2 0b0000111100001111 // 2 long beeps
//#define Beep_Alarm 0b0101010101010101 // 8 short beeps



/********  ISR *************************/
void interrupt(){
    TMR0 += TMR0reload;
    INTCON.T0IF = 0;                   // Clear TMR interrupt flag
  
//-------------Service Buzzer -----------/
    if(SoundBEEPER)
       PORTCing ^= Beepermask;
      else
       PORTCing &= ~Beepermask;
       PORTC = PORTCing;
//-------------Service Derived Timer ----/
/*Prescaler counts msec5PSset interrupts to make a 5msec period.
   From that, as many timers can be created as desired. Set the timer
   to the number of IRQ periods to time. The timer will run to 0 and stop.
    Poll the timer, when its 0, time is out. Do something, reload and go.*/
    if(msec5PreScaler == 0){ // iff prescaler ran out..
       msec5PreScaler = msec5PSset; // reset it and run timer(s)
          if(BeepTimer_5ms) // If Beem timer is > 0
             BeepTimer_5ms--; // decrement beep timer
   }
    else // else
       msec5PreScaler--; // decrement 5 msec prescaler
// IRQ service
}
/******** Tone *************************/
void setBeepPattern(BeepPatternType p){
      BeepPattern = p;
      BeepTimer_5ms = 0;
}

/******** Whole System Checking Routine ************/

void main(){
    INTCON = 0;                        // Ckear IRQ's
    PIE1 = 0;
    PIE2 = 0;
    OPTION_REG = 0x88;                 // No pullups TMRO runs as Tcyc

    ANSEL = 0x0F;                      // RA <0:4> as Analog Inputs
    ANSELH = 0x00;                     // Rest of Analog as Digitla I/O
    CM1CON0 = 0x07;                    // Disable comparator 1
    CM2CON0 = 0x07;                    // Disable comparator 2
  
    PORTA = 0;                         // Clear Ports
    PORTB = 0;                         // Clear Ports
    PORTCing = 0;                      // Clear PORT C shadow
    PORTC = 0;                         // Clear Ports
    TRISA = 0xFF;                      // PortA as Inputs
    TRISB = 0xDC;                      // PortB 'b11011100'
    TRISC = 0x00;                      // PortC as Outputs
  
    Sys_Ch = 0;                        // Clear Flag bit
    Batt_Ch = 0;                       // Clear Flag bit
    Float_Ch = 0;                      // Clear Flag bit
    AC__OK = 0;                        // Clear Flag bit
    AC__ON = 0;                        // Clear Flag bit
    Batt_Status = 0;                   // Clear Battery Status flag
    Check_Battery = 0;
    soundBEEPER = 0;
    msec5PreScaler = 0;
    BeepTimer_5ms = 0;
// -------- Start TMR0 IRG  ------------------
    TMR0 = 0;                          // Clear TMR0
    INTCON.T0IF = 0;                   // Clear TMR0 interrupt flag
    INTCON.T0IE = 1;                   // Enable TMR0 Interrupt
    INTCON.GIE = 1;                    // Enable Global Interrupt
    Backlit = 1;
    setBeepPattern(Beep_Long1);


   while(1){                             // While
//------------------- GENERATE BEEP PATTERN --------------------
// Shifts BeepPattern each time period turning beeper on/off in pattern
          if(BeepTimer_5ms == 0){ // time to do something?
          if(BeepPattern != 0){ // more to do?
          if(BeepPattern & BeepCtrlmask) // yes, beep on/off according
          // to bit in pattern
          soundBEEPER = 1; // Beep
          else
          soundBEEPER = 0; // Else don't beep
          BeepTimer_5ms = BeepTimerSet; // then reload timer
          BeepPattern = BeepPattern >> 1; // shift it right for
          } // next pattern bit
          else
          soundBEEPER = 1; // no bits in pattern, turn it off
}
}
}
TMR0.png

The above Image is for the TMR0 code as above.
Below code and image is for TMR2

C:
/******* PROGRAM CONFIGURATION **********/
#define Beepermask   0x40    // Buzzer @ RC6
#define Backlitmask  0x80    // Baacklit @ RC7
#define TMR2period_us 150
#define TMR2reload 256-TMR2period_us
#define msec5PSset 5000/TMR2period_us

// Beeper pattern. Bit mapped variable gets shifted right each BeepTIK.
// If LSbit==1 beeper sounds for one BeepTIK.If 0, beeper is off for that TIK.
// By scattering bits in BeepPattern, patterns and different beep times can be
// generated.
typedef unsigned int BeepPatternType;
BeepPatternType BeepPattern;
#define BeepCtrlmask ((BeepPatternType) 1)// tests LSbit in char or int or long
#define BeepTIK_ms 25 // ms per tik - Beep duration
#define BeepTimerSet (BeepTIK_ms / 5) //
// Beeper patterns for int..commented the ones I do not use
//#define Beep_OFF 0b0000000000000000 // no beep (copy/paste for new pattern)
#define Beep_Short1 0b0000000000000001 // 1 short beep--->Switch press Normal
#define Beep_Short2 0b000000000000101 // 2 short beeps-->Innitial On beep
#define Beep_Long1 0b0000000011111111 // 1 long beep---->ON OFF beep
//define Beep_Long2 0b0000111100001111 // 2 long beeps
//#define Beep_Alarm 0b0101010101010101 // 8 short beeps



/********  ISR *************************/
void interrupt(){
    TMR2 += TMR2reload;
    PIR1.TMR2IF = 0;                   // Clear TMR interrupt flag
  
//-------------Service Buzzer -----------/
    if(SoundBEEPER)
       PORTCimg ^= Beepermask;
      else
       PORTCimg &= ~Beepermask;
       PORTC = PORTCimg;
//-------------Service Derived Timer ----/
/*Prescaler counts msec5PSset interrupts to make a 5msec period.
   From that, as many timers can be created as desired. Set the timer
   to the number of IRQ periods to time. The timer will run to 0 and stop.
    Poll the timer, when its 0, time is out. Do something, reload and go.*/
    if(msec5PreScaler == 0){ // iff prescaler ran out..
       msec5PreScaler = msec5PSset; // reset it and run timer(s)
          if(BeepTimer_5ms) // If Beem timer is > 0
             BeepTimer_5ms--; // decrement beep timer
   }
    else // else
       msec5PreScaler--; // decrement 5 msec prescaler
// IRQ service
}
/******** Tone *************************/
void setBeepPattern(BeepPatternType p){
      BeepPattern = p;
      BeepTimer_5ms = 0;
}

/******** Whole System Checking Routine ************/

void main(){
    INTCON = 0;                        // Ckear IRQ's
    PIE1 = 0;
    PIE2 = 0;
    OPTION_REG = 0x80;                 // No pullups TMRO runs as Tcyc

    ANSEL = 0x0F;                      // RA <0:4> as Analog Inputs
    ANSELH = 0x00;                     // Rest of Analog as Digitla I/O
    CM1CON0 = 0x07;                    // Disable comparator 1
    CM2CON0 = 0x07;                    // Disable comparator 2
  
    PORTA = 0;                         // Clear Ports
    PORTB = 0;                         // Clear Ports
    PORTCimg = 0;                      // Clear PORT C shadow
    PORTC = 0;                         // Clear Ports
    TRISA = 0xFF;                      // PortA as Inputs
    TRISB = 0xDC;                      // PortB 'b11011100'
    TRISC = 0x00;                      // PortC as Outputs
  
    Sys_Ch = 0;                        // Clear Flag bit
    Batt_Ch = 0;                       // Clear Flag bit
    Float_Ch = 0;                      // Clear Flag bit
    AC__OK = 0;                        // Clear Flag bit
    AC__ON = 0;                        // Clear Flag bit
    Batt_Status = 0;                   // Clear Battery Status flag
    Check_Battery = 0;
    soundBEEPER = 0;
    msec5PreScaler = 0;
    BeepTimer_5ms = 0;
// -------- Disale TMR0 stuff  ------------------
    INTCON.T0IF = 0;                   // Clear TMR0 interrupt flag
    INTCON.T0IE = 0;                   // Disable TMR0 interrupt
// -------- Enable TMR2 stuff  ------------------
    TMR2 = 0;                          //Clear TMR2
    PR2 = 0x1E;                        // PR2 is decimal 30
    T2CON = 0x4C;                      // PostScaler = 1:10
                                       // TMR2 ON
                                       // Prescaler 1
    PIR1.TMR2IF = 0;                   // Clear TMr2 to PR2 interrupt Flag
    PIE1.TMR2IE = 1;                   // TMR2 to PR2 Match interrupt Enable
    INTCON.PEIE = 1;                   // Enable all Pheripheral interrupt
    INTCON.GIE = 1;                    // Enable Global interrupt
  
  
    Backlit = 1;
    setBeepPattern(Beep_Long1);


   while(1){                             // While
//------------------- GENERATE BEEP PATTERN --------------------
// Shifts BeepPattern each time period turning beeper on/off in pattern
          if(BeepTimer_5ms == 0){ // time to do something?
          if(BeepPattern != 0){ // more to do?
          if(BeepPattern & BeepCtrlmask) // yes, beep on/off according
          // to bit in pattern
          soundBEEPER = 1; // Beep
          else
          soundBEEPER = 0; // Else don't beep
          BeepTimer_5ms = BeepTimerSet; // then reload timer
          BeepPattern = BeepPattern >> 1; // shift it right for
          } // next pattern bit
          else
          soundBEEPER = 1; // no bits in pattern, turn it off
}
}
}
TMR2.png

Sound is Low in volume and tone.

So I need to change something. I would try the 150us but I think that is not what you would do John.

can you please go thru the TMR2 code and tell me if I should omit anything ?
 
Last edited:
Top