Version of the arduino MILLIS function (OshonSoft Basic).

Status
Not open for further replies.

DogFlu66

Member
It is a version of the arduino function "MILLIS", it is a general counter that increments every mSec. and that it takes several weeks to restart.

You can download the "_FuncionesPic16F88.bas" functions from this other thread:

Note: updated code improved (3/2023)
Code:
'***********************************************************************
'MILLIS function, long type geneal counter.
'For replacing absolute pauses generated with WaitMs.
'The _MILLIS function increments every mSec. so it takes
'approximately 49.7 days To reinitialize.
'That is, it will pass through a zero value.
'************************************************************************
'Pic16F88, OshonSoft Pic Basic Compiler v.8.42
'By COS, 03/2023
'************************************************************************
#define CONFIG = 0x2f50  'Fuse definition.
#define CONFIG2 = 0x3ffc
Define CLOCK_FREQUENCY = 8  'Clock a 8Mhz
'Define SIMULATION_WAITMS_VALUE = 1'Waitms is used activate for simulation.
Include "_FuncionesPic16F88.bas"
'************************************************************************
main:
    'Pin configuration
    AllDigital
    ConfigPin PORTA = Output
    ConfigPin PORTB = Output
    'Clock internal 8Mhz.
    Call _setup_oscillator_mode_select_bit(_oscillator_mode_defined_by_fosc)
    Call _setup_oscillator(_osc_8mhz)
    'Initialize Timer1 desborde 1mSec.
    Call _setup_timer1(_tmr1_internal, _tmr1_div1)
    Call _set_timer1(0xf831)  'Interruption every 1mSec.
    Call _timer1(_on)
    Call _enable_interrupts(_int_timer1)
    'Call _enable_interrupts(_global)
    'Assign names to the Leds
    Symbol LedGreen = RB0
    Symbol LedYellow = RA7
    '********************************************************************
    Call _SetUp_MILLIS()  'Setup _MILLIS functions, before activate interrupts
    Call _enable_interrupts(_global)
    Dim PreMillis As Long
    Dim PreMillis1 As Long

    'Loop
    While True

        Call _MILLIS()  'Repeat As few times As possible, so As Not To interfere with interruptions.

        If (_MILLIS - PreMillis) >= 200 Then  'Wait time in mSec.
            PreMillis = _MILLIS  'The last value of _MILLIS is stored.
            Toggle LedYellow  'Invers the state of the led.
        Endif


        If (_MILLIS - PreMillis1) >= 400 Then  'Wait time in mSec.
            PreMillis1 = _MILLIS  'The last value of _MILLIS is stored.
            Toggle LedGreen  'Invers the state of the led.
        Endif

    Wend
End                                             
'********************************************************************
'Function _MILLIS
'Requires the use of a timer and interrupts.
'**************************************************
'Call _SetUp_MILLIS()  'Before triggering interrupts
'Call _MILLIS()  'Update _MILLIS counter
'Call _CounterMillis()  'Incrementa contador Millis
'**************************************************
'Inicialize functions
Proc _SetUp_MILLIS()
    _MILLIS = 0
    _CounterMillis = 0
End Proc                                        
'Return _MILLIS as Long and global variable
Function _MILLIS() As Long
    Disable  'Stop interruption
    _MILLIS = _CounterMillis
    Enable  'Enable interruption
End Function                                    
'Increment the counter Millis
'Return _CounterMillis as Long and global variable
Function _CounterMillis() As Long
    _CounterMillis++  'Increment counter millis
End Function                                    
'********************************************************************
'Interrupt vector
On Interrupt  'Disable interruptions
Save System
    If _tmr1if Then
        Call _set_timer1(0xf831)  'Reload TMR1 registers to count 1mSec and clear _tmr1if.
        Call _CounterMillis()  'Increments _CounterMILLIS every mSec.
    Endif
Resume  'Enable interruptions
 
Last edited:
I wrote a similar thing using timer 2. You can see it in the file attached to this post. It sets up timer 2 with this code,
Code:
'setup 1mS interrupt = 8,000,000/16 = 500,000/10 = 50,000 set PR2=49 = 50,000/50 = 1000 = 1mS
T2CON = %01001110                        '& h4e
PR2 = 49                                        'This is timer 2 period register. I.E. reset after 50 clocks (0 to 49 = 50 counts)
PIE1.TMR2IE = 1                             'timer 2 interrupts enable
INTCON.PEIE = 1
INTCON.GIE = 1
And the ISR is simply,
Code:
On High Interrupt            'go via location 0x0008
Save System
    If PIR1.TMR2IF Then    'Is it a timer 2 interrupt
        mS = mS + 1            'Increment count
        PIR1.TMR2IF = 0
    Endif
Resume
Nice and simple, no resetting timers etc.

Note, above is using 32MHz oscillator.

Mike.
 
Last edited:
The use of functions generates a more transportable and clear code, but also consumes more resources.

