l3gd20 陀螺仪在 stm32f3discovery 上发回重复字节
Posted
技术标签:
【中文标题】l3gd20 陀螺仪在 stm32f3discovery 上发回重复字节【英文标题】:l3gd20 gyroscope sending back repeated bytes on stm32f3discovery 【发布时间】:2020-10-02 12:35:05 【问题描述】:我正在研究 stm32f3discovery 并试图从板上的 l3gd20 陀螺仪读取数据。当我尝试从 OUT_X_L 到 OUT_Z_H 连续读取 6 个字节(这是用于从陀螺仪读取读数的所有数据)时,发送的前三个字节与发送的最后三个字节相同。
当我尝试单独读取每个寄存器时,所有字节都相同,我在示波器上检查过,寄存器在 MOSI 线上发生变化,但响应是 6 个重复字节。
WHO_AM_I 和 OUT_TEMP 寄存器都工作得很好,所以我知道实际的 SPI 不是问题。
这是任何适当的代码,任何帮助或正确方向的指示将不胜感激,谢谢。
Main.rs
#![no_std]
#![no_main]
extern crate panic_itm; // logs messages over ITM; requires ITM support
use cortex_m::asm, iprintln, iprint, Peripherals as core_peripherals;
use cortex_m_rt::entry;
use cortex_m_semihosting::debug, hprintln;
use stm32f3::stm32f303;
mod my_api;
mod sensor;
#[entry]
fn main() -> !
let periph = stm32f303::Peripherals::take().unwrap();
let mut core_p = core_peripherals::take().unwrap();
let itm = &mut core_p.ITM.stim[0];
let gpioa = periph.GPIOA;
let gpioe = periph.GPIOE;
let rcc = periph.RCC
let flash = periph.FLASH;
let spi1 = periph.SPI1;
set_to_72MHz(&rcc, &flash);
let spi = my_api::spi_mod::spi_func::new(&rcc, &gpioa, &gpioe, &spi1);
let mut gyro = sensor::Gyro::gyro::new(&spi, &spi1).init(&spi, &spi1, &gpioe);
loop
iprintln!(itm, ":?", gyro.read_data(&spi, &spi1, &gpioe));
fn set_to_72MHz(rcc: &stm32f3::stm32f303::RCC, flash: &stm32f3::stm32f303::FLASH)
rcc.cr.modify(|_,w| w.hseon().set_bit()); //turns on the external oscillator
while rcc.cr.read().hserdy().bit_is_clear() //wait for it to be ready
flash.acr.modify(|_,w|
w.prftbe().set_bit(); //turn on prefetch
unsafew.latency().bits(0b010) //set latency for 72MHz
);
rcc.cfgr.modify(|_,w|
w.pllxtpre().clear_bit();
unsafew.pllsrc().bits(0b10);
w.pllmul().bits(0b0111);
unsafew.hpre().bits(0b0000);
w.ppre1().bits(0b100);
w.ppre2().bits(0b000)
);
rcc.cr.modify(|_,w| w.pllon().set_bit());
while rcc.cr.read().pllrdy().bit_is_clear()
rcc.cfgr.modify(|_,w| unsafew.sw().bits(0b10));
while rcc.cfgr.read().sws().bits() != 0b10
my_api.rs
pub mod spi_mod
pub struct spi_func
impl spi_func
pub fn new(rcc: &stm32f3::stm32f303::RCC, gpioa: &stm32f3::stm32f303::GPIOA, gpioe: &stm32f3::stm32f303::GPIOE, spi: &stm32f3::stm32f303::SPI1) -> Self
rcc.apb2enr.modify(|_,w| w.spi1en().set_bit()); //enable spi clock
rcc.ahbenr.modify(|_,w| w.iopaen().set_bit()); // enable gpio clocks
rcc.ahbenr.modify(|_,w| w.iopeen().set_bit());
gpioe.moder.modify(|_,w| w.moder3().bits(0b01)); //CS pin
gpioe.otyper.modify(|_,w| w.ot3().clear_bit());
gpioe.odr.modify(|_,w| w.odr3().set_bit()); //bring pe3 high to disable gyro com
// PA5 -> SCL // PA6 -> MISO // PA7 -> MOSI
gpioa.moder.modify(|_,w|
w.moder5().bits(0b10); // output type
w.moder6().bits(0b10);
w.moder7().bits(0b10));
gpioa.otyper.modify(|_,w|
w.ot5().clear_bit();// push pull type
w.ot6().clear_bit();
w.ot7().clear_bit());
gpioa.ospeedr.modify(|_,w|
w.ospeedr5().bits(0b11);// fast mode
w.ospeedr6().bits(0b11);
w.ospeedr7().bits(0b11));
gpioa.afrl.modify(|_,w|
w.afrl5().bits(0b0101);//Alternate function 5
w.afrl6().bits(0b0101);
w.afrl7().bits(0b0101)
);
spi.cr1.modify(|_,w|
w.bidimode().clear_bit(); //bidirectional mode
w.ssm().set_bit(); // hardware slave management disabled
w.ssi().set_bit(); // slave not selected -------------------------------
w.br().bits(0b011); // bring rate from 72MHz to 72/16MHz = 4.5MHz as gyro cant go above 10MHz
w.mstr().set_bit(); // set to master mode
w.cpol().set_bit(); // set to mode 3 to work for the l3gd20
w.cpha().set_bit()
);
spi.cr2.modify(|_,w|
//unsafew.ds().bits(0b0111); // data size = 8 bits
w.errie().clear_bit();
w.txeie().set_bit(); //enable interupt flags
w.rxneie().set_bit();
w.ssoe().clear_bit() //set to single master mode
);
spi.cr1.modify(|_,w| w.spe().set_bit()); // enable spi
spi_func
fn check_faults(&self, spi1: &stm32f3::stm32f303::SPI1) -> bool
if spi1.sr.read().ovr().bit_is_set() //checks through all the flags
false
else if spi1.sr.read().modf().bit_is_set()
false
else if spi1.sr.read().crcerr().bit_is_set()
false
else if spi1.sr.read().udr().bit_is_set()
false
else
true
pub fn write(&self, spi1: &stm32f3::stm32f303::SPI1, data: u16)
if self.check_faults(&spi1)
spi1.dr.modify(|_,w| w.dr().bits(data)); //write to the dr register
while spi1.sr.read().bsy().bit_is_set()
pub fn read(&self, spi1: &stm32f3::stm32f303::SPI1) -> u8
if self.check_faults(&spi1)
while spi1.sr.read().bsy().bit_is_set()
return (spi1.dr.read().dr().bits() >> 8) as u8 //read from the dr register
0
pub fn write_data(&self, spi1: &stm32f3::stm32f303::SPI1, reg_address: u8, data: u8)
let total_data: u16 = ((data as u16) << 8) + (reg_address as u16);
self.write(&spi1, total_data);
pub fn read_register(&self, spi1: &stm32f3::stm32f303::SPI1, reg_address: u8) -> u8
self.write(&spi1, (reg_address | 0x80) as u16); //set the bit to read mode and send
self.read(&spi1) //read the result
pub fn read_multiple_register(&self, spi1: &stm32f3::stm32f303::SPI1, reg_address: u8, rx_data: &mut [u8])
self.write(&spi1, (reg_address | 0x80 | 0x40) as u16);
for d in rx_data.iter_mut()
self.write(&spi1, 0x00);
*d = self.read(&spi1);
senor.rs
pub mod Gyro
pub use crate::my_api::spi_mod;
const WHO_AM_I: u8 = 0x0F;
const CTRL_REG1: u8 = 0x20;
const CTRL_REG4: u8 = 0x23;
const OUT_TEMP: u8 = 0x26;
const OUT_X_L: u8 = 0x28;
const OUT_X_H: u8 = 0x29;
const OUT_Y_L: u8 = 0x2A;
const OUT_Y_H: u8 = 0x2B;
const OUT_Z_L: u8 = 0x2C;
const OUT_Z_H: u8 = 0x2D;
pub struct gyro
pub x: i16,
pub y: i16,
pub z: i16,
offset_x: i32,
offset_y: i32,
offset_z: i32,
pub temp: i8
impl gyro
pub fn new(my_spi_mod: &spi_mod::spi_func, spi1: &stm32f3::stm32f303::SPI1) -> Self
gyro
x: 0,
y: 0,
z: 0,
offset_x: 0,
offset_y: 0,
offset_z: 0,
temp: 0,
pub fn init(self, spi: &spi_mod::spi_func, spi1: &stm32f3::stm32f303::SPI1, gpioe: &stm32f3::stm32f303::GPIOE) -> Self
self.cs_low(&gpioe);
spi.write_data(&spi1, CTRL_REG1, 0x3F); //power on the gyro
self.cs_high(&gpioe);
self.cs_low(&gpioe);
spi.write_data(&spi1, CTRL_REG4, 0x10); //power on the gyro
self.cs_high(&gpioe);
self
pub fn who_am_i(&self, spi: &spi_mod::spi_func, spi1: &stm32f3::stm32f303::SPI1, gpioe: &stm32f3::stm32f303::GPIOE) -> u8
self.cs_low(&gpioe);
let data = spi.read_register(&spi1, WHO_AM_I);
self.cs_high(&gpioe);
data
pub fn read_temp(&mut self, spi: &spi_mod::spi_func, spi1: &stm32f3::stm32f303::SPI1, gpioe: &stm32f3::stm32f303::GPIOE)
self.cs_low(&gpioe);
self.temp = spi.read_register(&spi1, OUT_TEMP) as i8;
self.cs_high(&gpioe);
pub fn read_data(&mut self, spi: &spi_mod::spi_func, spi1: &stm32f3::stm32f303::SPI1, gpioe: &stm32f3::stm32f303::GPIOE) -> [u8;6]
let mut data: [u8;6] = [0,0,0,0,0,0];
self.cs_low(&gpioe);
spi.read_multiple_register(&spi1, OUT_X_L, &mut data);
// data[0] = spi.read_register(&spi1, OUT_X_L);
// data[1] = spi.read_register(&spi1, OUT_X_H);
// data[2] = spi.read_register(&spi1, OUT_Y_L);
// data[3] = spi.read_register(&spi1, OUT_Y_H);
// data[4] = spi.read_register(&spi1, OUT_Z_L);
// data[5] = spi.read_register(&spi1, OUT_Z_H);
self.cs_high(&gpioe);
self.x = ((data[0] as u16) + ((data[1] as u16) << 8)) as i16;
self.y = ((data[2] as u16) + ((data[3] as u16) << 8)) as i16;
self.z = ((data[4] as u16) + ((data[5] as u16) << 8)) as i16;
data
fn cs_low(&self, gpioe: &stm32f3::stm32f303::GPIOE)
gpioe.odr.modify(|_,w| w.odr3().clear_bit());
fn cs_high(&self, gpioe: &stm32f3::stm32f303::GPIOE)
gpioe.odr.modify(|_,w| w.odr3().set_bit());
这是使用时的结果 sensor.rs -> read_data() -> spi.read_multiple_register(&spi1, OUT_X_L, &mut 数据); return data from board with repeated 3 bytes
当我使用注释掉的位时,这就是我得到的 return data when all bytes are the same
【问题讨论】:
我不知道 Rust。我对您的write()
功能感到怀疑/好奇。 write()
传输多少字节,一个,两个或其中一个?似乎它需要在第一次从read_multiple_register()
调用时传输两个字节,然后在后续调用中传输一个字节。真的会这样吗?
...或等待。我认为write()
从write_register()
或read_register()
调用时需要传输两个字节。但是write()
从read_multiple_register()
调用时需要传输一个字节。也许你不应该在来自read_multiple_register()
的电话中使用那个as u16
。我不知道 Rust。
感谢您的浏览。我想你可能会在那里做一些事情,因为这就是 write_register 函数所发生的事情。当我将数据左移 8 位并再次用 0、1 或数据填充其余字节时,您建议第二个字节是什么,它只是给了我重复的数字。当我在前面也只有一个 0 字节时也是如此。
【参考方案1】:
您是否尝试过在 0x27H 使用 STATUS_REG? Section 3.2 Page 10
【讨论】:
谢谢,我不介意数据是否被覆盖,我觉得这不应该意味着它正在给出它的结果。以上是关于l3gd20 陀螺仪在 stm32f3discovery 上发回重复字节的主要内容,如果未能解决你的问题,请参考以下文章
如何将 stm32f3discovery API 传递给函数?