A Blue Pill LMT01 Temperature Sensor

This is a rewrite of the previous LMT01 temperature sensor project. It now uses fixed point arithmetic to calculate the temperature to one decimal place and has some extra features such as USB/USART2 terminal access, and a MCU “Device Electronic Signature” reader etc.

It contains a ready to run binary for a 64KB Flash version of the STM32F103 Cortex-M3 MCU as used in the Blue Pill that boots from USB at power up.

Connect the few components shown in the schematic below to read the temperature. It runs fine without them but should complain about a missing sensor if you try to read the temperature.

USB

This uses the Mecrisp-Stellaris USB driver for STM32F103 by Jean-Claude Wippler which is based on the Coreforth USB driver by Eckhart Köppen.

Note

From Viktor Dvořák. USB needs PC side idVendor = 0x0483 idProduct = 0x7540 driver which is STM32 Virtual COM port driver desribed in en.DM00478229.pdf. The driver is en.stsw-stm32102.zip (24755 kB) is available directly from st.com

  • Connect the “Blue Pill” USB port to PC and look for “<Mecrisp STM32F10x Forth Serial Port>” device in your system

  • Connect a PC serial terminal to the USB device above, you can choose any Baud Rate.

Note

The USB terminal can switch to USART2 by entering “-usb”. Speed is 460800 Baud.

USART2

Connect a serial terminal to read the temperature.

USART2

MCU Signal

3.3v/USB Dongle

PA1

RTS

CTS

PA2

TX

RX

PA3

RX

TX

Note

The USART2 terminal can switch to USB by entering “+usb”

Screenshot

  • read the temperature by entering “C” or “F” in the terminal.

  • check the mcu signature by entering “stm32id”

  • examine the contents of the RCC CR register by entering “rcc_cr.”

  • read the remperature by pressing the PA0 pushbutton

_images/screenshot.jpg

Instructions

Schematic

Note

Press “C” or “F” for temperature reading, not “C” as shown below on this earlier version schematic.

_images/f103-lmt01.jpeg

Blue Pill Layout

Layout contributed by Michael Jeffery.

_images/lmt01-blue-pill-layout.jpg

Tarball Contents

ae9236b921613c07b1967f21ff20ee97.tar.gz

.
├── ae9236b921613c07b1967f21ff20ee97.DELETE.sh
├── ae9236b921613c07b1967f21ff20ee97.README.md
├── ae9236b921613c07b1967f21ff20ee97.bin
├── ae9236b921613c07b1967f21ff20ee97.flashme
├── ae9236b921613c07b1967f21ff20ee97.words4.txt
├── f103-lmt01.jpeg
├── image.bin
└── lmt01-blue-pill-layout-1.jpg

Source Code

This source code by itself won’t run the temperature sensor, however that’s no problem as all the support Words required are installed in the downloadable ready to run image above. Nothing else is required, just enter “C” or “F” in the terminal or press the push button to read the temperature.

Source Code