I also have a RingBuffer to receive data via serial port, the same interests you.
 
It is a version of the arduino function "MICROS",
It's really a bit more like a version of "millis()" since it counts milliseconds.

As Mike says, reloading the counter every ms will cause it to slowly lose time.
 
If I am correct the formula is the following:

PR2 = (maximum timer value + 1) - (((Desired Time in uSec. / (4/8Mhz)) / (Prescaler * Poscaler)) -1)

and it has to always be:

(((Desired Time in uSec. / (4/8Mhz)) / (Prescaler * Poscaler)) -1) < (maximum timer value + 1)
 
The millis() function is a built-in function in the Arduino programming language that returns the number of milliseconds that have passed since the Arduino board started running its current program.

Findtricks

Here's an example of how to use the millis() function in Arduino:
unsigned long previousMillis = 0; // variable to store the previous time
unsigned long interval = 1000; // interval at which to do something (in milliseconds)

void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // initialize serial communication
}

void loop() {
// put your main code here, to run repeatedly:
unsigned long currentMillis = millis(); // get the current time

if (currentMillis - previousMillis >= interval) { // check if the desired interval has passed
previousMillis = currentMillis; // save the current time as the previous time
Serial.println("Hello, world!"); // do something
}
}

In this example, the program prints "Hello, world!" to the serial monitor every second using the millis() function to keep track of the elapsed time.
 
This language has a more rigid structure than C.
This currently cannot be implemented for the moment.

if (currentMillis - previousMillis) >= interval

In his other way:

aux = currentMillis - previousMillis
if (aux >= interval)

Correction: this type of expression if it is accepted.
if (currentMillis - previousMillis) >= interval

And there is also another big difference, equally the name of the function is used to call it, but at the same time the name of the function is a global variable.
 
Last edited:
C is the best.
-----------------------------
Is this correct?: The lenguage is must less flexible.

It's an opinion - however, as XC8 etc. is the language that MicroChip provide for the PIC micro-controllers, and it's considerably more powerful than BASIC, then it makes sense to use it.

Obviously the learning curve is a LOT harder than BASIC, but it's something worth doing.

There's also the issue that Oshonsoft is fairly obscure and has relatively few users, so there's MUCH less help out there than there is for C.

The commands that are 'missing' are simply a decision of the writer, and what he decided to implement, and what to leave out.

My simple PIC compiler I wrote years years ago included IF/THEN/ELSE/ENDIF

Code:
IF X>10 THEN
  IF Y<2 THEN
    Z=1
  ELSE
    Z=2
  ENDIF
ELSE
  Z=0
  X=0
  Y=0
END IF

As well as REPEAT/UNTIL and WHILE/WEND.

For a more fully featured BASIC interpreter, you might have a look at MMBASIC, which can run on higher end PIC's and numerous other processors.

The main issue with C is that it's very loosely structured - which was historically why Pascal was often the language of choice at Universities (as it's very tightly structured).
 
C is the best.
Not necessarily but I much prefer it over Oshonsoft.
The problem with not having elseif is simple,
Code:
if a=1 then
  'will get executed if a=1
else if b=1
  'will get executed if b=2 AND a is not 1
endif
People think you can simply add another if construct,
Code:
if a=1 then
  'will get executed if a=1
endif
if b=1
  'will get executed if b=2 AND a can be anything
endif
In fact, in the first version only one of the outcomes can be executed, in the second both can.

Mike.
 
I don't like to write long messages because I make a lot of mistakes with the language.

The "C" language today is the king for programming microcontrollers.
There are many "C" languages, and there are better ones and there are worse ones, the same happens with other languages.
There are also "Basic" languages that after compilation generate very small and fast code.

I like to use the oshonsoft Pic simulator because of the simulator, machine code assembler/diassembler and also because of its add-on language that allows for a function-oriented "basic" language.

When I have a problem with a function in "C" it is very useful for me to translate it to oshonsoft, it is really easy to do the translation, and then debug it with it. This is just a preference.

In any case, the best language that exists, in my opinion, is the one that does what the programmer has in mind.

And finally, for those who want to be professionals in this it is better to learn C.
 
Reactions: jjw
The problem with not having elseif is simple,
You just have to deal with the cards you're dealt...

Code:
if a=1 then
  'will get executed if a=1
else
	if b=1 then
	  'will get executed if b=1 and a<>1
	else
	  'will get executed if neither a=1 or  b=1 
	endif
endif

same as 'if/elseif/else'
 

Corrección: este tipo de expresión si se acepta.
if (millis actual - Millis anterior) >= intervalo
 
Last edited:
Correction: this type of expression if it is accepted.
if (currentMillis - previousMillis >= interval)
If this works depends on the order of functions.
It may be doing if current-false or if current-true.
Your earlier version, if (currentMillis - previousMillis) >= interval removes doubt by having the parentheses in the correct place.
Can that now be implemented?

Mike.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…