由于 RT-Thread 穩定高效的內核,豐富的文檔教程,積極活躍的社區氛圍,以及設備驅動框架、Kconfig、Scons、日志系統、海量的軟件包……很難不選擇 RT-Thread 進行項目開發。但也正是因為這些優點的覆蓋面較廣,很多初學者會覺得無從下手,但只要步入 RT-Thread 的大門,你就發現她的美好。這系列文檔將作為本人基于 RT-Thread 開發 RoboMaster 電控框架的記錄與分享,希望能幫助到更多初識 RT-Thread 的小伙伴,也歡迎大家交流分享,指正不足,共同進步。
背景
使用的開發板為大疆的 RoboMaster-C 型開發板,基礎工程為 rt-thread>bsp>stm32f407-robomaster-c
ist8310磁力計模塊開發
ist8310 為 robomaster-c 開發板上集成的三軸磁力計,使用 I2C 通訊
添加 I2C 讀寫 API
首先將飛控程序中針對 RT-Thread 的 I2C 設備驅動封裝的 I2C 讀寫函數借鑒過來:
rt_err_t i2c_read_reg(struct rt_i2c_bus_device bus, uint16_t slave_addr, uint8_t reg, uint8_t buffer)
{
rt_size_t ret;
struct rt_i2c_msg msgs[2];
msgs[0].addr = slave_addr;
msgs[0].flags = RT_I2C_WR | bus->flags;
msgs[0].buf = ?
msgs[0].len = 1;
msgs[1].addr = slave_addr;
msgs[1].flags = RT_I2C_RD | bus->flags;
msgs[1].buf = buffer;
msgs[1].len = 1;
ret = rt_i2c_transfer(bus, msgs, 2);
return ret == 2 ? RT_EOK : RT_ERROR;
}
rt_err_t i2c_write_reg(struct rt_i2c_bus_device *bus, uint16_t slave_addr, uint8_t reg, uint8_t val)
{
rt_size_t ret;
rt_uint8_t buffer[2];
struct rt_i2c_msg msgs;
buffer[0] = reg;
buffer[1] = val;
msgs.addr = slave_addr;
msgs.flags = RT_I2C_WR | bus->flags;
msgs.buf = buffer;
msgs.len = 2;
ret = rt_i2c_transfer(bus, &msgs, 1);
return ret == 1 ? RT_EOK : RT_ERROR;
}
rt_err_t i2c_read_regs(struct rt_i2c_bus_device bus, uint16_t slave_addr, uint8_t reg, uint8_t buffer, uint16_t count)
{
rt_size_t ret;
struct rt_i2c_msg msgs[2];
msgs[0].addr = slave_addr;
msgs[0].flags = RT_I2C_WR | bus->flags;
msgs[0].buf = ?
msgs[0].len = 1;
msgs[1].addr = slave_addr;
msgs[1].flags = RT_I2C_RD | bus->flags;
msgs[1].buf = buffer;
msgs[1].len = count;
ret = rt_i2c_transfer(bus, msgs, 2);
return ret == 2 ? RT_EOK : RT_ERROR;
}
rt_err_t i2c_write_regs(struct rt_i2c_bus_device bus, uint16_t slave_addr, uint8_t reg, uint8_t vals, uint16_t count)
{
rt_size_t ret;
struct rt_i2c_msg msgs[2];
msgs[0].addr = slave_addr;
msgs[0].flags = RT_I2C_WR | bus->flags;
msgs[0].buf = ?
msgs[0].len = 1;
msgs[1].addr = slave_addr;
msgs[1].flags = RT_I2C_WR | bus->flags;
msgs[1].buf = vals;
msgs[1].len = count;
ret = rt_i2c_transfer(bus, msgs, 2);
return ret == 2 ? RT_EOK : RT_ERROR;
}
BSP 中 STM32 I2C 設備驅動使用的是軟件 I2C,于是進入到 menuconfig 中對 I2C 引腳進行配置:
/* Notice: PA8 --> 8; PC9 --> 41 */
#define BSP_I2C1_SCL_PIN 8
#define BSP_I2C1_SDA_PIN 41
IST8310 驅動
主要就是先對 IST8310 進行初始化,設置相關采樣參數,之后就可以讀取磁力計的信息了
static rt_err_t mag_raw_measure(int16_t mag[3])
{
uint8_t buffer[6];
i2c_read_regs(i2c_bus, IST8310_ADDRESS, REG_DATA_OUT_X_L, buffer, sizeof(buffer));
/* swap the data /
mag[0] = ((int16_t)buffer[1] << 8) | (int16_t)buffer[0];
mag[1] = ((int16_t)buffer[3] << 8) | (int16_t)buffer[2];
mag[2] = ((int16_t)buffer[5] << 8) | (int16_t)buffer[4];
/ start next measurement /
// i2c_write_reg(i2c_bus, IST8310_ADDRESS, REG_CTRL1, CTRL1_ODR_SINGLE));
return RT_EOK;
}
static rt_err_t mag_measure(float mag[3])
{
int16_t raw[3];
mag_raw_measure(raw);
mag[0] = _range_scale * raw[0];
mag[1] = _range_scale * raw[1];
mag[2] = _range_scale * raw[2];
ist8310_rotate_to_frd(mag);
if (ist8310_user_calibrate != RT_NULL) {
/ do user defined calibration */
ist8310_user_calibrate(mag);
}
return RT_EOK;
}
其中 ist8310_user_calibrate 和 ist8310_rotate_to_frd 為預留的虛函數,用戶可根據校準及轉化需求,自行定義實現。
attribute ((weak)) void ist8310_user_calibrate(float data[3]);
/* Re-implement this function to define customized rotation /
attribute ((weak)) void ist8310_rotate_to_frd(float data);
抽象設備
為提高程序的模塊化,選用不同傳感器時的靈活性,將 ist8310 抽象為 mag 一類設備,抽象出 mag_init 和 mag_read 兩個操作方法。
struct mag_ops{
rt_err_t (mag_init)(const char i2c_bus_name);
rt_err_t (*mag_read)(float data[3]);
};
項目選用不同的磁力計傳感器時,對接這兩個接口即可,以 ist8310 為例:
/**
@brief 調用此函數初始化 ist8310
@param i2c_bus_name ist8310 所掛載的總線名稱
@return RT_EOK
/
static rt_err_t drv_ist8310_init(const char i2c_bus_name);
/**
@brief 調用此函數讀取 ist8310 數據
@param data[3] 存儲讀取數據的數組
@return 讀取成功 RT_EOK ; 讀取失敗 -RT_ERROR
*/
static rt_err_t ist8310_read(float data[3]);
struct mag_ops mag = {
.mag_init = drv_ist8310_init,
.mag_read = ist8310_read,
};
應用層需要使用磁力計時,調用 mag_ops 中的操作方法即可:
static float read_data[3];
mag.mag_init("i2c1"); // 初始化 mag 設備
mag.mag_read(read_data); // 將設備數據讀取到 read_data 中
到此就可以方便的使用磁力計模塊啦
存在問題及優化方向
目前為了提高性能,mag設備的注冊對接形式是比較簡陋的。
后續考慮能不能也優化為,read,write,control 等形式。
-
傳感器
+關注
關注
2552文章
51382瀏覽量
755774 -
STM32
+關注
關注
2270文章
10923瀏覽量
357076 -
I2C通信
+關注
關注
0文章
22瀏覽量
8892 -
三軸磁力計
+關注
關注
0文章
7瀏覽量
8409 -
RT-Thread
+關注
關注
31文章
1305瀏覽量
40310
發布評論請先 登錄
相關推薦
評論