文章目录

  • IIC总线上挂载多个从机的程序实现
    • IIC简介:
    • 1、项目的硬件参考电路:
    • 2、程序实现:
    • 2.1、程序框架设计:
    • 2.2 IIC 总线接口程序实现:
    • 2.3 加速度传感器的配置:
    • 2.4 气压传感器的配置,可以仿写加速度传感器的实现:
    • 2.5气压器的处理测试程序
    • 3、重写IIC的读写程序
    • 总结:

IIC总线上挂载多个从机的程序实现

IIC简介:

1、I2C总线具有两根双向信号线,一根是数据线SDA,另一根是时钟线SCL

2、IIC总线上可以挂很多设备:多个主设备,多个从设备(外围 设备)。

3、多主机会产生总线裁决问题。当多个主机同时想占用总线时,企图启动总线传输数据,就叫做总线竞争。I2C通过总线仲裁,以决定哪台主机控制总线

在一般的项目中,一般不会涉及到IIC总线上挂载多主机多从机的情况。但挂载单个主机多个从机的情况还是有的。

在嵌入式领域:要不专注于硬件的设计,要不专注于软件的实现。当然最好两者都兼备。相对来说,软件层面的复杂度会相对高一点,在项目开发所占的任务比重也比较大,特别是一些组网的大型项目,往往还会涉及到上位机测试软件的开发等。本篇主要讲述STM32系列单片机的IIC挂载多个从机的程序实现。

1、项目的硬件参考电路:

如上图,将LIS2HH12加速度传感器、LPS25HB气压传感器通过IIC总线相连,与STM32Lxx 系列MCU的管脚PB6\PB7 相连。

2、程序实现:

对于一个嵌入式软件工程师来说,IIC通信的基本知识需要了解,不过最重要的还是关心程序如何实现。

ST公司目前将STM32全系列都是支持HAL库的开发。cubeMx软件可以外设的驱动程序自动生成。但是多说情况下,还是需要手工改写。要不怎么称得上嵌入式软件开发工程师呢?

一般来说,对于嵌入式领域的单片机程序开发,
程序开头都会做一些初始化,初始化完成后然后进入一个死循环while(1),这对大多数没有操作系统的单片机软件来说。
我们也不例外,请看下面的程序框架:

2.1、程序框架设计:

int main(void)
{HAL_Init();        SystemClock_Config();     //系统时钟初始化MX_I2C1_Init();                 //外设IIC的初始化,PB6\PB7,对应的外设IIC1/* 看门狗初始化 */MX_IWDG_Init();   HAL_IWDG_Refresh(&hiwdg);/*加速度传感器的配置*/BSP_ACC_Init(&dev_ctx);BSP_ACC_Config(&dev_ctx);/*气压计的配置及功能实现*/   BSP_BARO_Init(&dev_baro));BSP_BARO_Config(&dev_baro);while(1){/*加速度传感器运用中断方式实现,所以while(1)中就出添加加速度的处理程序了*//*气压计的处理程序*/BSP_BARO_handle(&dev_baro);}
}

2.2 IIC 总线接口程序实现:

根据电路图和传感器的数据手册,进行如下的配置

uint8_t MX_I2C1_Init(void)  //加速度、气压传感器SensorIIC接口
{hi2c1.Instance = I2C1;hi2c1.Init.ClockSpeed = 400000;  //hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;hi2c1.Init.OwnAddress1 = 0x34;  //这里的排至值并不影响。因为后面我们IIC的读写程序不用库函数,而是重写IIC的读写功能。hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c1.Init.OwnAddress2 = 0;//这里的排至值并不影响。因为后面我们IIC的读写程序不用库函数,而是重写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 加速度传感器的配置:

这里我们定义了传感器对象的一个结构体,将此结构体的指针指向两个IIC的读写程序platform_write、platform_read。应为传感器挂载在IIC1上,这里将传感器结构体指针的句柄定位为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);   }
/************************************************************************
* 函数名称:BSP_ACC_Config(lis2hh12_ctx_t *dev_acc)
* 功    能: 加速度配置
* 输入参数:无
* 返 回 值:dev_acc 结构体
* 其    他:无
************************************************************************/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);                                       //在加速度全域范围内运行【-8g:8g】/* Configure filtering chain *//* Accelerometer data output- filter path / bandwidth */  lis2hh12_xl_filter_aalias_bandwidth_set(dev_acc, LIS2HH12_AUTO);                   // 自适应 bandwidthlis2hh12_xl_filter_out_path_set(dev_acc, LIS2HH12_BYPASSED);                              // 开启内部低通滤波lis2hh12_xl_filter_low_bandwidth_set(dev_acc, LIS2HH12_LP_ODR_DIV_9);              //设置低通滤波的频率/* Accelerometer interrrupt - filter path / bandwidth */ lis2hh12_xl_filter_int_path_set(dev_acc, LIS2HH12_HP_DISABLE);              //开启 内部高通滤波 /* Set Output Data Rate */lis2hh12_xl_data_rate_set(dev_acc, LIS2HH12_XL_ODR_50Hz);                            // ODR 设为100Hz#ifdef  FIFO_ACClis2hh12_fifo_mode_set(dev_acc,LIS2HH12_STREAM_MODE);                                    // 设置 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);                             //设置中断lis2hh12_fifo_watermark_set_level(dev_acc,THRESH_MASK);#endif};

加速度传感器的中断管脚对应的中断服务函数:

在中断函数中实现计步功能。

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 气压传感器的配置,可以仿写加速度传感器的实现:

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气压器的处理测试程序

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, &reg.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的读写程序

