Maker Pro
Maker Pro

Need help with program code

Hello all,


I am currently working on a project to establish to check the frequency of two input signals and am finding it hard to get the code working in multisim. The initial code is just to have the two timers set up as counters and a delay of 100microsecs before(hopefully) an interrupt occurs and checks the difference of the frequencies.I would like to incorporate a buzzer and an lcd but would like to walk befor i can run-I personally find the programming difficult to get my head round.Any help on this matter would be greatly appreciated and I will put up my c files for the timer and lcd(Cant say i trust either).

Thanks for any input at all.

#include<htc.h>



#define TRUE 1
#define FALSE 0

#define LED P12;
void delay(void);//50us delay;

static void delay1(void){//set up for 1ms delay
char c;
for(c=0;c<20;c++){
delay();
}
}



#define On_Off= P10;//On-Off switch on P1^0(Starts device)

//function to see if switched is pressed

bit SwitchOn_Off(void);

//50ms debounce function
void debounce (void);

//function to count the pulses received on the timer input pins(T0 and T1)
void Pulsecount(void);
void delay(void);//50us delay;



void main (void){

while (TRUE){

if (SwitchOn_Off()==TRUE){
LED=0;

Pulsecount();//initiate count

}
else{}//do nothing

}
}

bit SwitchOn_Off(void){

if(On_Off==FALSE){//If switched is closed(0)
debounce();//carry out switch debounce(delay Procedure)
return TRUE;//Returns TRUE to allow operation to carry on
}
return FALSE;//function returns a FALSE
}

void debounce (void){

TL0=0xb0;
TH0=0x3c;
TMOD=0x01;
TR0=1;
TF0=0;
/*sets timer0 as interval timer and loads the decimal value
15536 in to it;;leading to it being incremeneted 50000 times
before it overflows;;ie TF=1(50ms)*/
while (TF0==FALSE){}
TR0=FALSE;
TF0=FALSE;
}

void Pulsecount(void){

while(TRUE)

T0=1;//set T0 as input pin(therefore increments Timer0 as pulse goes from low to high
T1=1;//set T1 as input pin(therefore increments Timer1 as pulse goes from low to high

TMOD=0x55;//sets Timers in 16bit interval timer mode

//clear any values in timers
TH1=0;
TL1=0;
TH0=0;
TL0=0;


TR1=TRUE;//start timer1
TR0=TRUE;//start timer0
delay1();
TR1=FALSE;
TR0=FALSE;



}

void delay (void){
char c;
for(c=0;c<16;c++);//50us delay
}





#include <reg51.h>




#define LCD_PORT P0 //LCD_PORT = total pins on port o

sbit Busy = LCD_PORT^7; //Busy flag
sbit E = P2^2; //enable pin
sbit RS = P2^0; //register select pin
sbit RW = P2^1; //read/write pin


/*This function negates the need for a delay loop as the use of the busy flag
gives a delay for almost the exact time necessart to process the commands */
void LCDbusy(){

Busy=1; //make input (Busy Flag)
E=1;
RS=0; //command register selected
RW=1; //read
while(Busy){ //keep reading busy flag until changes to zero

E=1;
E=0; //until busy flag changes introduce high to low enable

}
}


/*This funtion retrieves the value on singular port pins*/
static bit getBit(char c, char bitNumber) {
return (c >> bitNumber) & 1;
}

//-------------------------------
void Home(void) {
//returns both the display and cursor to original position

RS = 0;
RW=0;
LCD_PORT=0x02; //00000010
E = 1;
E = 0;
LCDbusy();
}

void ClearDisplay(void) {
//clears entire display and sets ddram to 0

RS = 0;
RW=0;
LCD_PORT=0x01;//00000001
E = 1;
E = 0;

LCDbusy();
// total of 1.65 ms - data sheet states clearing the display takes 1.52 ms
}

void EntryModeSet(void) {
//Sets cursor move direction and specifies shift in
//display
LCD_PORT=0x06;//000001110

//"I/D"set to increment (cursor moves to the right)(DB1)
//"S"=0 so tyhe display is not shifted at this point(DB0)
RS = 0;
RW=0;
E = 1;
E = 0;
LCDbusy();
}

void displayOnOffControl(void) {
//Turns on both display and cursor
LCD_PORT=0x0F;//00001111
//"D"=1 turning display on(DB3)
//"C"=1 turning cursor on(DB2)
//"B"=1 blinking turned on (DB1)

RS = 0;
RW=0;
E = 1;
E = 0;
LCDbusy();
}

