combining projects in MikroC

Post your requests and ideas on the future development of mikroC PRO for PIC.
Post Reply
Author
Message
mister_ezeh
Posts: 1
Joined: 19 Oct 2016 09:16

combining projects in MikroC

#1 Post by mister_ezeh » 30 Mar 2017 18:23

hello
im a beginner and i have issues combining two projects to be run by one microcontroller. the code compiled but does not function as expected in proteus.this is my code

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 LCD module connections
char message1[] = "PHCN SOURCE VOLT ";
float voltage;
float val;
int voltage1;
int cnt;
char text[15];
char volt[4];
int timer=8;

void interrupt() {
if (TMR0IF_bit) {
cnt++; // increment counter
TMR0IF_bit = 0; // clear TMR0IF
TMR0 = 39;
}
}
void int_delay(){
if (cnt ==120) {
PORTB.F2 = ~PORTB.F2; // Toggle PORTB LEDs
timer--;
cnt = 0; // Reset cnt
inttostr( timer, text);
Lcd_Out(1,1,"conctn to source");
Lcd_Out(2,6,text);
Lcd_Out(2,7,"sec");
if(timer==0){ timer=0; intcon.T0IE=0; Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1,message1);}}}
void voltagecon(){
do {
voltage = ADC_Read(2);
val=(voltage*5)/1023;
voltage1 = (voltage * 5 * 65)/ (1023);
inttostr(voltage1,volt); // it converts integer value into string
Lcd_Out(2,1,"Voltage = ");
Lcd_Out(2,11,Ltrim(volt));
Lcd_Out(2,16,"V");
if(voltage1>260){
RB2_BIT=1;
Lcd_Out(2,1,"DANGER ");
DELAY_MS(1000); }
}
while(1);}
//
void main() {
OPTION_REG = 0x84; // Assign prescaler to TMR0
TRISB = 0; // PORTB is output
PORTB.f2 = 1; // Initialize PORTB
TMR0 = 39; // Timer0 initial value
INTCON = 0xA0; // Enable TMRO interrupt
cnt = 0; // Initialize cnt
ADCON0 = 0b00001000; // Analog channel select @ AN2
ADCON1 = 0x00;
TRISA = 0b00001100; // PORTA All Outputs, Except RA3 and RA2
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off

while(1){
int_delay();
voltagecon ();

}}