以为加速度传感器的程序为例,当然气压器的IIC读写程序可以类似仿写。

读写时将从机的地址要写入


#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,将代码烧录到板子上,测试成功。debug 可以看到气压计和计步值都正常输出了。

总结:

ST的Mems扩展板的示例程序上有IIC总结挂载多个从机的Demo,但是移植程序比较困难。因为需要改写很多内容。

这个示例比较简单实用。当然ST官网还提供了很多示例,根据实际项目需要可以添加需要的传感器功能。

IIC总线上挂载多个从机的程序实现相关推荐

  1. 1-Wire总线上挂载多个DS18B20温度传感器驱动程序

    问题背景 DS18B20 是一款温度传感器,单片机可以通过 1-Wire 协议与 DS18B20 进行通信,最终将温度读出.1-Wire 总线的硬件接口很简单,只需要把 DS18B20 的数据引脚和单 ...

  2. IIC总线协议基本原理以及GPIO虚拟IIC接口

    IIC 一般应用于芯片之间的通信,是半双工串行同步通信总线,它的传输距离短,但其好处是 IIC 支持一主多从的挂载方式,因此主机和多个从机之间的通信线只要两条就够了, IIC硬件结构: IIC 串行总 ...

  3. Chapter007-FPGA学习之IIC总线EEPROM读取

    IIC总线是嵌入式领域较为重要的器件间通信总线,同样,FPGA也能通过模块的形式实现IIC的功能,其原理和STM32的模拟IIC总线一致,就是控制每个时间点的SCL.SDA总线电平. IIC总线需要对 ...

  4. iic总线从机仲裁_IIC协议底层原理超详细解析!示波器,逻辑分析仪多图预警

    1. 协议基础 1.1.     协议简介 IIC-BUS(Inter-IntegratedCircuit Bus)最早是由PHilip半导体(现在被NXP收购)于1982年开发.主要是用来方便微控制 ...

  5. STM32使用IIC总线通讯协议在OLED屏幕上显示字符串、汉字、图像(硬件IIC)

    参考:基于STM32-Oled(IIC)的使用 作者:奋斗的小殷 发布时间: 2021-05-07 13:09:26 网址:https://blog.csdn.net/boybs/article/de ...

  6. IIC(I2C)总线上的设备其地址如何定义?通俗易懂

    IIC(I2C)总线上的设备其地址如何定义? IIC总线 一般串行数据通讯都有时钟和数据之分,有异步和同步之别. 有单线,双线和三线等. I2C肯定是2线的(不算地线). I2C协议确实很科学,比3/ ...

  7. Linux底层IIC 总线的理解、调用函数以及常见面试问题

    对 IIC 总线的理解.调用函数以及常见面试问题 一.IIC 总线概述: IIC 即Inter-Integrated Circuit(集成电路总线) I2C总线是PHLIPS公司推出的一种串行总线, ...

  8. 对 IIC 总线的理解、调用函数以及常见面试问题

    一.IIC 总线概述: IIC 即Inter-Integrated Circuit(集成电路总线) I2C总线是PHLIPS公司推出的一种串行总线, I2C总线只有两根双向信号线.一根是数据线SDA, ...

  9. # 浅谈IIC总线通讯协议

    浅谈IIC总线通讯协议 相关概念 IIC总线是PHLIPS公司在八十年代初推出的一种同步串行的半双工总线,支持多主机多从机,具备总线裁决功能,用于连接整体电路. 整体电路:同一块板子上,两个芯片之间的 ...

最新文章

  1. 根据ip获取用户地址-百度
  2. catia 桥接曲面圆角_4.3.7.1-Catia曲面之多桥接曲面_简单构面
  3. MATLAB:图像的与、或、非、异或逻辑运算(、|、~、xor)
  4. 设计模式(一):工厂方法
  5. 【jQuery学习】—jQuery对象的过滤
  6. BayaiM__oracle切换归档模式步骤:
  7. Mongodb-副本集
  8. 构建自己的PHP框架(MVC)
  9. 【车间调度】基于matlab NSGA-2算法求解多目标车间调度问题【含Matlab源码 893期】
  10. 数据挖掘领头人韩家炜教授:如何从无结构文本到有用的知识?
  11. WPF界面样式学习及优化
  12. cognex扫码枪识别内容直接_康耐视cognex DataMan8600系列-手持终端-条码扫描枪-PDA-扫描模块-条码打印机-苏州奥维尔...
  13. 面试算法 香槟塔 ,算法:暴力算法
  14. Grown Up Digital: How the Net Generation is Changing Your World
  15. think in google--think in 互联网系列2
  16. 微信可以设置雪花昵称了,真漂亮!
  17. Payoneer(P卡)怎么免费申请Joom账号?
  18. 中国石油大学(北京)-《外国文学作品选读》在线考试
  19. Pycharm 2018.2.1最新版破解到2099年图解教程
  20. ssh 修改超时时间

热门文章

  1. LIBRARY_PATH和LD_LIBRARY_PATH环境变量的区别
  2. 一个可以在github上搜代码段的网站
  3. list::splice函数的用法与参数解释
  4. 【笔记】基于 Mask R-CNN 的玉米田间杂草检测方法
  5. [云炬创业管理笔记]第三章测试5
  6. 科大星云诗社动态20210210
  7. 科大星云诗社动态20210416
  8. [2DPIC调试笔记]parameter_antenna_radiation1013(3)
  9. 面绘制经典算法:MarchingCube实现(控制台篇)
  10. C++返回字符串函数的几种实现方法