~/projects/programming-languages/forth/mecrisp-stellaris/f103-lmt01/f103-lmt01.fs.html
  1 \ Program Name: f103-lmt01.fs
  2 \ Date: Fri 1 Nov 2019 21:02:00 AEDT
  3 \ Copyright 2019 by t.j.porter <terry@tjporter.com.au>, licensed under the GPLV2
  4 \ This program may require preloaded support files
  5 \ For Mecrisp-Stellaris by Matthias Koch.
  6 \ https://sourceforge.net/projects/mecrisp/
  7 \ Chip: STM32F103RBT6, Board: Olimex P103
  8 \ Clock: 8 Mhz using the internalRC clock, unless otherwise stated
  9 \ All register names are CMSIS-SVD compliant
 10 \ Note: gpio a,b,c,d,e, and uart1 are enabled by Mecrisp-Stellaris Core.
 11 \ Requires preloaded support program(s): 
 12 \ Standalone: no preloaded support files required
 13 \
 14 \ This Program :  Texas Instruments LMT01 temperature sensor reader for 128KB STM32F103 MCU
 15 \ Prints DegC and DegF seperately via terminal or together when Push Button (PB0) is pressed.
 16 \ Uses Fixed Point Maths: https://mecrisp-stellaris-folkdoc.sourceforge.io/fixed-point.html?highlight=fixed
 17 \  
 18 \ Clock is set to 72MHz in upload.main.sh for faster uploading
 19 \ ---------------------------------------------------------------------------\
 20 \ LMT01: Output Transfer Function: Temp (C) = ((count/4096) *256) -50
 21 \    Temperature (°C)    Number of pulses
 22 \         ­-49.9375      1
 23 \          -­49.875      2
 24 \             ­-40      160
 25 \             ­-20      480
 26 \                0      800
 27 \               30     1280
 28 \               50     1600
 29 \              100     2400
 30 \              150     3200
 31 \ 
 32 \ ---------------------------------------------------------------------------\
 33 \  GPIO Description
 34 \  ---- -----------
 35 \  PA0   Wake Up PB, normally low        : irq$ = 6 
 36 \  PC12  LED ( open drain to led cathode): not used here
 37 \  PB12  Count input                     : irq# = 40       
 38 \  PB13  LMT01-1 Activate
 39 \ ---------------------------------------------------------------------------\
 40  compiletoram
 41 \ compiletoflash
 42 
 43  \ Variables
 44  0 variable count.lmt01
 45 
 46 
 47  \ GPIO Words
 48  : GPIOB_CRH_MODE13   ( %XX -- ) 20 lshift GPIOB_CRH bis! ;          \ GPIOB_CRH_MODE13 Port n.13 mode bits
 49  : GPIOB_CRH_CNF13   ( %XX -- ) 22 lshift GPIOB_CRH bic! ;           \ GPIOB_CRH_CNF13 Port n.13 configuration  bits
 50  : GPIOB_BSRR_BS13   %1 13 lshift GPIOB_BSRR bis! ;                  \ GPIOB_BSRR_BS13 Set bit 13
 51  : GPIOB_BSRR_BR13   %1 29 lshift GPIOB_BSRR bis! ;                  \ GPIOB_BSRR_BR13 Reset bit 13
 52  : GPIOA_CRL_CNF0   ( %XX -- ) 2 lshift GPIOA_CRL bis! ;             \ GPIOA_CRL_CNF0 Port n.0 configuration  bits
 53  : GPIOA_BRR_BR0   %1 0 lshift GPIOA_BRR bis! ;                      \ GPIOA_BRR_BR0 Reset bit 0
 54 
 55  \ Interrupt Words for LMT01 on PB12, falling trigger. Interrupt #40
 56  : AFIO_EXTICR4_EXTI12   ( %XXXX -- ) 0 lshift AFIO_EXTICR4 bis! ;   \ AFIO_EXTICR4_EXTI12 EXTI12 configuration
 57  : line.12.unmask   %1 12 lshift EXTI_IMR bis! ;                     \ EXTI_IMR_MR12 Interrupt Mask on line 12
 58  : line.12.mask   %1 12 lshift EXTI_IMR bic! ;                       \ EXTI_IMR_MR12 Interrupt Mask on line 12
 59  : EXTI_RTSR_TR12   %1 12 lshift EXTI_RTSR bis! ;                    \ EXTI_RTSR_TR12 Rising trigger line 12 
 60  : EXTI_FTSR_TR12   %1 12 lshift EXTI_FTSR bis! ;                    \ EXTI_FTSR_TR12 Falling trigger line 12
 61  : EXTI_PR_PR12   %1 12 lshift EXTI_PR bis! ;                        \ EXTI_PR_PR12 Pending bit 12
 62  : NVIC_ISER1_SETENA   ( %XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -- ) 0 lshift NVIC_ISER1 bis! ;  \ NVIC_ISER1_SETENA    SETENA
 63 
 64  \ Interrupt for PB on PA0 falling edge as trigger. Interrupt #6
 65  : AFIO_EXTICR1_EXTI0   ( %XXXX -- ) 0 lshift AFIO_EXTICR1 bis! ;    \ EXTI0 configuration 
 66  : line.0.unmask  %1 0 lshift EXTI_IMR bis! ;                        \ EXTI_IMR_MR0 Interrupt Mask on line 0
 67  : line.0.mask    %1 0 lshift EXTI_IMR bic! ;        \ EXTI_IMR_MR0 Interrupt Mask on line 0
 68  : EXTI_RTSR_TR0   %1 0 lshift EXTI_RTSR bis! ;                      \ EXTI_RTSR_TR0 Rising trigger line 0
 69  : EXTI_PR_PR0   %1 0 lshift EXTI_PR bis! ;                          \ EXTI_PR_PR0 Pending bit 0
 70  : NVIC_ISER0_SETENA   ( %XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -- ) 0 lshift NVIC_ISER0 bis! ;  \ NVIC_ISER0_SETENA    SETENA
 71 
 72  \ General Words
 73  : >s31.32 ( u -- s31.32 ) 0 swap ; \ convert integer to a Fixed Point s31.32 number
 74  : nvic-priority ( priority irq# -- )
 75   $E000E400 + c!
 76  ;
 77 
 78  : pa0.pulldown  ( -- )    \ PA0 is read temperature pushbutton, triggered when pulled high, so add pulldown.
 79    \ 3 2    1 0
 80    \ CNF0   MOD0
 81    \ 0 1    0 0    default input, floating
 82    \ 1 0    0 0    wanted   %10 constant cnf.input.pull.up.down
 83    2 bit GPIOA_CRL bic!    \ clear bit 2
 84    3 bit GPIOA_CRL bis!    \ set bit 3
 85    GPIOA_BRR_BR0           \ with F103, pulldown enabled setting output bit to low
 86  ;
 87 
 88  : pb13->output ( -- )
 89    \ 23 22  21 20
 90    \ CNF13  MODE13
 91    \ 0  1   1  1  
 92    %11 GPIOB_CRH_MODE13    \ set both mode bits in output mode 50
 93    %11 GPIOB_CRH_CNF13     \ clear both bits = push/pull in output mode
 94  ;
 95 
 96  : lmt01.power.on  ( -- )
 97    GPIOB_BSRR_BS13
 98  ;
 99 
100  : lmt01.power.off ( -- )
101    GPIOB_BSRR_BR13
102  ;
103 
104  : lmt01-fault? ( -- ) count.lmt01 @ 0 = ;         \ if count.lmt01 >0, no error
105 
106  : lmt01.interrupt.handler ( -- )
107    line.12.mask                                    \ prevent line.12 retriggering until fully handled
108    EXTI_PR_PR12                                    \ clear trigger on line 12 
109    1 count.lmt01 +!                                \ increment count.lmt01 by one
110    line.12.unmask                                  \ line.12 can be retriggered now
111  ;
112 
113  : lmt01.interrupt.init ( #40 )
114    1 AFIO_EXTICR4_EXTI12                           \ line PB12
115    line.12.unmask
116    EXTI_FTSR_TR12                                  \ falling trigger on line 12
117    ['] lmt01.interrupt.handler irq-exti10 !        \ link exti10 ( to pb.interrupt.handler
118    %100000000 NVIC_ISER1_SETENA                    \ enable enterrupt #40 
119  ;
120 
121  : read.lmt01 ( lmt01 -- count )          \ read sensor, power on, delay, power off
122    0 count.lmt01 !
123    ms.counter.reset
124    lmt01.power.on
125    100 ms.delay
126    lmt01.power.off
127    lmt01-fault? if                        \ count window has ended, if no counts there has been an error.
128       ." LMT01 FAULTY OR NOT PRESENT ! "
129       else
130       count.lmt01 @
131       then
132    line.0.unmask                          \ pb.interrupt may now be triggered again
133  ;
134 
135  : convert.count.to.degrees.c ( count -- degC )    \ convert count.lmt01 to deg C
136    >s31.32                                         \ Temp (C) = ((count.lmt01/4096) *256) -50
137    4096,0 f/ 256,0 f* 50,0 d-
138  ;
139 
140  : convert.count.to.degrees.f ( -- )
141    convert.count.to.degrees.c
142    1,8 f* 32 >s31.32 d+                            \ °F = °C * 1.8000 + 32.00
143 
144  ;
145 
146  : C ( -- )                               \ Deg C print shortcut
147    read.lmt01
148    convert.count.to.degrees.c
149    2 f.n ." C " cr
150  ;
151 
152  : F  ( c -- )                            \ Deg F print shortcut.
153    read.lmt01
154    convert.count.to.degrees.f
155    2 f.n ." F " cr
156  ;
157 
158  : pb.interrupt.handler ( -- )
159    line.0.mask                            \ prevent retriggering until fully handled
160    EXTI_PR_PR0                            \ clear trigger   
161    C F cr                                 \ read temperatures
162  ;
163 
164  : pb.interrupt.init ( #6 )
165    0 AFIO_EXTICR1_EXTI0                   \ line PA0 
166    line.0.unmask                          \ unmask line 0
167    EXTI_RTSR_TR0                          \ rising trigger in line 0
168    ['] pb.interrupt.handler irq-exti0 !   \ link exti0 to pb.interrupt.handler
169    %1000000  NVIC_ISER0_SETENA            \ enable interrupt #6 
170  ;
171 
172  : interrupt.priorities ( -- )            \ highest number is lowest priority
173    100 40   nvic-priority                 \ lmt01 sensor pulse detect
174    200  6   nvic-priority                 \ pushbutton
175  ;
176 
177  : init ( -- )
178    72mhz
179    interrupt.priorities
180    systick.init
181    lmt01.interrupt.init
182    pb.interrupt.init
183    pa0.pulldown
184    pb13->output
185  ;
186 
187  init
188 
189 compiletoram
190 
191 
192 \ Screenshots
193 \ 
194 \ c 35,68 C 
195 \  ok.
196 \ f 96,23 F 
197 \  ok.
198 \ press button
199 \ 35,68 C 
200 \ 96,34 F
201 \ 
202 \ 35,68 C 
203 \ 96,34 F 
204 \ 
205 \ read.lmt01 . 1371  ok.  <-- raw count @ 35,68 C = 96,34 F
206 

Play With Forth ?

This Image is a complete system, it contains the compiler and many internal Peripheral registers, see the ae9236b921613c07b1967f21ff20ee97.words4.txt file for a listing of what’s there.

Wonder what they all mean ? see the Dictionary.

You can read, write and examine registers, run programs, even commit them to Flash memory.

Note

to erase all the Flash except the default Mecrisp-Stellaris Forth system, enter “eraseflash” at the terminal. This will remove everything from this project including the USB, and only USART2 will work with a terminal. To reinstall everything just reflash the ae9236b921613c07b1967f21ff20ee97.bin imahe to your board.