\ Program Name: f0-adc-read-all-ch.fs \ Date: Thu Sep 7 07:36:28 AEST 2017 \ Copyright 2017 t.porter , licensed under the GPL \ For Mecrisp-Stellaris by Matthias Koch \ Chip: STM32F051 \ Board: STM32F0 Discovery Board \ Clock: 8 Mhz using the internal STM32F051 RC clock, unless otherwise stated \ All register names must be CMSIS-SVD compliant \ Note: gpio a,b,c,d,e, and uart1 are enabled by Mecrisp-Stellaris core as default. \ \ This Program is a ADC all channel scanner, no DMA, no interrupts, using only a spin delay to wait for the end \ of conversion sequence(s). It works by scanning each channel and pushing the results on the Stack. \ After a conversion sequence of 19 channels is finished, it pops the results off the stack, scales and displays them. \ \ Inputs: pa0-pa7, pb0-pb1, pc0-pc5 \ Outputs: terminal only \ \ Registers Used: rcc, gpioa, gpiob, gpioc, adc \ \ \ ADC Channels \ \ ch desc port and bit number or peripheral name \ == ======= ============================================ \ 0 adc_in0 pa0 : this is the "USER" push button on a STM32F0 Discovery Board, normally LOW, goes to VCC when pressed \ 1 adc_in1 pa1 : in this instance I have a 10k pot connected across Vcc and 0V. The wiper is connected to pa1 \ 2 adc_in2 pa2 \ 3 adc_in3 pa3 \ 4 adc_in4 pa4 \ 5 adc_in5 pa5 \ 6 adc_in6 pa6 \ 7 adc_in7 pa7 \ 8 adc_in8 pb0 \ 9 adc_in9 pb1 \ 10 adc_in10 pc0 (not present in 32pin qfn package) \ 11 adc_in11 pc1 (not present in 32pin qfn package) \ 12 adc_in12 pc2 (not present in 32pin qfn package) \ 13 adc_in13 pc3 (not present in 32pin qfn package) \ 14 adc_in14 pc4 (not present in 32pin qfn package) \ 15 adc_in15 pc5 (not present in 32pin qfn package) \ 16 temp internal peripheral, must be turned on in rcc \ 17 vref internal peripheral, must be turned on in rcc \ 18 batt internal peripheral, must be turned on in rcc \ \ NOTE: What does ADC_INX correspond to in the real world, where is that information ? \ It is shown in: https://www.st.com/resource/en/datasheet/stm32f051t8.pdf , see Table 13. Pin definitions \ \ ======================== screenpic ! ======================= \ \ t \ stm32f0 discovery board, no dma, no interrupts, all channel adc scan \ -------------------------------------------------------------------- \ battery = 2.964 v \ vref (typically 1.16 to 1.25 v) = 1.219 v \ temperature = 26.860 c \ pc5 = 1.951 v \ pc4 = 1.969 v \ pc3 = 2.054 v \ pc2 = 2.056 v \ pc1 = 2.056 v \ pc0 = 2.049 v \ pb1 = 1.748 v \ pb0 = 1.803 v \ pa7 = 1.914 v \ pa6 = 1.801 v \ pa5 = 1.731 v \ pa4 = 1.366 v \ pa3 = 1.617 v \ pa2 = 0.977 v \ pa1 = 0.009 v \ pa0 = 0.011 v \ \ eoc flag state: reset \ eos flag state: reset \ adc has NOT overrun \ eoc spincount, total over 19 channels = 95 \ ok. \ \ ------------------------------------------------------------------------------------------------------ \ Essential - Create and preload a Memory-Map file for registers used in this program. \ \ i.e. "$48000000 constant gpioa_moder \ GPIO port mode register" \ \ For a easy way to do this see https://mecrisp-stellaris-folkdoc.sourceforge.io/svd2mem-sqlite.html \ \ 31Dec2021: Sadly I wrote this program in 2018 using a now obsolete system, and there is no memory map file for it. \ I'll rewrite this using my current system (SVD2FORTH V6) which generates everything needed for projects, inc \ the memory in due course. \ ------------------------------------------------------------------------------------------------------ compiletoram 0 variable spincount \ This is used to give a indication of how long the adc takes to convert a voltage \ init words : pa0-7-analog %111111111111111111 0 lshift gpioa_moder bis! ." pa0-7 set to analog mode " ; : pb0-1-analog %1111 0 lshift gpiob_moder bis! ." pb0-1 set to analog mode " ; : pc0-5-analog %111111111111 0 lshift gpioc_moder bis! ." pc0-5 set to analog mode " ; : adc-select-ch-0-18 %1111111111111111111 0 lshift adc_chselr bis! ." adc channels 0-18 select for scanning " ; : vref-enable %1 22 lshift adc_ccr bis! ." adc vref enabled " ; : battery-monitor-enable %1 24 lshift adc_ccr bis! ." battery monitor enabled " ; : temperature-sensor-enable %1 23 lshift adc_ccr bis! ." temp sensor enabled " ; : adc-clock-enable %1 9 lshift rcc_apb2enr bis! ." adc clock enabled" ; : adc-set-sample-time %111 adc_smpr bis! ." adc sample time set to 239.5 clock cycles " ; : adc-forward-scan %1 2 lshift adc_cfgr1 bic! ." forward scan channel 0 to channel 18 selected" ; \ general words : adc-disable %1 0 lshift adc_cr bic! ; \ adc disable aden=0 : adc-set-calibrate-bit %1 31 lshift adc_cr bis! ; \ adcal=1 : adc-calibrate-bit? %1 31 lshift adc_cr bit@ ; \ adcal= ? : adc-calibrated? begin adc-calibrate-bit? not until ." adc calibrated" cr ; \ adcal=0, had the adc finished calibrating itself ? : adc-ready-flag? %1 0 lshift adc_isr bit@ ; \ adc_adrdy flag, is the adc ready to do a read ? : adc-end-of-conversion-flag? %1 2 lshift adc_isr bit@ ; \ adc_eoc conversion flag : adc-end-of-sequence-flag? %1 3 lshift adc_isr bit@ ; \ eos flag is set when all conversions are finished, reset by application software : adc-end-of-sequence? begin adc-end-of-sequence-flag? until ; \ has adc scan sequence finished ? : adc-set-to-single-conversion-mode %1 13 lshift adc_cfgr1 bic! ; \ adc_cont is set to 0 on reset : adc-conversion-start %1 2 lshift adc_cr bis! ; \ adc_adstart - start a adc conversion : adc-ready? begin adc-ready-flag? until ; \ is the adc ready ? : scan0-18 %1 2 lshift adc_cfgr1 bic! ; \ adc_scandir scandir=0: forward scan channel 0 to channel 18 : scan18-0 %1 2 lshift adc_cfgr1 bis! ; \ adc_scandir scandir=1: backward scan channel 18 to channel 0 : adc-enable %1 0 lshift adc_cr bis! ." adc enabled " adc-ready? ; : eoc?? adc-end-of-conversion-flag? if ." eoc flag state: set" else ." eoc flag state: reset" then cr ; \ the eoc flag is reset by reading the adc_dr register. : eos?? adc-end-of-sequence-flag? if ." eos flag stare: set" else ." eos flag state: reset" then cr ; \ the eos flag is reset by writing a "1" to it. : overun? %1 4 lshift adc_isr bit@ if ." adc has overrun, data is missed" else ." adc has NOT overrun" then cr ; \ adc_ovr : reset-eos-flag %1 3 lshift adc_isr bis! ; : adc-calibrate ( -- calibrate adc) cr adc-disable adc-set-calibrate-bit adc-calibrated? ; : portbit? ( adc channel -- portbit ) case 0 of ." pc5 = " endof 1 of ." pc4 = " endof 2 of ." pc3 = " endof 3 of ." pc2 = " endof 4 of ." pc1 = " endof 5 of ." pc0 = " endof 6 of ." pb1 = " endof 7 of ." pb0 = " endof 8 of ." pa7 = " endof 9 of ." pa6 = " endof 10 of ." pa5 = " endof 11 of ." pa4 = " endof 12 of ." pa3 = " endof 13 of ." pa2 = " endof 14 of ." pa1 = " endof 15 of ." pa0 = " endof endcase ; \ init adc-calibrate pa0-7-analog pb0-1-analog pc0-5-analog adc-clock-enable \ must be set before following items, or they can't be set. adc-set-sample-time adc-forward-scan adc-select-ch-0-18 vref-enable temperature-sensor-enable battery-monitor-enable adc-enable : read-voltages ( -- read all channels ) begin adc-conversion-start begin 1 spincount +! \ count the number of times we loop here, this is the 'eoc spincount' adc-end-of-conversion-flag? \ jump to 'begin' unless the eoc flag is set until adc_dr @ \ push this ADC reading onto the Stack adc-end-of-sequence-flag? \ jump to 'begin' unless the eos flag is set until reset-eos-flag \ eos-flag has to be reset by the user application ; : display-samples \ pop all channels off the stack, scale and assign names then pretty print them cr ." stm32f0 discovery board, no dma, no interrupts, all channel adc scan " cr ." -------------------------------------------------------------------- " cr \ the 3 special purpose voltages ." battery = " 2970 4096 */ 2 * 0 <# # # # 46 hold #s #> type ." v " cr ." vref (typically 1.16 to 1.25 v) = " 2970 4096 */ 0 <# # # # 46 hold #s #> type ." v " cr ." temperature = " 2970 4096 */ 1300 swap - 100 5 */ 29700 + 0 <# # # # 46 hold #s #> type ." c " cr \ the 16 gpio inputs 16 0 do i portbit? 2970 4096 */ 0 <# # # # 46 hold #s #> type ." v " cr loop ; : t \ scan, read and print with stats read-voltages display-samples cr eoc?? eos?? overun? \ Were we too slow and missed getting a conversion value before the next one was ready ? ." eoc spincount, total over 19 channels = " spincount @ . cr 0 spincount ! \ reset spincount ; t \ just enter 't' to rerun the scan