void cursorOrDisplayShift(void) {
//moves cursor and shifts the display to the left
LCD_PORT =0x18;//00001000

//DB3=1; //SC=1 all display moves
//DB2=0;//"R/L" =1 shift to right,,0 to left
RS = 0;
RW=0;
E = 1;
E = 0;
LCDbusy();
}

void functionSet(void) {
//Sets to 8-bit operation/1 display lines/and 5*8
// characters
RS=0;
RW=0;
LCD_PORT=0x30;//00110000
//"DL"=1,,Data length = 8bits(DB5)
//"N"=0,1 display lines(DB4)
//"F"=0,,5*8dots(DB3)
E = 1;
E = 0;

LCDbusy();

}

void setDdRamAddress(char address) {
RS = 0;
LCD_PORT=address;
E = 1;
E = 0;
LCDbusy();
}

void sendChar(char c) {

LCD_PORT=c;

RS = 1;
E = 1;
E = 0;
LCDbusy();
}

// -- End of LCD Module instructions
// --------------------------------------------------------------------

void sendString(char* str) {
int index = 0;
while (str[index] != 0) {
sendChar(str[index]);
index++;
}
}
///This function initializes the display
void initialize(void){
functionSet();
displayOnOffControl();
ClearDisplay();
EntryModeSet();
}
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Please describe clearly what you are trying to achieve.

OK, comparing 2 frequencies, how? why the interrupt each 100uS?

Are you counting pulses and comparing them?

Don't ask me to read your code to find out.
 
Sorry for the lack of clarity steve. Not too sure how these forums work. I intend to have two identical sensors connected to the timer counter pins. Basically I want to check variance of these input frequencies(range 50Hz-100Hz) to use in a gradiometer(metal Detector) project. Maybe an interrupt not necessary but I would like to get a comparison after the counters are started every 100uS or so and if a difference occurs use a buzzer to alert me.I am using Multisim as it would be helpful to idicate this procedure occurring.
Thanks for replying.
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
There are always many ways of skinning a cat.

You could use an interrupt to catch (say) rising edges on each input and keep a differential count so you know which one is running faster than the other. There re various tricks you can do here so that the results are essentially averaged over time.

Another method is to have each connected to an internal counter and either sample the counts occasionally, or generate an interrupt when they overflow. The latter method will have far less overhead than the one above if the frequencies were very high (which they're not)

For low frequencies you may even look at the difference in time between the incoming pulses and determine a phase difference when the frequencies are very close. If your oscillator is very stable this may improve sensitivity.

At 100Hz, a cycle takes 10,000 uS, so starting counters every 100uS isn't going to achieve much. Maybe you meant MHz?
 
Thanks again steve.The frequencies i'm dealing with are 50kHz-100kHz(pulsing every 20uS-10uS).Apologies again as I know it is not nice to ask for assistance and not provide the correct info.It is the second suggestion(sampling the counts occasionally) that i have been trying to accomplish but need to show this occurring and not too sure of the best way to do it. Code seems to compile ok in keil but without the inputs I cant justify the theory. This is the reason I am trying to get the code simulated in Multisim but not too sure how to declare functions and variables using the htc.h header.
Once again thanks
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
I'm a fan of stepwise refinement, whether it be top-down, or bottom up. When dealing with hardware, bottom up tends to make a lot of sense.

I'm also not a user of multisim, so my recommendations will not be with that tool in mind.

I would recommend that you first get your 100uS interrupt working. Code it up and use it to simply toggle a pin. You can check this with an oscilloscope (real or simulated) to make sure that it's working.

Then get your display working (I assume you have a display or some form of output).

Then combine these by (say) outputting a count that increments every 10,000 cycles (once per second). So you should see a counter incrementing once per second on your display.

Next set up your interrupt routine to read a counter (and reset it if that's what you intend to do) each 100uS and display the value with the counter (so 1 in each 10,000 reads will get displayed). Now you can check that you're reading the counter. Make sure you get the results you expect.

Then modify the code to read 2 counters, displaying both. Again test that this works.

Then get it to calculate the difference (or whatever function you want) and display this. Check you get the expected results.

Now you have enough of the basics working that you can code up what you actually want to do (perhaps)
 
Not to put this forum down, but I found this forum helpful for programming
in PIC assembly or C:

http://www.microchip.com/forums/

I received a lot of professional programming help there.

Again, not putting down this site, there are a lot of very knowledgeable programmers here as well. I just think one should try more than one source.
 
Top