please i need assistance :(

User avatar
darko.ilijevski
Posts: 581
Joined: 21 Mar 2017 16:57

Re: combining projects in MikroC

#2 Post by darko.ilijevski » 02 Apr 2017 14:28

Hello mister_ezeh,

First of all, I really really hope your code doesn't look like that on your compiler :wink:
Seriously, the first step to a working code, is it's readability. Now let's move on.

You haven't said what MCU you have used, so judging by the registers and stuff, I came to a conclusion that it was PIC16F877.
If I am wrong, then only a few registers need to be corrected, according to the datasheet of the MCU you have.

Now - the code:
1 - First thing I saw is that interrupt routine. I'd clear the TMR0IF flag as the first instruction, after the check, just in case. If no prescaler is used, you might end up with yet another interrupt, while you are still in the first one, increasing the cnt variable, having in mind that the MCU clock is pretty fast.

2 - Writing values to the TMR0 register is unnecessary, as it may lead to unpredicted events. Writing this register blocks the timer for 2 cycles, also sets and resets a bunch of other stuff (you can find the details about it in the datasheet), also dangerous while in the interrupt - so just leave it be, as it cycles from 0 to FF, increasing it's value with each clock pulse (or divided by the prescaler), if you set it to be a 'timer' and not 'counter' (with the T0CS bit of the OPTION_REG register)

Code: Select all

void interrupt()
{
  if (TMR0IF_bit)
  {
    TMR0IF_bit = 0;     // clear TMR0IF
    cnt++;              // increment counter
  }
}
Ok, let's move on.

You can do all the initialization inside the main(), but a good practice is to break the code into functions, so I did that - a habit I have - it's not mandatory for the code to work, but it adds to the readability. I named my init function InitMain(). Read the comments for the explanation:

Code: Select all

void initMain()
{
  OPTION_REG = 0b10000100;            // Assign prescaler 1:32 to TMR0 and disable pullups (or 0x84)
  TRISB = 0x00;                       // PORTB is output
  PORTB = 0x00;                       // Initialize PORTB
  TMR0 = 0x00;                        // Timer0 initial value (again - it's not needed, but let us start it clean - from 0)
  INTCON = 0xA0;                      // Enable TMRO interrupt & global interrupt
  cnt = 120;                          // Initialize cnt (I've set it so as soon as I call the function, the screen will display the timer txt, avoiding blank screen for the first 'timer-- ;' cycle)
  ADCON0 = 0b00000000;                // Analog channel select @ AN0 (I have connected my board this way, again it might differ from your MCU and connections)
  ADCON1 = 0x00;
  TRISA = 0b00000001;                 // PORTA All Outputs, Except RA0
  Lcd_Init();                         // Initialize LCD
  ADC_Init();                         // Initialize ADC module (not necessary if you use ADC_Read(ch))
  Lcd_Cmd(_LCD_CLEAR);                // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);           // Cursor off
}
Ok now we have a nice function for the initialization of everything we use. Next part:

Code: Select all

void int_delay()
{
  do
  {
     if (cnt >= 120)                            // I am checking for >= 120 because the value might get increased beyond this, if I wait for too long. Timer increases it, right ?
     {
       PORTB.F2 = ~PORTB.F2;                    // Toggle PORTB LEDs
       timer--;
       cnt = 0;                                 // Reset cnt
       inttostr( timer, text);
       Lcd_Out(1,1,"conctn to source");
       Lcd_Out(2,6,text);
       Lcd_Out(2,7,"sec");

       if(timer==0)
       {
         INTCON.T0IE=0;
         Lcd_Cmd(_LCD_CLEAR);
         Lcd_Out(1,1,message1);
       }
     }
   }
   while (timer);                                //do - while loop. I suppose you wanted to countdown till the timer = 0, right ? If so, you need to stay in the loop until it happens...
}
As you can see, it's slightly modified, also I have used a do-while loop to wait for the voltage connection to happen, this was what you originally wanted, right ? Moving on.

After this loop, I am in the endless loop which will sample the voltage and display a warning if dangerous voltage appears. Also I've made it so the LED turns off, once you're under the dangerous voltage level.

Code: Select all

void voltagecon()
{
  while (1)
  {
      voltage = ADC_Read(0);
      val=(voltage*5)/1023;
      voltage1 = (voltage * 5 * 65)/ (1023);
      IntToStr(voltage1, volt);                  // it converts integer value into string
      Ltrim(volt);                               // Ltrim changes the string's length, by stripping the blank places out.

      Lcd_Out(2,1,"Voltage = ");
      Lcd_Out(2,11, volt);                       // ...thus 'volt' is not formatted properly, but it's good enough for this example.
      Lcd_Out(2,16,"V");
      if(voltage1 > 260)
      {
        RB2_bit = 1;
        Lcd_Out(2,1,"DANGER ");
        Delay_ms(1000);
      } else {                                   //my personal touch of awesomeness ! JK :D Making sure the led goes off after the value has dropped under the threshold, 
        RB2_bit = 0;                             //maybe you even don't want that, but there it is...
      }
   }
}
As you can see, not much is changed here. I've used ' while (1) {...some looping code} ', instead of ' do {...some looping code} while (1) ' - the same thing, only a bit shorter...

Lastly - the main() function:

Code: Select all

void main()
{
   initMain();
   int_delay();              //this function will run till the 'timer' variable gets to 0. after that, we break out of the loop and move on to the next function
   voltagecon();             //this function samples the voltage, displays stuff and it's an endless loop. Once in, program never leaves it.
}
A short piece of code, just calling in the functions.
I will send you the finished project, so you can try it yourself. It's for the PIC16F877, if you have different one, just adjust the project accordingly.

Hope this helps, best regards.
Attachments
ADC&TimerIRQ.zip
(47.3 KiB) Downloaded 154 times
BR,
Darko

hexreader
Posts: 1784
Joined: 27 Jun 2010 12:07
Location: England

Re: combining projects in MikroC

#3 Post by hexreader » 02 Apr 2017 15:52

@darko.ilijevski

You have the patience of a saint :D
Start every day with a smile...... (get it over with) :)

Post Reply

Return to “mikroC PRO for PIC Wish List”