Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
embedded-rust-michael-david
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
david.dasilvam2
embedded-rust-michael-david
Commits
70adabc6
Commit
70adabc6
authored
1 year ago
by
michael.divia
Browse files
Options
Downloads
Patches
Plain Diff
I2C & SPI Working
parent
70decd77
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
.vscode/settings.json
+3
-0
3 additions, 0 deletions
.vscode/settings.json
src/i2c.rs
+0
-69
0 additions, 69 deletions
src/i2c.rs
src/main.rs
+398
-24
398 additions, 24 deletions
src/main.rs
with
401 additions
and
93 deletions
.vscode/settings.json
0 → 100644
+
3
−
0
View file @
70adabc6
{
"cortex-debug.variableUseNaturalFormat"
:
false
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/i2c.rs
deleted
100644 → 0
+
0
−
69
View file @
70decd77
#![no_std]
#![no_main]
extern
crate
panic_halt
;
use
cortex_m_rt
::
entry
;
use
cortex_m_semihosting
::
hprintln
;
use
stm32l4xx_hal
as
hal
;
use
crate
::
hal
::
i2c
;
use
crate
::
hal
::
i2c
::
I2c
;
use
crate
::
hal
::
prelude
::
*
;
#[entry]
fn
main
()
->
!
{
hprintln!
{
"Nucleo-l476RG is alive !"
};
/*
setup peripherals
*/
let
periphs
=
hal
::
stm32
::
Peripherals
::
take
()
.unwrap
();
let
mut
flash
=
periphs
.FLASH
.constrain
();
// .constrain();
let
mut
rcc
=
periphs
.RCC
.constrain
();
let
mut
pwr
=
periphs
.PWR
.constrain
(
&
mut
rcc
.apb1r1
);
// let mut gpioa = periphs.GPIOA.split(&mut rcc.ahb2);
let
mut
gpiob
=
periphs
.GPIOB
.split
(
&
mut
rcc
.ahb2
);
let
clocks
=
rcc
.cfgr
.freeze
(
&
mut
flash
.acr
,
&
mut
pwr
);
/*
setup i2c
*/
let
mut
scl
=
gpiob
.pb13.into_alternate_open_drain
::
<
4
>
(
&
mut
gpiob
.moder
,
&
mut
gpiob
.otyper
,
&
mut
gpiob
.afrh
,
);
scl
.internal_pull_up
(
&
mut
gpiob
.pupdr
,
true
);
let
mut
sda
=
gpiob
.pb14.into_alternate_open_drain
::
<
4
>
(
&
mut
gpiob
.moder
,
&
mut
gpiob
.otyper
,
&
mut
gpiob
.afrh
,
);
sda
.internal_pull_up
(
&
mut
gpiob
.pupdr
,
true
);
let
mut
i2c
=
I2c
::
i2c2
(
periphs
.I2C2
,
(
scl
,
sda
),
i2c
::
Config
::
new
(
100
.kHz
(),
clocks
),
&
mut
rcc
.apb1r1
,
);
let
mut
buffer
=
[
0u8
;
4
];
const
MPL115A2_ADDR_WRITE
:
u8
=
0xC0
;
const
MPL115A2_ADDR_READ
:
u8
=
0xC1
;
i2c
.write_read
(
MPL115A2_ADDR_WRITE
,
&
[
0x04
],
&
mut
buffer
)
.unwrap
();
hprintln!
(
"TEST: {}"
,
buffer
[
0
]);
loop
{
continue
;
}
}
This diff is collapsed.
Click to expand it.
src/main.rs
+
398
−
24
View file @
70adabc6
...
...
@@ -3,77 +3,451 @@
extern
crate
panic_halt
;
use
cortex_m
::
asm
;
use
cortex_m_rt
::
entry
;
use
cortex_m_semihosting
::
hprint
;
use
cortex_m_semihosting
::
hprintln
;
use
hal
::
gpio
::
Alternate
;
use
stm32l4xx_hal
as
hal
;
use
crate
::
hal
::
i2c
;
use
crate
::
hal
::
i2c
::
I2c
;
use
crate
::
hal
::
prelude
::
*
;
use
stm32l4xx_hal
::{
gpio
::{
PushPull
,
Speed
},
hal
::
spi
::{
Mode
,
Phase
,
Polarity
},
prelude
::
*
,
spi
::
Spi
,
};
struct
Coefficient
{
a0
:
f32
,
b1
:
f32
,
b2
:
f32
,
c12
:
f32
,
}
struct
Data
{
pression
:
f32
,
temperature
:
f32
,
luminosity
:
i32
,
}
#[entry]
fn
main
()
->
!
{
// Clean terminal and acknowledge the boot
hprint!
{
"{}[2J"
,
27
as
char
};
hprintln!
{
"Nucleo-l476RG is alive !"
};
/*
setup peripherals
*/
// **** Setup Peripherals ****
let
periphs
=
hal
::
stm32
::
Peripherals
::
take
()
.unwrap
();
let
mut
flash
=
periphs
.FLASH
.constrain
();
// .constrain();
let
mut
flash
=
periphs
.FLASH
.constrain
();
let
mut
rcc
=
periphs
.RCC
.constrain
();
let
mut
pwr
=
periphs
.PWR
.constrain
(
&
mut
rcc
.apb1r1
);
//
let mut gpio
a
= periphs.GPIO
A
.split(&mut rcc.ahb2);
let
mut
gpio
c
=
periphs
.GPIO
C
.split
(
&
mut
rcc
.ahb2
);
let
mut
gpiob
=
periphs
.GPIOB
.split
(
&
mut
rcc
.ahb2
);
let
mut
gpioa
=
periphs
.GPIOA
.split
(
&
mut
rcc
.ahb2
);
let
clocks
=
rcc
.cfgr
.freeze
(
&
mut
flash
.acr
,
&
mut
pwr
);
// **** Setup SPI ****
/*
setup gpios
VCC -> 5V
GND -> GND
SCK -> PC_10
SDO -> PC_11
NC -> X
CS -> PB_6
*/
// let mut led = gpioa
// .pa5
// .into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper);
// Pins
let
sclk
=
gpioc
.pc10
.into_alternate
(
&
mut
gpioc
.moder
,
&
mut
gpioc
.otyper
,
&
mut
gpioc
.afrh
)
.set_speed
(
Speed
::
High
);
let
miso
=
gpioc
.pc11
.into_alternate
(
&
mut
gpioc
.moder
,
&
mut
gpioc
.otyper
,
&
mut
gpioc
.afrh
)
.set_speed
(
Speed
::
High
);
let
mosi_dummy
=
gpioc
.pc12
.into_alternate
(
&
mut
gpioc
.moder
,
&
mut
gpioc
.otyper
,
&
mut
gpioc
.afrh
)
.set_speed
(
Speed
::
High
);
let
mut
cs
=
gpiob
.pb6
.into_push_pull_output
(
&
mut
gpiob
.moder
,
&
mut
gpiob
.otyper
);
// SPI
let
mut
spi
=
Spi
::
spi3
(
periphs
.SPI3
,
(
sclk
,
miso
,
mosi_dummy
),
Mode
{
phase
:
Phase
::
CaptureOnFirstTransition
,
polarity
:
Polarity
::
IdleLow
,
},
1000
.kHz
(),
clocks
,
&
mut
rcc
.apb1r1
,
);
// **** Setup I2C ****
/*
setup i2c
VDD -> 5V
GND -> GND
SCL -> PB_13
SDA -> PB_14
RST -> X
SDWN -> X
*/
// Pins
let
mut
scl
=
gpiob
.pb13.into_alternate_open_drain
::
<
4
>
(
&
mut
gpiob
.moder
,
&
mut
gpiob
.otyper
,
&
mut
gpiob
.afrh
,
);
scl
.internal_pull_up
(
&
mut
gpiob
.pupdr
,
true
);
let
mut
sda
=
gpiob
.pb14.into_alternate_open_drain
::
<
4
>
(
&
mut
gpiob
.moder
,
&
mut
gpiob
.otyper
,
&
mut
gpiob
.afrh
,
);
// Set pull up
scl
.internal_pull_up
(
&
mut
gpiob
.pupdr
,
true
);
sda
.internal_pull_up
(
&
mut
gpiob
.pupdr
,
true
);
let
mut
i2c
=
I2c
::
i2c2
(
// Create I2C
let
mut
i2c_a
=
I2c
::
i2c2
(
periphs
.I2C2
,
(
scl
,
sda
),
i2c
::
Config
::
new
(
100
.kHz
(),
clocks
),
&
mut
rcc
.apb1r1
,
);
let
mut
buffer
=
[
0u8
;
4
];
// Create Data Struct
let
mut
data
=
Data
{
pression
:
0.0
,
temperature
:
0.0
,
luminosity
:
0
,
};
// **** Main Loop ****
loop
{
// Get Data
mpl115_a2
(
&
mut
i2c_a
,
&
mut
data
);
pb200_286
(
&
mut
spi
,
&
mut
cs
,
&
mut
data
);
// Display Data
hprintln!
(
"{}[2J"
,
27
as
char
);
hprintln!
(
"Pression: {} [kPa]
\n
Température: {} [°C] (±5 °C)
\n
Luminosité: {} / 125"
,
data
.pression
,
data
.temperature
,
data
.luminosity
);
// Wait
asm
::
delay
(
2_000_000
);
}
}
// **** pb200_286 Function ****
/// Retrieve luminosity data from a Pmod ALS: Ambient Light Sensor
/// INPUT :
/// 1: spi -> The SPI module with which you would like to communicate
/// 2: cs -> The corresponding Chip Select for this SPI module
/// 3: data -> The reference in which the data will be written
/// OUTPUT :
/// NONE
fn
pb200_286
(
spi
:
&
mut
Spi
<
crate
::
hal
::
pac
::
SPI3
,
(
crate
::
hal
::
gpio
::
Pin
<
Alternate
<
PushPull
,
6
>
,
crate
::
hal
::
gpio
::
H8
,
'C'
,
10
>
,
crate
::
hal
::
gpio
::
Pin
<
Alternate
<
PushPull
,
6
>
,
crate
::
hal
::
gpio
::
H8
,
'C'
,
11
>
,
crate
::
hal
::
gpio
::
Pin
<
Alternate
<
PushPull
,
6
>
,
crate
::
hal
::
gpio
::
H8
,
'C'
,
12
>
,
),
>
,
cs
:
&
mut
crate
::
hal
::
gpio
::
Pin
<
crate
::
hal
::
gpio
::
Output
<
PushPull
>
,
crate
::
hal
::
gpio
::
L8
,
'B'
,
6
,
>
,
data
:
&
mut
Data
,
)
{
// Set Chip Select to low to start data exchange
cs
.set_low
();
// Retrieve the data
let
mut
buffer
=
[
0x00
,
0x00
];
spi
.transfer
(
&
mut
buffer
)
.unwrap
();
// Set Chip Select to high to stop data exchange
cs
.set_high
();
// Data is send in 2 bytes, with 3 leading and 4 trailing zeros
let
mut
lux
=
buffer
[
0
]
<<
3
;
lux
|
=
buffer
[
1
]
>>
4
;
// Store Data in struct
data
.luminosity
=
lux
as
i32
;
}
/// **** mpl115_a2 Function ****
/// Retrieve Pressure and Temperature data from a MPL115A2 - I2C Barometric Pressure/Temperature Sensor
/// INPUT :
/// 1: i2c -> The I2C module with which you would like to communicate
/// 2: data -> The reference in which the data will be written
/// OUTPUT :
/// NONE
fn
mpl115_a2
(
i2c
:
&
mut
I2c
<
crate
::
hal
::
pac
::
I2C2
,
(
crate
::
hal
::
gpio
::
Pin
<
Alternate
<
crate
::
hal
::
gpio
::
OpenDrain
,
4
>
,
crate
::
hal
::
gpio
::
H8
,
'B'
,
13
,
>
,
crate
::
hal
::
gpio
::
Pin
<
Alternate
<
crate
::
hal
::
gpio
::
OpenDrain
,
4
>
,
crate
::
hal
::
gpio
::
H8
,
'B'
,
14
,
>
,
),
>
,
data
:
&
mut
Data
,
)
{
// Create our buffers
let
mut
buffer_4
=
[
0u8
;
4
];
let
mut
buffer_8
=
[
0u8
;
8
];
// Set the address of our card
const
MPL115A2_ADDR
:
u8
=
0x60
;
/*
Main loop
*/
// Get Coefficients
i2c
.write_read
(
MPL115A2_ADDR
,
&
[
0x04
],
&
mut
buffer_8
)
.unwrap
();
let
coeffs
=
coeff
(
buffer_8
);
asm
::
delay
(
1_000_000
);
i2c
.write_read
(
MPL115A2_ADDR
,
&
[
0x04
],
&
mut
buffer
)
.unwrap
();
hprintln!
(
"TEST: {}"
,
buffer
[
0
]
);
// Start Pressure and Temperature Conversion
i2c
.write
(
MPL115A2_ADDR
,
&
[
0x12
,
0x00
])
.unwrap
(
);
loop
{
continue
;
asm
::
delay
(
1_000_000
);
// Get Temperature & Pressure
i2c
.write_read
(
MPL115A2_ADDR
,
&
[
0x00
],
&
mut
buffer_4
)
.unwrap
();
asm
::
delay
(
1_000_000
);
// Calculate Pressure Compensation
let
pcomp
=
pcomp
(
buffer_4
,
coeffs
);
// Calculate Pressure
let
press
=
pcomp
*
((
115.0
-
50.0
)
/
1023.0
)
+
50.0
;
// Calculate non accurate and non calibrated temperature
let
temp
=
((((((
buffer_4
[
2
]
as
u16
)
<<
8
)
+
buffer_4
[
3
]
as
u16
)
>>
6
)
as
f32
)
-
605.75
)
/
-
5.35
;
// Store Data in struct
data
.pression
=
press
;
data
.temperature
=
temp
;
}
/// **** pcomp Function ****
/// Calculates the Pressure Compensation with the Pressure ADC and the Temperature ADC
/// INPUT :
/// 1: buffer -> Buffer with the Pressure ADC and the Temperature ADC
/// 2: coeffs -> Struct with all Coefficients
/// OUTPUT :
/// Pressure Compensation
fn
pcomp
(
buffer
:
[
u8
;
4
],
coeffs
:
Coefficient
)
->
f32
{
// Retrieve Pressure ADC and Temperature ADC
let
padc
=
((((
buffer
[
0
]
as
u16
)
<<
8
)
+
buffer
[
1
]
as
u16
)
>>
6
)
as
f32
;
let
tdac
=
((((
buffer
[
2
]
as
u16
)
<<
8
)
+
buffer
[
3
]
as
u16
)
>>
6
)
as
f32
;
//https://cdn-shop.adafruit.com/datasheets/MPL115A2.pdf
// For TEST
//let padc = (0x6680 >> 6) as f32;
//let tdac = (0x7EC0 >> 6) as f32;
// Pcomp = a0 + (b1 + c12 * Tadc) * Padc + b2 * Tadc
let
c12_2
=
coeffs
.c12
*
tdac
;
let
a1
=
coeffs
.b1
+
c12_2
;
let
a1_1
=
a1
*
padc
;
let
y1
=
coeffs
.a0
+
a1_1
;
let
a2_2
=
coeffs
.b2
*
tdac
;
return
y1
+
a2_2
;
}
/// **** coeff Function ****
/// Calculates all the coefficients
/// INPUT :
/// 1: buffer -> Buffer with all coefficients data
/// OUTPUT :
/// Coefficients
fn
coeff
(
buffer
:
[
u8
;
8
])
->
Coefficient
{
// Get the HEX of all coefficients
let
a0_coeff_hex
=
((
buffer
[
0
]
as
u16
)
<<
8
)
+
buffer
[
1
]
as
u16
;
let
b1_coeff_hex
=
((
buffer
[
2
]
as
u16
)
<<
8
)
+
buffer
[
3
]
as
u16
;
let
b2_coeff_hex
=
((
buffer
[
4
]
as
u16
)
<<
8
)
+
buffer
[
5
]
as
u16
;
let
c12_coeff_hex
=
((
buffer
[
6
]
as
u16
)
<<
8
)
+
buffer
[
7
]
as
u16
>>
2
;
//https://cdn-shop.adafruit.com/datasheets/MPL115A2.pdf
// For TEST
//let a0_coeff_hex: u16 = 0x3ECE;
//let b1_coeff_hex: u16 = 0xB3F9;
//let b2_coeff_hex: u16 = 0xC517;
//let c12_coeff_hex: u16 = 0x33C8 >> 2;
// Apply Q-Format on all coefficients
let
a0
=
q_format_to_float
(
a0_coeff_hex
,
3
,
13
,
0
);
let
b1
=
q_format_to_float
(
b1_coeff_hex
,
13
,
3
,
0
);
let
b2
=
q_format_to_float
(
b2_coeff_hex
,
14
,
2
,
0
);
let
c12
=
q_format_to_float
(
c12_coeff_hex
,
13
,
0
,
9
);
return
Coefficient
{
a0
,
b1
,
b2
,
c12
};
}
/// **** q_format_to_float Function ****
/// Converts Hex to f32 with custom Q-Format
/// INPUT :
/// 1: hex -> coefficient data
/// 2: fractional_bits -> Number of fractional bits
/// 3: int_bits -> Number of int bits
/// 4: decimal_padding -> Padding for the fractional bits
/// OUTPUT :
/// Coefficient
fn
q_format_to_float
(
hex
:
u16
,
fractional_bits
:
i64
,
int_bits
:
i64
,
decimal_padding
:
i64
)
->
f32
{
// Mask to isolate the fractional part
let
bitmask
=
(
1
<<
fractional_bits
)
-
1
;
// Get the fractional part
let
frac_part
=
frac_to_float
(
hex
&
bitmask
,
fractional_bits
,
decimal_padding
);
// Get the signed part
let
signed_part
=
shex_to_float
(
hex
>>
fractional_bits
,
int_bits
);
// Add fractional part to signed part by making sure that if the signed part was negative, the fractional part must also be negative
if
signed_part
.is_sign_positive
()
{
return
signed_part
+
frac_part
;
}
else
{
return
signed_part
-
(
1.0
-
frac_part
);
}
}
/// **** custom_pow Function ****
/// Custom Power function
/// INPUT :
/// 1: base -> base of the power
/// 2: exponent -> exponent of the power
/// OUTPUT :
/// Result of power
fn
custom_pow
(
base
:
f32
,
exponent
:
i64
)
->
f32
{
// Any number raised to the power of 0 is 1
if
exponent
==
0
{
return
1.0
;
}
let
mut
result
=
1.0
;
let
mut
exp
=
exponent
;
let
mut
base_val
=
base
;
// Handle negative exponents by inverting the base and exponent, ensuring a positive calculation
if
exponent
<
0
{
base_val
=
1.0
/
base_val
;
exp
=
-
exp
;
}
// Loop to calculate the power iteratively by multiplying base_val with itself 'exp' times
for
_
in
0
..
exp
{
result
*=
base_val
;
}
return
result
;
}
/// **** frac_to_float Function ****
/// Converts the fractional bites to a normal fractional number
/// INPUT :
/// 1: hex -> coefficient data
/// 2: fractional_bits -> Number of fractional bits
/// 2: decimal_padding -> Padding for the fractional bits
/// OUTPUT :
/// Fractional part
fn
frac_to_float
(
hex
:
u16
,
fractional_bits
:
i64
,
decimal_padding
:
i64
)
->
f32
{
// Fractional bites are calculated this way :
// Hex => 0xA / number of fractional bytes => 5
// Binary => 01010
// Fractional part => 2^-2 + 2^-4 = 0.3125
let
mut
frac
=
0.0
;
let
mut
exp
=
fractional_bits
;
// Knowing that we will travel from right to left, we will start with the smallest power and go to the biggest
for
i
in
0
..
fractional_bits
{
// Mask to isolate 1 bit
let
mask
=
1
<<
i
;
// Check if the bit is a 1
if
(
hex
&
mask
)
!=
0
{
// Calculate the fraction with our custom power function and without forgetting to add the decimal padding
frac
+=
custom_pow
(
2.0
,
(
exp
+
decimal_padding
)
*
-
1
);
}
// 'exp' is going inverted from 'i'
exp
-=
1
;
}
return
frac
;
}
/// **** shex_to_float Function ****
/// Converts the Signed integer bites to a normal integer number
/// INPUT :
/// 1: hex -> coefficient data
/// 2: int_bits -> Number of integer bits
/// OUTPUT :
/// Signed Integer part
fn
shex_to_float
(
hex
:
u16
,
int_bits
:
i64
)
->
f32
{
// No need to do everything if the hex is already 0
if
hex
!=
0
{
// Get the sign bit
let
sign_bit
=
1
<<
(
int_bits
-
1
);
// If the int is negative
if
(
hex
&
sign_bit
)
!=
0
{
// Create a mask to get the Integer part without the sign bit
let
mask
=
(
1u16
<<
int_bits
)
-
1
;
// Invert every bits and multiply by -1
let
negative_value
=
((
hex
^
mask
)
as
f32
)
*
-
1.0
;
return
negative_value
;
}
else
{
// Simply convert the value
return
hex
as
f32
;
}
}
else
{
return
0.0
;
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment