\ Program Name: f0-lmt01-temp-sensor-2.fs \ This program may require other support files listed in preload.sh which need to be loaded first \ Date: Thu 20 Dec 2018 15:00:36 AEDT \ Copyright 2018 t.porter , licensed under the GPL \ For Mecrisp-Stellaris by Matthias Koch. \ https://sourceforge.net/projects/mecrisp/ \ Chip: STM32F051, Board: STM32F0 Discovery Board \ Clock: 8 Mhz using the internal STM32F051 RC clock, unless otherwise stated \ All register names are CMSIS-SVD compliant \ Note: gpio a,b,c,d,e, and uart1 are enabled by Mecrisp-Stellaris Core. \ \ This Program : \ * reads temperature from multiple LMT01 temperature sensors via PC0. \ * Timer6 provides a 105mS non blocking window for the LMT01 pulse counting \ * Both Timer6 and PC0 use Interrupts \ * The program is controlled by a Cooperative Multitasker so terminal response is fast and consistent \ regardless of what is happening. \ \ This System is designed for a modified Mecrisp-Stellaris Kernel which should have a downloadable link \ \ \ Multitasking is in use see /library/f0-multitask.fs which is loaded last, sdd 'pause' in looping \ words for multitasking performance \ \ Clock is set to 48MHz. \ \ LMT01: Output Transfer Function: Temp (C) = ((count/4096) *256) -50 \ TEMPERATURE (°C) NUMBER OF PULSES \ ­-49.9375 1 \ -­49.875 2 \ ­-40 160 \ ­-20 480 \ 0 800 \ 30 1280 \ 50 1600 \ 100 2400 \ 150 3200 \ \ ---------------------------------------------------------------------------\ \ GPIO DESCRIPTION \ ---- ----------- \ PC0 COUNT INPUT \ PC1 LMT01-1 \ PC2 LMT01-2 \ PC3 LMT01-3 \ \ Uses about 4120 bytes of Flash not counting memmaps, and support apps like multitask. \ ---------------------------------------------------------------------------\ \ compiletoram compiletoflash 0 variable lmt01-x.count 0 variable raw.temperature 0 variable ready.flag \ RCC Words : rcc_apb2enr_syscfgen-set ( -- ) %1 0 lshift rcc_apb2enr bis! ; \ rcc_apb2enr_syscfgen syscfg clock enable : rcc_apb1enr_tim6en ( -- ) %1 4 lshift rcc_apb1enr bis! ; \ rcc_apb1enr_tim6en tim6 clock enable : init.gpio ( -- ) \ One Port pull up for all sensors rcc_apb2enr_syscfgen-set \ REQUIRED!! for using GPIO's as interrupts! pull-up ( %xx -- ) 0 lshift gpioc_pupdr bis! \ gpioc_pupdr_pupdr0 PC0 ; \ LMT01 related Words : syscfg_exticr1_exti0 ( -- ) %0010 0 lshift syscfg_exticr1 bis! ; \ pc-0 is interrupt source x010: pc[0] pin : exti_imr_mr0-set ( -- ) %1 0 lshift exti_imr bis! ; \ exti_imr_mr0 set interrupt mask on line 0 : exti_pr_pr0 ( -- ) %1 0 lshift exti_pr bis! ; \ exti_pr_pr0 pending bit 0 : exti_ftsr_tr0-set ( -- ) %1 0 lshift exti_ftsr bis! ; \ exti_ftsr_tr0 falling trigger event configuration of line 0 : exti_pr_pr0-set ( -- ) %1 0 lshift exti_pr bis! ; \ exti_pr_pr0 interrupt pending flag for line 0 : nvic_iser_setena-exti0_1 ( -- ) %100000 0 lshift nvic_iser bis! ; \ nvic_iser_setena-exti0_1 : nvic_icer_clrena-exti0_1 ( -- ) %100000 0 lshift nvic_icer bis! ; \ nvic_icer_clrena-exti0_1 : lmt01-1.power.on ( -- ) output ( %xx -- ) 2 lshift gpioc_moder bis! \ gpioc_moder_moder1 PC1 %1 1 lshift gpioc_bsrr bis! \ gpioc_bsrr_bs1; output high ; : lmt01-2.power.on ( -- ) output ( %XX -- ) 4 lshift GPIOC_MODER bis! \ GPIOC_MODER_MODER2 PC2 %1 2 lshift gpioc_bsrr bis! ; \ gpioc_bsrr_bs2; output high : lmt01-3.power.on ( -- ) output ( %XX -- ) 6 lshift gpioc_moder bic! \ gpioc_moder_moder3 PC3 %1 3 lshift gpioc_bsrr bis! ; \ gpioc_bsrr_bs3; output high : lmt01-1.power.off %11 ( -- ) 2 lshift gpioc_moder bic! ; \ gpioc_moder_moder1 PC1 : lmt01-2.power.off %11 ( -- ) 4 lshift gpioc_moder bic! ; \ gpioc_moder_moder2 PC2 : lmt01-3.power.off %11 ( -- ) 6 lshift gpioc_moder bic! ; \ gpioc_moder_moder3 PC3 : lmt01-x.power.off ( -- ) \ turn off all lmt01's by switching the port from output to input mode lmt01-1.power.off lmt01-2.power.off lmt01-3.power.off ; \ Tim6 related Words 48000000 constant fCK : nvic_iser_setena-tim6 ( -- ) 1 17 lshift nvic_iser bis! ; \ nvic_iser_setena tim6 : nvic_icer_clrena-tim6 ( -- ) 1 17 lshift nvic_icer bis! ; \ nvic_icer_clrena tim6 : nvic_icpr_clrpend-tim6 ( -- ) 1 17 lshift nvic_icpr bis! ; \ nvic_icpr_clrpend tim6 : tim6_cnt@ ( -- ) tim6_cnt h@ ; \ tim6_cnt_cnt 16 bit counter value : tim6_cr1_opm ( -- ) %1 3 lshift tim6_cr1 hbis! ; \ tim6_cr1_opm one-pulse mode : tim6_cr1_cen ( -- ) %1 0 lshift tim6_cr1 hbis! ; \ tim6_cr1_cen counter enable : tim6_cr1_cdis ( -- ) %1 0 lshift tim6_cr1 hbic! ; \ tim6_cr1_cen counter disable : tim6_dier_uie ( -- ) %1 0 lshift tim6_dier hbis! ; \ tim6_dier_uie update interrupt enable : tim6_sr_uif ( -- ) %1 0 lshift tim6_sr hbic! ; \ tim6_sr_uif clear tim6 int pending flag : tim6_egr_ug ( -- ) %1 0 lshift tim6_egr hbis! ; \ tim6_egr_ug update generation : preset.psc.no.int ( -- ) \ preset Prescaler but don't cause interrupt. PSC does not get 'active' until the second update event tim6_arr h! \ preset arr tim6_egr_ug \ update generation: (causes a interrupt when run) but loads ARR into shaddow register! tim6_sr_uif \ clear tim6 int pending flag after running tim6_egr_ug tim6_dier_uie \ update interrupt enable ; : tim6.int.handler ( -- ) nvic_icpr_clrpend-tim6 \ clear pending iser for tim6 tim6_sr_uif \ clear tim6 int pending flag tim6_cr1_cdis \ counter disable nvic_icer_clrena-tim6 \ disable the tim6 interrupt or dropping power to the LMT01 will re-trigger it green-off \ mark finish of count window lmt01-x.power.off lmt01-x.count @ raw.temperature ! \ raw.temperature now contains valid lmt01 count 1 ready.flag ! \ it's safe to read raw.temperature now nvic_iser_setena-tim6 \ re-enable tim6 iser nvic_iser_setena-exti0_1 \ re enable exti0_1 iser ( won't work without this ) ; : init.tim6 ( -- ) rcc_apb1enr_tim6en \ enable tim6 in rcc tim6_cr1_opm \ one pulse mode high = Counter stops counting at the next update event (clearing the bit CEN) 47952 tim6_psc h! \ preset prescaler for 1mS (47 for 1 uS) 104 preset.psc.no.int \ preset PSC --> clear int pending flag, enable interrupt ['] tim6.int.handler irq-tim6_dac ! nvic_iser_setena-tim6 \ enable iser ; : lmt01.interrupt.handler ( -- ) exti_pr_pr0 \ clear pending bit 0 lmt01-x.count @ 1+ lmt01-x.count ! \ increment temperature count by one exti_pr_pr0-set \ clear external interrupt pending register (exti_pr) ; : init.lmt01 ( -- ) syscfg_exticr1_exti0 \ negative going pulses from lmt01 trigger pc0 interrupt exti_imr_mr0-set \ exti0 set interrupt mask on line 0 exti_ftsr_tr0-set \ falling trigger on line 0 ['] lmt01.interrupt.handler irq-exti0_1 ! \ tie the interrupt handler to the interrupt nvic_iser_setena-exti0_1 \ enable exti0_1 interrupt ; : lmt01-fault? ( -- ) raw.temperature @ 0 = ; \ flag if sensor faulty : pretty.print ( -- ) 0 <# # 46 hold #s #> type ; \ insert one decimal point : degrees.c ( raw -- C ) pretty.print ." C " ; : degrees.f ( raw -- F ) \ 1259 = 28.6 C = 83.48 F | (28.6 * 1.8 +32 = 83.48) formula: °C x 9/5 + 32 = °F 90 5 / * 3200 + 10 / \ 1259 10000 4096 */ 256 * 500000 - 1000 / u. 286 ok. pretty.print ." F " \ 286 90 5 / * 3200 + u. 8348 ok. ; : degrees ( -- ) lmt01-fault? if ." LMT01 faulty or disconnected " else raw.temperature @ \ fetch total number of pulses counted 10000 4096 */ 256 * 500000 - 1000 / \ Temp (C) = ((count/4096) *256) -50 scale raw temp into degrees x 10 dup degrees.c ." or " degrees.f then ; : temperature ( sensor -- ) \ one temperature measurement 0 lmt01-x.count ! \ zero lmt01 pulse count 0 raw.temperature ! 0 ready.flag ! case \ power up selected sensor 1 OF lmt01-1.power.on ENDOF 2 OF lmt01-2.power.on ENDOF 3 OF lmt01-3.power.on ENDOF ." No such sensor !! " drop exit \ sensor not implimented fall thru warning endcase green-on \ mark start of count window tim6_cr1_cen \ start timer6 (end of timer kills the power to the lmt01) begin \ loop until raw.temperature is stable pause ready.flag @ 1 = until degrees cr ; : t temperature ; : testall cr ( -- ) \ simple test of sensors ." Sensor-1: " 1 t ." Sensor-2: " 2 t ." Sensor-3: " 3 t ." Sensor-4: " 4 t ; : main ( -- ) \ executed about every 5ms @48mh pause ; : init-general ( -- ) \ executed once at boot-up f0-disco-48mhz init.gpio init.tim6 init.lmt01 ; \ ----- added last by IDE ------- \ task: maintask \ essential multitasking Word : main& ( -- ) \ multitasking.fs Word maintask activate \ multitasking.fs Words begin main again \ this is the only task, and it loops forever (about every 5uS @ 48Mhz clock) unless blocked ; : init ( -- ) \ essential multitasking Word init-general \ main user application inits multitask \ multitasking.fs Word main& \ multitasking.fs Word ; init \ this init for non flash use, i.e. after uploading this program \ ----- added last by IDE ------- \ \ testall ( only LMT01 sensors 1 and 2 are fitted ) \ \ Sensor-1: 25.5C or 77.9F \ Sensor-2: 25.5C or 77.9F \ Sensor-3: LMT01 faulty or disconnected \ Sensor-4: No such sensor !! ok.