Perfect!
Thank you. This is what I was looking for. "The get_pitch_roll_yaw" subroutine takes less than 1 ms to run so there should be no problem. I've been impressed with the 64MHz speed of the 18F87K22. The interrupt has no effect on any of the other code such as SEROUT2, HSEROUT running at 115200 baud or other i2c calls.
Announcement
Collapse
No announcement yet.
How would I call a Picbasic Pro subroutine using ASM
Collapse
X
-
i2cread p_i2c_sda, p_i2c_scl, addr_gyro_read, $1D, [gyro_x_reading.highbyte, gyro_x_reading.lowbyte, gyro_y_reading.highbyte, gyro_y_reading.lowbyte, gyro_z_reading.highbyte, gyro_z_reading.lowbyte]
Leave a comment:
-
a few thoughts\
get_intrpt_time:
' The TICK variable is incremented every 10 ms. Since the TICK variable is a
' byte this means that we have 2560 ms before the TICK variable overflows.
' This means that I have to run this subroutine within a 2.56 second window.
PIE1 = 0 ' Mask the interrupt while we're messing with TICK
intrpt_seconds = intrpt_seconds + (tick/100)
tick = tick // 100 ' Retain the left-over ticks
PIE1 = $01 ' Interrupt on again
Return ' Return to the main program
movlw 0B1h ; Prepare to set TMR1 high register
movwf TMR1H ; Set TMR1H to $B1
movlw 0ECh ; Prepare to set TMR1 low register
movwf TMR1L ; Set TMR1L to $EC
incf _TICK,F ; INCREMENT TICK COUNT
bcf PIR1, 0 ; Clear interrupt flag
main:
gosub get_intrpt_time
gosub get_pitch_roll_yaw
goto main
Code:main: if flag ==1 then gosub get_pitch_roll_yaw flag.0 = 0 endif if flag ==2 then gosub get_intrpt_time flag.1 = 0 endif goto main
would run code enery 10ms { if possible} if flag was set in isr
add new var
flag var byte bank0
add this to isr
bsf _flag,1
not sure what chip ,used so added bank switching just in case , it won't hurt to leave it in even if its not required
Code:Asm myint ; Save the state of critical registers movwf wsave ; Save W swapf STATUS, W ; Swap STATUS to W (swap avoids changing STATUS) clrf STATUS ; Clear STATUS movwf ssave ; Save swapped STATUS ; a 64MHz oscillator with an 8 prescaler and 4 clocks per instruction ; produces 2,000,000 counts per second. Timer1 can hold a maximum of 65536 ; counts. Thus Timer1 overflows 30.5 times in a second. This means that Timer1 ; will overflow in 32.8 milliseconds if it starts from 0. We want Timer1 to ; overflow every 10 milliseconds. To do this Timer1 needs to be set at 65536 - 19988 ; which comes to 45,548 whenever there is a reset. This translates to Timer1 ; highbyte being set to $B1 and Timer1 lowbyte being set to $EC movlw 0B1h ; Prepare to set TMR1 high register CHK?RP TMR1 movwf TMR1H ; Set TMR1H to $B1 movlw 0ECh ; Prepare to set TMR1 low register movwf TMR1L ; Set TMR1L to $EC bcf PIR1, 0 ; Clear interrupt flag RST?RP incf _TICK,F ; INCREMENT TICK COUNT bsf _flag,1 ; CODE NEEDS TO GO HERE TO RUN SUBROUTINE "get_pitch_roll_yaw" ; Retrieve critical registers swapf ssave, W ; Retrieve the swapped STATUS value (swap to avoid changing STATUS) movwf STATUS ; Restore it to STATUS swapf wsave, F ; Swap the stored W value swapf wsave, W ; Restore it to W (swap to avoid changing STATUS) retfie ; Return from interrupt EndAsm
without knowing how long all this takes to execute the task may be impossible anyway
Code:get_pitch_roll_yaw: ' read the gyroscope. There should always be data available in the gyro' registers ' but we enter a loop just in case gyro_ready = false Do while gyro_ready = false gosub read_gyro_register_ready loop ' get readings i2cread p_i2c_sda, p_i2c_scl, addr_gyro_read, $1D, [gyro_x_reading.highbyte, gyro_x_reading.lowbyte, gyro_y_reading.highbyte, gyro_y_reading.lowbyte, gyro_z_reading.highbyte, gyro_z_reading.lowbyte] 'set bits for indicating negative direction values. Gyro data is in twos compliment gosub calculate_directions ' subtract out offsets gosub subtract_offsets ' convert xyz values to angles and add to overall angles gosub update_x_angle gosub update_y_angle gosub update_z_angle return
Last edited by richard; 10-21-2016, 07:17 AM.
Leave a comment:
-
My code for reading gyro sensor
Below is a portion of the code for reading the gyro.
In the interrupt handler you can see where I want the subroutine called "get_pitch_roll_yaw" to run every 10 ms.
It currently runs in my main loop.
Any help in getting the ASM to run the "get_pitch_roll_yaw" subroutine would be greatly appreciated.
Code:' Test Program for InvenSense ITG-3200 Gyro ' define oscillator to be 64Mhz DEFINE OSC 64 OSCCON = %11110000 OSCTUNE.6 = 1 ' make sure all pins are digital CVRCON = 0 ADCON0 = 0 ANCON0 = 0 ANCON1 = 0 ANCON2 = 0 PADCFG1 = 0 MEMCON.7 = 1 Define INTHAND myint ' define interrupt handler ' define ports p_i2c_scl var PORTJ.6 '[pin 41] p_i2c_sda var PORTJ.7 '[pin 42] p_tx_to_pc var PORTH.5 '[pin 21] ' define constants false con 0 true con 1 Baud384NoIvn CON 6 ' 38.4K baud rate without inversion (used for communication between pics) addr_gyro_write con %11010010 ' write to gyro addr_gyro_read con %11010011 ' read from gyro gyro_sensitivity con 14375 ' actually 14.375 mV/degree/second ' define variables wsave VAR BYTE bankA system ' Saves WREG ssave VAR BYTE bankA system ' Saves STATUS TICK VAR BYTE bankA ' make sure that the variables are in bank 0 if they are to be used in the interrupt handler intrpt_seconds VAR long ' Elapsed seconds intrpt_seconds_hold VAR long ' Elapsed seconds for comparison gyro_x_reading var word gyro_y_reading var word gyro_z_reading var word x_gyro_neg var bit y_gyro_neg var bit z_gyro_neg var bit x_gyro_offset var byte y_gyro_offset var byte z_gyro_offset var byte x_gyro_offset_neg var bit y_gyro_offset_neg var bit z_gyro_offset_neg var bit x_gyro_sum var long y_gyro_sum var long z_gyro_sum var long x_gyro_sum_neg var bit y_gyro_sum_neg var bit z_gyro_sum_neg var bit x_angle var long ' all angles are in milliDegrees y_angle var long ' all angles are in milliDegrees z_angle var long ' all angles are in milliDegrees x_angle_neg var bit y_angle_neg var bit z_angle_neg var bit gyro_sample_rate var byte gyro_number_of_samples var byte gyro_low_pass_filter var byte gyro_ready var bit got_gyro_data var bit gyro_register_byte var byte tempByte var byte tempWord var word tempLong var long sample_time var long '(micro seconds) The time it takes between samples counter var byte timer0 VAR WORD i var byte intrpt_seconds = 0 ' Clear time intrpt_seconds_hold = 0 T1CON = %00110000 ' Turn off Timer1, prescaler = 8, time based on instruction cycle INTCON = %11000000 ' Enable global interrupts, peripheral interrupts PIE1 = $00 ' Disable TMR1 overflow interrupt until we enter main loop TICK = 0 GoTo jumpInterrupt ' jump over the interrupt handler and sub ' Assembly language interrupt handler Asm myint ; Save the state of critical registers movwf wsave ; Save W swapf STATUS, W ; Swap STATUS to W (swap avoids changing STATUS) clrf STATUS ; Clear STATUS movwf ssave ; Save swapped STATUS ; a 64MHz oscillator with an 8 prescaler and 4 clocks per instruction ; produces 2,000,000 counts per second. Timer1 can hold a maximum of 65536 ; counts. Thus Timer1 overflows 30.5 times in a second. This means that Timer1 ; will overflow in 32.8 milliseconds if it starts from 0. We want Timer1 to ; overflow every 10 milliseconds. To do this Timer1 needs to be set at 65536 - 19988 ; which comes to 45,548 whenever there is a reset. This translates to Timer1 ; highbyte being set to $B1 and Timer1 lowbyte being set to $EC movlw 0B1h ; Prepare to set TMR1 high register movwf TMR1H ; Set TMR1H to $B1 movlw 0ECh ; Prepare to set TMR1 low register movwf TMR1L ; Set TMR1L to $EC incf _TICK,F ; INCREMENT TICK COUNT bcf PIR1, 0 ; Clear interrupt flag ; CODE NEEDS TO GO HERE TO RUN SUBROUTINE "get_pitch_roll_yaw" ; Retrieve critical registers swapf ssave, W ; Retrieve the swapped STATUS value (swap to avoid changing STATUS) movwf STATUS ; Restore it to STATUS swapf wsave, F ; Swap the stored W value swapf wsave, W ; Restore it to W (swap to avoid changing STATUS) retfie ; Return from interrupt EndAsm ' PicBasic subroutine to update seconds variable get_intrpt_time: ' The TICK variable is incremented every 10 ms. Since the TICK variable is a ' byte this means that we have 2560 ms before the TICK variable overflows. ' This means that I have to run this subroutine within a 2.56 second window. PIE1 = 0 ' Mask the interrupt while we're messing with TICK intrpt_seconds = intrpt_seconds + (tick/100) tick = tick // 100 ' Retain the left-over ticks PIE1 = $01 ' Interrupt on again Return ' Return to the main program jumpInterrupt: x_angle = 0 y_angle = 0 z_angle = 0 x_angle_neg = 0 y_angle_neg = 0 z_angle_neg = 0 T1CON = %00110001 ' Start Timer1 PIE1 = $01 ' Start interrupts ' enter main loop of program main: gosub get_intrpt_time gosub get_pitch_roll_yaw goto main '******************************************************************************* ' This routine reads the gyroscope, subtracts out the x,y,z offsets and adds the ' x,y,z angle values to their perspective summation values. get_pitch_roll_yaw: ' read the gyroscope. There should always be data available in the gyro' registers ' but we enter a loop just in case gyro_ready = false Do while gyro_ready = false gosub read_gyro_register_ready loop ' get readings i2cread p_i2c_sda, p_i2c_scl, addr_gyro_read, $1D, [gyro_x_reading.highbyte, gyro_x_reading.lowbyte, gyro_y_reading.highbyte, gyro_y_reading.lowbyte, gyro_z_reading.highbyte, gyro_z_reading.lowbyte] 'set bits for indicating negative direction values. Gyro data is in twos compliment gosub calculate_directions ' subtract out offsets gosub subtract_offsets ' convert xyz values to angles and add to overall angles gosub update_x_angle gosub update_y_angle gosub update_z_angle return '*******************************************************************************
Leave a comment:
-
Originally posted by khufumen View PostI would like to read an i2c sensor and process its data every 10ms. I am familiar with the timer interrupts and can see how data can be saved to variables using ASM . However, I am not familiar with any code that uses ASM to run a PICbasic pro subroutine. I don't even know if it's possible. I'm using an 18F87K22 PIC. Any help would be greatly appreciated. Thanks.
Leave a comment:
-
How would I call a Picbasic Pro subroutine using ASM
I would like to read an i2c sensor and process its data every 10ms. I am familiar with the timer interrupts and can see how data can be saved to variables using ASM . However, I am not familiar with any code that uses ASM to run a PICbasic pro subroutine. I don't even know if it's possible. I'm using an 18F87K22 PIC. Any help would be greatly appreciated. Thanks.Tags: None
Leave a comment: