IIC总线上挂载多个从机的程序实现
文章目錄
- IIC總線上掛載多個(gè)從機(jī)的程序?qū)崿F(xiàn)
- IIC簡(jiǎn)介:
- 1、項(xiàng)目的硬件參考電路:
- 2、程序?qū)崿F(xiàn):
- 2.1、程序框架設(shè)計(jì):
- 2.2 IIC 總線接口程序?qū)崿F(xiàn):
- 2.3 加速度傳感器的配置:
- 2.4 氣壓傳感器的配置,可以仿寫加速度傳感器的實(shí)現(xiàn):
- 2.5氣壓器的處理測(cè)試程序
- 3、重寫IIC的讀寫程序
- 總結(jié):
IIC總線上掛載多個(gè)從機(jī)的程序?qū)崿F(xiàn)
IIC簡(jiǎn)介:
1、I2C總線具有兩根雙向信號(hào)線,一根是數(shù)據(jù)線SDA,另一根是時(shí)鐘線SCL
2、IIC總線上可以掛很多設(shè)備:多個(gè)主設(shè)備,多個(gè)從設(shè)備(外圍 設(shè)備)。
3、多主機(jī)會(huì)產(chǎn)生總線裁決問題。當(dāng)多個(gè)主機(jī)同時(shí)想占用總線時(shí),企圖啟動(dòng)總線傳輸數(shù)據(jù),就叫做總線競(jìng)爭(zhēng)。I2C通過總線仲裁,以決定哪臺(tái)主機(jī)控制總線
在一般的項(xiàng)目中,一般不會(huì)涉及到IIC總線上掛載多主機(jī)多從機(jī)的情況。但掛載單個(gè)主機(jī)多個(gè)從機(jī)的情況還是有的。
在嵌入式領(lǐng)域:要不專注于硬件的設(shè)計(jì),要不專注于軟件的實(shí)現(xiàn)。當(dāng)然最好兩者都兼?zhèn)?。相?duì)來說,軟件層面的復(fù)雜度會(huì)相對(duì)高一點(diǎn),在項(xiàng)目開發(fā)所占的任務(wù)比重也比較大,特別是一些組網(wǎng)的大型項(xiàng)目,往往還會(huì)涉及到上位機(jī)測(cè)試軟件的開發(fā)等。本篇主要講述STM32系列單片機(jī)的IIC掛載多個(gè)從機(jī)的程序?qū)崿F(xiàn)。
1、項(xiàng)目的硬件參考電路:
如上圖,將LIS2HH12加速度傳感器、LPS25HB氣壓傳感器通過IIC總線相連,與STM32Lxx 系列MCU的管腳PB6\PB7 相連。
2、程序?qū)崿F(xiàn):
對(duì)于一個(gè)嵌入式軟件工程師來說,IIC通信的基本知識(shí)需要了解,不過最重要的還是關(guān)心程序如何實(shí)現(xiàn)。
ST公司目前將STM32全系列都是支持HAL庫的開發(fā)。cubeMx軟件可以外設(shè)的驅(qū)動(dòng)程序自動(dòng)生成。但是多說情況下,還是需要手工改寫。要不怎么稱得上嵌入式軟件開發(fā)工程師呢?
一般來說,對(duì)于嵌入式領(lǐng)域的單片機(jī)程序開發(fā),
程序開頭都會(huì)做一些初始化,初始化完成后然后進(jìn)入一個(gè)死循環(huán)while(1),這對(duì)大多數(shù)沒有操作系統(tǒng)的單片機(jī)軟件來說。
我們也不例外,請(qǐng)看下面的程序框架:
2.1、程序框架設(shè)計(jì):
int main(void) {HAL_Init(); SystemClock_Config(); //系統(tǒng)時(shí)鐘初始化MX_I2C1_Init(); //外設(shè)IIC的初始化,PB6\PB7,對(duì)應(yīng)的外設(shè)IIC1/* 看門狗初始化 */MX_IWDG_Init(); HAL_IWDG_Refresh(&hiwdg);/*加速度傳感器的配置*/BSP_ACC_Init(&dev_ctx);BSP_ACC_Config(&dev_ctx);/*氣壓計(jì)的配置及功能實(shí)現(xiàn)*/ BSP_BARO_Init(&dev_baro));BSP_BARO_Config(&dev_baro);while(1){/*加速度傳感器運(yùn)用中斷方式實(shí)現(xiàn),所以while(1)中就出添加加速度的處理程序了*//*氣壓計(jì)的處理程序*/BSP_BARO_handle(&dev_baro);} }2.2 IIC 總線接口程序?qū)崿F(xiàn):
根據(jù)電路圖和傳感器的數(shù)據(jù)手冊(cè),進(jìn)行如下的配置
uint8_t MX_I2C1_Init(void) //加速度、氣壓傳感器SensorIIC接口 {hi2c1.Instance = I2C1;hi2c1.Init.ClockSpeed = 400000; //hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;hi2c1.Init.OwnAddress1 = 0x34; //這里的排至值并不影響。因?yàn)楹竺嫖覀僆IC的讀寫程序不用庫函數(shù),而是重寫IIC的讀寫功能。hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c1.Init.OwnAddress2 = 0;//這里的排至值并不影響。因?yàn)楹竺嫖覀僆IC的讀寫程序不用庫函數(shù),而是重寫IIC的讀寫功能。hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;if (HAL_I2C_Init(&hi2c1) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}if( HAL_I2C_GetState( &hi2c1) == HAL_I2C_STATE_READY ){return 0;}else{return 1;}}2.3 加速度傳感器的配置:
這里我們定義了傳感器對(duì)象的一個(gè)結(jié)構(gòu)體,將此結(jié)構(gòu)體的指針指向兩個(gè)IIC的讀寫程序platform_write、platform_read。應(yīng)為傳感器掛載在IIC1上,這里將傳感器結(jié)構(gòu)體指針的句柄定位為IIC1的地址。
I2C_HandleTypeDef hi2c1; //傳感器的I2C接口 # define SENSOR_BUS hi2c1void BSP_ACC_Init(lis2hh12_ctx_t *dev_acc) {dev_acc->write_reg = platform_write;dev_acc->read_reg = platform_read;dev_acc->handle = &SENSOR_BUS;BSP_ACC_IO_ITConfig(); // 使能ACC MEMS 中斷}//使能加速度傳感器的中斷管腳功能。 void BSP_ACC_IO_ITConfig( void ){/* At the moment this feature is only implemented for LPS22HB */GPIO_InitTypeDef GPIO_InitStructureInt1;/* Enable INT1 GPIO clock */__GPIOA_CLK_ENABLE();/* Configure GPIO PINs to detect Interrupts */GPIO_InitStructureInt1.Pin = GPIO_PIN_0;GPIO_InitStructureInt1.Mode = GPIO_MODE_IT_RISING;GPIO_InitStructureInt1.Speed = GPIO_SPEED_MEDIUM;GPIO_InitStructureInt1.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStructureInt1);/* Enable and set EXTI Interrupt priority */HAL_NVIC_SetPriority(EXTI0_IRQn, 4, 0x00); } /************************************************************************ * 函數(shù)名稱:BSP_ACC_Config(lis2hh12_ctx_t *dev_acc) * 功 能: 加速度配置 * 輸入?yún)?shù):無 * 返 回 值:dev_acc 結(jié)構(gòu)體 * 其 他:無 ************************************************************************/void BSP_ACC_Config(lis2hh12_ctx_t *dev_acc) {/* Check device ID */lis2hh12_dev_id_get(dev_acc, &whoamI);if (whoamI != LIS2HH12_ID){while(1){/* manage here device not found */}}/* Restore default configuration */lis2hh12_dev_reset_set(dev_acc, PROPERTY_ENABLE);do {lis2hh12_dev_reset_get(dev_acc, &rst);} while (rst);/* Enable Block Data Update */lis2hh12_block_data_update_set(dev_acc, PROPERTY_ENABLE);/* Set full scale */ lis2hh12_xl_full_scale_set(dev_acc, LIS2HH12_8g); //在加速度全域范圍內(nèi)運(yùn)行【-8g:8g】/* Configure filtering chain *//* Accelerometer data output- filter path / bandwidth */ lis2hh12_xl_filter_aalias_bandwidth_set(dev_acc, LIS2HH12_AUTO); // 自適應(yīng) bandwidthlis2hh12_xl_filter_out_path_set(dev_acc, LIS2HH12_BYPASSED); // 開啟內(nèi)部低通濾波lis2hh12_xl_filter_low_bandwidth_set(dev_acc, LIS2HH12_LP_ODR_DIV_9); //設(shè)置低通濾波的頻率/* Accelerometer interrrupt - filter path / bandwidth */ lis2hh12_xl_filter_int_path_set(dev_acc, LIS2HH12_HP_DISABLE); //開啟 內(nèi)部高通濾波 /* Set Output Data Rate */lis2hh12_xl_data_rate_set(dev_acc, LIS2HH12_XL_ODR_50Hz); // ODR 設(shè)為100Hz#ifdef FIFO_ACClis2hh12_fifo_mode_set(dev_acc,LIS2HH12_STREAM_MODE); // 設(shè)置 FIFO Modelis2hh12_fifo_watermark_set(dev_acc,PROPERTY_ENABLE); //開啟watermarklis2hh12_pin_int1_route_t pinValue; pinValue.int1_drdy = 0;pinValue.int1_fth = 1;pinValue.int1_inact = 0;pinValue.int1_ig1 = 0;pinValue.int1_ig2 = 0;pinValue.int1_ovr = 0;lis2hh12_pin_int1_route_set(dev_acc,pinValue); //設(shè)置中斷lis2hh12_fifo_watermark_set_level(dev_acc,THRESH_MASK);#endif};加速度傳感器的中斷管腳對(duì)應(yīng)的中斷服務(wù)函數(shù):
在中斷函數(shù)中實(shí)現(xiàn)計(jì)步功能。
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == GPIO_PIN_0) // { ACC_DRY_Flag = SET; lis2hh12_handle(&dev_ctx); } }2.4 氣壓傳感器的配置,可以仿寫加速度傳感器的實(shí)現(xiàn):
void BSP_ACC_Init(lps25hb_ctx_t *dev_ctx) {dev_ctx.write_reg = platform_write;dev_ctx.read_reg = platform_read;dev_ctx.handle = &hi2c1; } void BSP_ACC_Config(lps25hb_ctx_t *dev_ctx) {/* Check device ID */whoamI = 0;lps25hb_device_id_get(&dev_ctx, &whoamI);if ( whoamI != LPS25HB_ID )while(1); /*manage here device not found *//* Restore default configuration */lps25hb_reset_set(&dev_ctx, PROPERTY_ENABLE);do {lps25hb_reset_get(&dev_ctx, &rst);} while (rst);/* Enable Block Data Update */lps25hb_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);/* Set Output Data Rate */lps25hb_data_rate_set(&dev_ctx, LPS25HB_ODR_1Hz); }2.5氣壓器的處理測(cè)試程序
void BSP_BARO_handle(lps25hb_ctx_t *dev_ctx);{while(1){HAL_IWDG_Refresh(&hiwdg);/* Read output only if new value is available */lps25hb_reg_t reg;lps25hb_status_get(&dev_ctx, ®.status_reg); if (reg.status_reg.p_da){memset(data_raw_pressure.u8bit, 0x00, sizeof(int32_t));lps25hb_pressure_raw_get(dev_ctx, data_raw_pressure.u8bit);pressure_hPa = lps25hb_from_lsb_to_hpa( data_raw_pressure.i32bit); } if (reg.status_reg.t_da){memset(data_raw_temperature.u8bit, 0x00, sizeof(int16_t));lps25hb_temperature_raw_get(dev_ctx, data_raw_temperature.u8bit);temperature_degC = lps25hb_from_lsb_to_degc( data_raw_temperature.i16bit);}HAL_Delay(500);} }3、重寫IIC的讀寫程序
以為加速度傳感器的程序?yàn)槔?#xff0c;當(dāng)然氣壓器的IIC讀寫程序可以類似仿寫。
讀寫時(shí)將從機(jī)的地址要寫入
#define LIS2HH12_I2C_ADD_L 0x3DU /** @brief Write generic device register (platform dependent)** @param handle customizable argument. In this examples is used in* order to select the correct sensor bus handler.* @param reg register to write* @param bufp pointer to data to write in register reg* @param len number of consecutive register to write**/ static int32_t platform_write(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len) {if (handle == &hi2c1){HAL_I2C_Mem_Write(handle, LIS2HH12_I2C_ADD_L, reg,I2C_MEMADD_SIZE_8BIT, bufp, len, 1000);}return 0; }/** @brief Read generic device register (platform dependent)** @param handle customizable argument. In this examples is used in* order to select the correct sensor bus handler.* @param reg register to read* @param bufp pointer to buffer that store the data read* @param len number of consecutive register to read**/ static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len) {if (handle == &hi2c1){HAL_I2C_Mem_Read(handle, LIS2HH12_I2C_ADD_L, reg,I2C_MEMADD_SIZE_8BIT, bufp, len, 1000);}return 0; }ok,將代碼燒錄到板子上,測(cè)試成功。debug 可以看到氣壓計(jì)和計(jì)步值都正常輸出了。
總結(jié):
ST的Mems擴(kuò)展板的示例程序上有IIC總結(jié)掛載多個(gè)從機(jī)的Demo,但是移植程序比較困難。因?yàn)樾枰膶懞芏鄡?nèi)容。
這個(gè)示例比較簡(jiǎn)單實(shí)用。當(dāng)然ST官網(wǎng)還提供了很多示例,根據(jù)實(shí)際項(xiàng)目需要可以添加需要的傳感器功能。
總結(jié)
以上是生活随笔為你收集整理的IIC总线上挂载多个从机的程序实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于 ST mems传感器开发的一些技术
- 下一篇: LPS25HB 气压计 的嵌入式程序开发