User Tools

Site Tools


en:pfw:i2c_gd32vf_noforth_gd32vf103_hw-i2c.f

(* GD32VF103 hardware I2C driver

Values for CRL/CRH-Registers:
 0:  Analog Input
 1:  Output Push/Pull, 10 MHz
 2:  Output Push/Pull,  2 MHz
 3:  Output Push/Pull, 50 MHz
 4:  Floating Input (Reset state)
 5:  Open-Drain Output, 10 MHz
 6:  Open-Drain Output,  2 MHz
 7:  Open-Drain Output, 50 MHz
 8:  Input with pull-up / pull-down
 9:  Alternate Function, Push/Pull, 10 MHz
 A:  Alternate Function, Push/Pull,  2 MHz
 B:  Alternate Function, Push/Pull, 50 MHz
 C:  Reserved
 D:  Alternate Function, Open-Drain, 10 MHz
 E:  Alternate Function, Open-Drain,  2 MHz
 F:  Alternate Function, Open-Drain, 50 MHz

Look at page20ff of the GD32VF103 Datasheet for the optional pin functions

PB6 = SCL
PB7 = SDA

dm 260 is (52Mhz/(100Khz*2)). (And SCL rise-time no longer then 1000 ns)

100 = Start, 200 = Stop, 400 = Ack

  User words:  I2C-ON  {I2C-WRITE  {I2C-READ   I2C}
               BUS@  BUS!  DEVICE!  {DEVICE-OK?}
  Additional:  {I2C-OUT  {I2C-IN  {POLL}  BUS!}  BUS@}  BUS-MOVE  ||
 
  An example, first execute I2C-ON  After that the I2C is setup as
  a master. Sent byte 'b' to an I2C device with address 'a'.
    : >SLAVE    ( b a -- )  device!  1 {i2c-write  bus!  i2c} ;
    : >PCF8574  ( b -- )    20 >slave ;

*)

hex
\ : ABORT" ( flag ccc -- )         
\    postpone if  postpone ."  postpone abort  postpone then ; immediate

v: inside also definitions
40010C00 constant PB-CRL    \ Port-B control Register for pins 0 to 7
40010C08 constant PB-IDR    \ Port-B Input Data Register
40010C0C constant PB-ODR    \ Port-B Output Data Register

40021010 constant RCU-APB1RST   \ bit-21 = I2C-0 - 200000 = Reset device
40021018 constant RCU-APB2EN    \ bit-3  = I2C-0 - 000008 = Clock to device
4002101C constant RCU-APB1EN    \ bit-21 = I2C-0 - 200000 = Clock to device

40005400 constant I2C-CTL0      \ Control register 1
40005404 constant I2C-CTL1      \ Control register 2
40005410 constant I2C-DATA      \ Buffer register
40005414 constant I2C-STAT0     \ Status register 0
40005418 constant I2C-STAT1     \ Status register 1
4000541C constant I2C-CKCFG     \ Configure
40005420 constant I2C-RT        \ Rise time
40005490 constant I2C-FMPCFG    \ Fast mode config.

value DEV  value SUM
: i2c-stat0?    ( mask -- 0|mask )      i2c-stat0 bit* ;
v: extra definitions
: ||            ( -- )                  ; immediate  \ Dummy modifier...

: I2C-ON        ( -- )
    1 i2c-ctl0 *bic             \ Disable I2C
    EE44,4444 pb-crl !          \ Special Function tp PB6 & PB7, 10 MHz, open collector
    20,0000 rcu-apb1rst **bis   \ Restart I2C
    20,0000 rcu-apb1rst **bic   \ Restart I2C
    00,0008 rcu-apb2en **bis    \ Enable PB
    20,0000 rcu-apb1en **bis    \ Enable I2C APB1 clock
    dm 52 i2c-ctl1 h!           \ 52 MHz I2C clock
\   dm 260 i2c-ckcfg h!         \ I2C 100 kHz clock
    dm 130 i2c-ckcfg h!         \ I2C 200 kHz clock
\   dm  65 i2c-ckcfg h!         \ I2C 400 kHz clock
\   dm  32 i2c-ckcfg h!         \ I2C ~800 kHz clock, max ~900 kHz = 28
\     801A i2c-ckcfg h!         \ I2C 1 MHz clock fast mode (DOES NOT WORK!)
\        1 i2c-fmpcfg h!        \ Fast mode plus enable
    dm  25 i2c-rt h!            \ I2C rise time ~520ns
\   dm  15 i2c-rt h!            \ I2C rise time ~300ns (Fast Mode)
    401 i2c-ctl0 *bis ;         \ Enable I2C & ack

v: inside definitions
: >I2C-ADDR     ( +n dev -- )   \ Make start condition & send dev. address
    begin  2 i2c-stat1 bit* 0= until \ Bus free?
    100 i2c-ctl0 *bis           \ Start I2C
    begin  1 i2c-stat0? until   \ Done?
    i2c-data h!  to sum ;       \ Set dev. address & count

v: extra definitions
: {I2C-WRITE    ( +n --)
    dev >i2c-addr               \ Start cond. & dev. address
    begin  2 i2c-stat0? until   \ Done?
    2 i2c-stat1 *bic ;          \ Clear busy

\ The 1+ in the next line is not documented anywhere
: {I2C-READ     ( +n --)
    dev 1+ >i2c-addr            \ Start cond. & dev. address
    begin  2 i2c-stat0? until   \ Send?
    2 i2c-stat1 *bic            \ Clear busy
    400 i2c-ctl0 *bis ;         \ Activate ACK

: I2C}          ( -- )
    begin  200 i2c-ctl0 bit* 0= until ; \ Stop condition finished?

: BUS!          ( b -- )
    begin  80 i2c-stat0? until  \ Buffer free?
    -1 +to sum  i2c-data h!     \ Count bytes & store data
    sum 0= if 200 i2c-ctl0 *bis then ; \ Last byte add stop condition

: BUS@          ( -- b )
    -1 +to sum  sum 0= if       \ Last byte?
        400 i2c-ctl0 *bic       \ Yes, Nack
        200 i2c-ctl0 *bis       \ & stop condition
    then
    begin  40 i2c-stat0? until  \ Buffer filled?
    i2c-data h@ ;

: DEVICE!       ( dev -- )      2* FE and  to dev ;
: {DEVICE-OK?}  ( -- 0|2 )      \ Result is '2' when the address matched
    0 dev >i2c-addr             \ Send start & address
    200 i2c-ctl0 *bis           \ Activate stop condition 
    0  50 0 do                  \ Wait a while for address not matched bit!
        drop  2 i2c-stat0?      \ Read ADDSEND bit 
        dup if  leave  then     \ Ready when address match!
    loop
    2 i2c-stat1 *bic  i2c} ;    \ Clear busy


\ Additional routines like; acknowledge polling & optimised open & close
: {POLL}    ( -- )          begin  {device-ok?} until ; \ Wait until ACK received
: {I2C-OUT  ( dev +n -- )   swap  device!  {i2c-write ;
: {I2C-IN   ( dev +n -- )   swap  device!  {i2c-read ;
: BUS!}     ( b -- )        bus!  i2c} ;
: BUS@}     ( -- b )        bus@  i2c} ;
: BUS-MOVE  ( a u -- )      bounds ?do i c@ bus! loop ; \ Send string of bytes from 'a' with length 'u

v: fresh
shield HW-I2C\  freeze

\ End ;;;
en/pfw/i2c_gd32vf_noforth_gd32vf103_hw-i2c.f.txt · Last modified: 2023-09-04 18:15 by uho