【FR8016外设模拟I2C应用】BLE心率监测-程序员宅基地

技术标签: 蓝牙  


  本次测评fr8016的模拟i2c外设和蓝牙功能,通过芯片的IO口模拟I2C通信时序与心率模块max30102通信,采集人体心率,将结果通过BLE上传给安卓手机显示。运用到SDK的内容有

  • BLE协议栈GATT、GAP
  • IO模拟I2C
  • 系统定时任务CLOCK
  • 操作系统抽象层OSAL

  下面将逐一介绍,从max30102驱动开始,最终实现心率数据向安卓手机上传,完成一个BLE应用。

一、FR8016资源与SDK架构

1.1 FR8016资源

在这里插入图片描述

  • FLASH Cache RAM:这是一个8KB的数据RAM,主要由缓存控制器使用。缓存控制器直接从外部QSPI FLASH执行,从而减少对FLASH的访问。
  • UART:异步串行接口,具有32字节深度的FIFO,波特率从4800到921600不等。
  • SPI:串行外设接口,具有128字节深度和8位宽度的FIFO。最大总线频率为24MHz。
  • I2C:这是用于传感器和/或主机MCU通信的主I2C接口。它包括一个8位宽、8字节深的RX FIFO和一个8位宽、10字节深的TX FIFO。最大总线频率为2MHz。
  • QSPI Controller:与Quad SPI Flash设备的接口,最大总线频率为24MHz
  • SARADC:差分逐次逼近寄存器模数转换器。它支持多达8个外部模拟输入通道,10位宽度和1MHz采样率。
  • RADIO Transciver:此模块实现2.4GHz的蓝牙低能量协议的射频部分。
  • clock generator:此块负责系统的计时。它包含一个24MHz晶体振荡器,用于系统的有源模式。还有一个62.5 kHz振荡器(RC62.5K),精度(<300 ppm)。RCX振荡器可用作休眠时钟,以提高功耗,同时减少系统的物料清单。
  • timer:2个独立的16位计数器计时器.
  • PWM:PWM模块电路实现脉宽调制波输出。6通道数字PWM输出模块,超高达(1/48M)分辨率。另外还有另一个3通道PMU PWM输出模块,具有1/(PMU系统clk)分辨率。
  • Keyboard scanner: 该电路实现了对键盘矩阵的扫描和去抖动,并在不需要CPU的情况下对可配置的动作产生中断。
  • AHB/APB bus:执行AHB和APB规范的AMBA Lite版本。
  • I2S和PDM端口:该部分通过脉冲密度调制(PDM)和IC间声音(I2S)接口实现音频流。它支持使用PDM接口和内部编解码器块的数字麦克风、模拟麦克风和单声道扬声器.I2S接口具有64 16位宽度FIFO深度、最大24MHz总线速度和16 kHz/8kHz、16位采样率。PDM接口具有64个16位宽度FIFO深度、1MHz/2MHz总线速度和16 kHz/8kHz、16位采样率。
  • audio codec:它由1路16位∑ΔADC和1路16位∑ΔDAC组成,采样率高达48kHz。内部麦克风偏置等于0.9*编解码器电源电压,输入PGA放大器-17.25dB-30dB增益范围,输出耳机PA,音频编解码器块内输出功率高达50mW。
  • 电源管理。一个复杂的电源管理电路,带有降压型DC-DC转换器和几个LDO,可通过PMU模块打开/关闭。即使FR801xH处于睡眠/深度睡眠模式,也会提供额外的引脚为外部设备供电.它还包括用于蓄电池充电的恒流/恒压(CCCV)充电器和充电状态燃油表电路。CCCV充电器电流从48mA到258mA不等。
    该模块还包括一个LDO输出,最大驱动能力为125mA,输出电压范围为1.8~3.5V。引脚垫驱动能力为12mA。所有焊盘的总驱动能力等于LDO输出驱动能力,即125mA。

1.2 SDK架构

  FR801xH SDK 的架构如下图所示。 SDK 包含了完整的 BLE 5.0 协议栈, 包括完整的 controller, host, profile, SIG Mesh部分。 其中蓝牙协议栈的 controller 和 host 部分以及操作系统抽象层 OSAL 都是以库的形式提供, 图中为灰色部分。 MCU 外设驱动和 profile, 以及应用层的例程代码, 都是以源码的形式提供, 图中为绿色部分。
在这里插入图片描述

二、心率芯片max30102通信协议及驱动编程

2.1 max30102介绍

2.1.1 功能图

在这里插入图片描述

2.1.2 详细说明

  MAX30102是一个完整的脉搏血氧饱和度和心率传感器系统解决方案模块,专为可穿戴设备的苛刻要求而设计。该设备在不牺牲光学或电学性能的情况下保持非常小的解决方案尺寸。集成到可穿戴系统中需要最少的外部硬件组件。
  MAX30102通过软件寄存器完全可调,数字输出数据可存储在IC内的32深FIFO中。FIFO允许MAX30102连接到共享总线上的微控制器或处理器,在共享总线上数据不是从MAX30102的寄存器连续读取的。

2.1.3 血氧饱和度子系统

  MAX30102的SpO2子系统包含环境光消除(ALC)、连续时间sigma-delta ADC和专有的离散时间滤波器。自动高度控制有一个内部跟踪/保持电路,以消除环境光并增加有效动态范围。SpO2 ADC的可编程满标度范围为2µA至16µA。ALC可抵消高达200µA的环境电流。
  内部ADC是一个具有18位分辨率的连续时间过采样sigma-delta转换器。ADC采样率为10.24MHz。ADC输出数据速率可从50sps(每秒采样数)编程到3200sps。

2.1.4 温度传感器

  MAX30102有一个片上温度传感器,用于校准SpO2子系统的温度依赖性。温度传感器的固有分辨率为0.0625°C。
  设备输出数据对红外LED的波长相对不敏感,其中红色LED的波长对于正确解释数据至关重要。与MAX30102输出信号一起使用的SpO2算法可以补偿与环境温度变化相关的SpO2误差。

2.1.5 LED驱动器

  MAX30102集成了红色和红外LED驱动器,用于调制用于SpO2和HR测量的LED脉冲。在适当的电源电压下,LED电流可编程设定在0到50mA之间。LED脉冲宽度可从69µs编程到411µs,以允许算法根据用例优化SpO2和HR精度以及功耗。

2.1.6 接近功能

  当用户的手指不在传感器上时,该装置包括接近功能以节省功率并减少可见光发射。当SpO2或HR功能启动时(通过写入模式寄存器),IR LED在接近模式下激活,驱动电流由PILOT PA寄存器设置。当通过超过IR ADC计数阈值(在PROX\u INT\u THRESH寄存器中设置)检测到物体时,部件自动转换到正常SpO2/HR模式。要重新进入接近模式,必须重写模式寄存器(即使值相同)。
  可通过将接近功能重置为0来禁用接近功能。在这种情况下,血氧饱和度或心率模式立即开始。

2.2 i2c通信协议

2.2.1 从FIFO读取

  通常,从I2C接口读取寄存器会自动递增寄存器地址指针,这样所有寄存器都可以在无I2C启动事件的突发读取中读取。在MAX30102中,这适用于除FIFO数据寄存器(寄存器0x07)以外的所有寄存器。
  读取FIFO\数据寄存器不会自动增加寄存器地址。突发读取该寄存器从同一地址反复读取数据。每个样本都包含多个字节的数据,因此应从该寄存器(在同一事务中)读取多个字节以获得一个完整的样本。
  另一个例外是0xFF。在0xFF寄存器之后读取更多字节不会使地址指针返回0x00,读取的数据也没有意义。

2.2.2 FIFO数据结构

  数据FIFO由一个32采样内存组组成,它可以存储IR和Red ADC数据。由于每个样本由两个数据通道组成,因此每个样本有6个字节的数据,因此FIFO中可以存储总共192个字节的数据。
  FIFO数据左对齐,如表1所示;换句话说,无论ADC分辨率设置如何,MSB位始终位于位17数据位置。FIFO数据结构的直观表示见表2。
表1。FIFO数据左对齐
在这里插入图片描述

2.2.3FIFO数据每个通道包含3个字节

  FIFO数据左对齐,这意味着无论ADC分辨率设置如何,MSB始终位于同一位置。未使用FIFO数据[18]–[23]。表2显示了每个三元组字节的结构(包含每个通道的18位ADC数据输出)。
  SpO2模式下的每个数据样本包含两个数据三元组(每个三元组3个字节),要读取一个样本,每个字节需要一个I2C读取命令。因此,要在SpO2模式下读取一个样本,需要读取6个I2C字节。读取每个样本的第一个字节后,FIFO读取指针将自动递增。

2.2.4 写/读指针

  写/读指针用于控制FIFO中的数据流。每次向FIFO添加新样本时,写入指针都会递增。每次从FIFO读取样本时,读取指针都会递增。要从FIFO中重新读取样本,将其值减一,然后再次读取数据寄存器。
  在进入SpO2模式或HR模式时,应清除FIFO写/读指针(返回0x00),以便在FIFO中没有表示的旧数据。如果VDD通电或VDD低于其UVLO电压,指针将自动清除。
表2。FIFO数据(每个通道3字节)
在这里插入图片描述
在这里插入图片描述

2.3 驱动编程

2.3.1 从FIFO读取数据的伪代码示例

第一个事务:获取FIFO_WR_PTR:
START;
Send device address + write mode
Send address of FIFO_WR_PTR;
REPEATED_START;
Send device address + read mode
Read FIFO_WR_PTR;
STOP;
中央处理器评估要从FIFO读取的样本数:
NUM_AVAILABLE_SAMPLES = FIFO_WR_PTR – FIFO_RD_PTR
(Note: pointer wrap around should be taken into account)
NUM_SAMPLES_TO_READ = < less than or equal to NUM_AVAILABLE_SAMPLES >
第二个事务:从FIFO读取样本数:
START;
Send device address + write mode
Send address of FIFO_DATA;
REPEATED_START;
Send device address + read mode
for (i = 0; i < NUM_SAMPLES_TO_READ; i++) {
Read FIFO_DATA;
Save LED1[23:16];
Read FIFO_DATA;
Save LED1[15:8];
Read FIFO_DATA;
Save LED1[7:0];
Read FIFO_DATA;
Save LED2[23:16];
Read FIFO_DATA;
Save LED2[15:8];
Read FIFO_DATA;
Save LED2[7:0];
Read FIFO_DATA;
}
STOP;
START;
Send device address + write mode
Send address of FIFO_RD_PTR;
Write FIFO_RD_PTR;
STOP;
第三个事务:写入FIFO_RD_PTR寄存器。如果第二个事务成功,则FIFO_RD_PTR指向FIFO中的下一个样本,而第三个事务不是必需的。否则,处理器会适当地更新FIFO_RD_PTR,以便重新读取样本。

2.3.2 编程实现

  这里以读取数据的FIFO为例子,介绍fr8016读取max30102的fifo。

int8_t maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
/**
* \brief        Read a set of samples from the MAX30102 FIFO register
* \par          Details
*               This function reads a set of samples from the MAX30102 FIFO register
*
* \param[out]   *pun_red_led   - pointer that stores the red LED reading data
* \param[out]   *pun_ir_led    - pointer that stores the IR LED reading data
*
* \retval       true on success
*/
{
    
    uint32_t un_temp;
    unsigned char uch_temp;
    char ach_i2c_data[6];
    uint8_t Ack1,Ack2,Ack3;//,Ack4;
    *pun_red_led=0;
    *pun_ir_led=0;
    //read and clear status register
    maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
    maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
    ach_i2c_data[0]=REG_FIFO_DATA;
    sensirion_i2c_start();
    Ack1 = sensirion_i2c_write_byte(I2C_WRITE_ADDR);	//发送设备写地址
    Ack2 = sensirion_i2c_write_byte(ach_i2c_data[0]);	//发送寄存器地址
    sensirion_i2c_start();
    Ack3 = sensirion_i2c_write_byte(I2C_READ_ADDR);	//发送设备读地址
    //un_temp=(unsigned char) ach_i2c_data[0];
    un_temp = sensirion_i2c_read_byte(1);//读取
    un_temp<<=16;
    *pun_red_led+=un_temp;
    //un_temp=(unsigned char) ach_i2c_data[1];
    un_temp = sensirion_i2c_read_byte(1);//读取
    un_temp<<=8;
    *pun_red_led+=un_temp;
    //un_temp=(unsigned char) ach_i2c_data[2];
    un_temp = sensirion_i2c_read_byte(1);//读取
    *pun_red_led+=un_temp;
// un_temp=(unsigned char) ach_i2c_data[3];
    un_temp = sensirion_i2c_read_byte(1);//读取
    un_temp<<=16;
    *pun_ir_led+=un_temp;
    //un_temp=(unsigned char) ach_i2c_data[4];
    un_temp = sensirion_i2c_read_byte(1);//读取
    un_temp<<=8;
    *pun_ir_led+=un_temp;
    //un_temp=(unsigned char) ach_i2c_data[5];
    un_temp = sensirion_i2c_read_byte(0);//读取
    sensirion_i2c_stop();//产生停止
    *pun_ir_led+=un_temp;
    *pun_red_led&=0x03FFFF;  //Mask MSB [23:18]
    *pun_ir_led&=0x03FFFF;  //Mask MSB [23:18]
    if(Ack1 || Ack2 || Ack3)//如果
        return -1; //发送失败
    else
        return 0; //发送成功
}

  上面需要使用到FR8016的SDK的模拟I2C函数,比如i2c起始,i2c读写一个字节。

#define DELAY_USECC (SENSIRION_I2C_CLOCK_PERIOD_USEC / 2)

static uint8_t sensirion_wait_while_clock_stretching(void) {
    
    uint8_t timeout = 100;

    while (--timeout) {
    
		//co_printf("timeout= %d\r\n",timeout);
        if (sensirion_SCL_read())
            return STATUS_OK;
        sensirion_sleep_usec(DELAY_USECC);
    }

    return STATUS_FAIL;
}

static int8_t sensirion_i2c_write_byte(uint8_t data) {
    
    int8_t nack, i;
    for (i = 7; i >= 0; i--) {
    
        sensirion_SCL_out();
        if ((data >> i) & 0x01)
            sensirion_SDA_in();
        else
            sensirion_SDA_out();
        sensirion_sleep_usec(DELAY_USECC);
        sensirion_SCL_in();
        sensirion_sleep_usec(DELAY_USECC);
        if (sensirion_wait_while_clock_stretching())
            return STATUS_FAIL;
    }
    sensirion_SCL_out();
    sensirion_SDA_in();
    sensirion_sleep_usec(DELAY_USECC);
    sensirion_SCL_in();
    if (sensirion_wait_while_clock_stretching())
        return STATUS_FAIL;
//	printf("sensirion_i2c_write_byte\r\n************");
    nack = (sensirion_SDA_read() != 0);//判断ACK    
    sensirion_SCL_out();
//printf("nack =%d\r\n",nack);
    return nack;
}

static uint8_t sensirion_i2c_read_byte(uint8_t ack) {
    
    int8_t i;
    uint8_t data = 0;
    sensirion_SDA_in();
    for (i = 7; i >= 0; i--) {
    
        sensirion_sleep_usec(DELAY_USECC);
        sensirion_SCL_in();
        if (sensirion_wait_while_clock_stretching())
            return STATUS_FAIL;
        data |= (sensirion_SDA_read() != 0) << i;
        sensirion_SCL_out();
    }
    if (ack)
        sensirion_SDA_out();
    else
        sensirion_SDA_in();
    sensirion_sleep_usec(DELAY_USECC);
    sensirion_SCL_in();
    sensirion_sleep_usec(DELAY_USECC);
    if (sensirion_wait_while_clock_stretching())
        return STATUS_FAIL;
    sensirion_SCL_out();
    sensirion_SDA_in();

    return data;
}

static uint8_t sensirion_i2c_start(void) {
    
    sensirion_SCL_in();
    if (sensirion_wait_while_clock_stretching())
        return STATUS_FAIL;

    sensirion_SDA_out();
    sensirion_sleep_usec(DELAY_USECC);
    sensirion_SCL_out();
    sensirion_sleep_usec(DELAY_USECC);
    return STATUS_OK;
}

static void sensirion_i2c_stop(void) {
    
    sensirion_SDA_out();
    sensirion_sleep_usec(DELAY_USECC);
    sensirion_SCL_in();
    sensirion_sleep_usec(DELAY_USECC);
    sensirion_SDA_in();
    sensirion_sleep_usec(DELAY_USECC);
}

三、【SDK组件一】蓝牙协议栈GATT和GAP编程

  SDK 里面包含了完整的协议栈, 虽然 controller 和 host 部分是以库的形式提供, 但给出了接口丰富的 API 提供给上层应用开发调用。 Profile 则是以源码的形式提供。
GAP操作如下:

/*********************************************************************
 * @fn      simple_peripheral_init
 *
 * @brief   Initialize simple peripheral profile, BLE related parameters.
 *
 * @param   None. 
 *       
 *
 * @return  None.
 */
void simple_peripheral_init(void)
{
    
    // set local device name
	uint8_t local_name[] = "Simple Peripheral";
	gap_set_dev_name(local_name, sizeof(local_name));

	// Initialize security related settings.
	gap_security_param_t param =
	{
    
	    .mitm = false,
	    .ble_secure_conn = false,
	    .io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT,
	    .pair_init_mode = GAP_PAIRING_MODE_WAIT_FOR_REQ,
	    .bond_auth = true,
	    .password = 0,
	};

	gap_security_param_init(&param);

	gap_set_cb_func(app_gap_evt_cb);

	gap_bond_manager_init(BLE_BONDING_INFO_SAVE_ADDR, BLE_REMOTE_SERVICE_SAVE_ADDR, 8, true);
	gap_bond_manager_delete_all();

	mac_addr_t addr;
	gap_address_get(&addr);
	co_printf("Local BDADDR: 0x%2X%2X%2X%2X%2X%2X\r\n", addr.addr[0], addr.addr[1], addr.addr[2], addr.addr[3], addr.addr[4], addr.addr[5]);

	// Adding services to database
    sp_gatt_add_service();
	speaker_gatt_add_service();				    //创建Speaker profile,
    
	//按键初始化 PD6 PC5
	pmu_set_pin_pull(GPIO_PORT_D, (1<<GPIO_BIT_6), true);
	pmu_set_pin_pull(GPIO_PORT_C, (1<<GPIO_BIT_5), true);
	pmu_port_wakeup_func_set(GPIO_PD6|GPIO_PC5);
	button_init(GPIO_PD6|GPIO_PC5);

	demo_LCD_APP();							            //显示屏
//	demo_CAPB18_APP();						            //气压计
	demo_SHT3x_APP();						            //温湿度
//	gyro_dev_init();						            //加速度传感器
//	
//	//OS Timer
	os_timer_init(&timer_refresh,timer_refresh_fun,NULL);//创建一个周期性1s定时的系统定时器
	os_timer_start(&timer_refresh,1000,1);

}

GATT操作主要是在回调函数sp_gatt_read_cb和sp_gatt_write_cb里进行:

/*********************************************************************
 * @fn      sp_gatt_msg_handler
 *
 * @brief   Simple Profile callback funtion for GATT messages. GATT read/write
 *			operations are handeled here.
 *
 * @param   p_msg       - GATT messages from GATT layer.
 *
 * @return  uint16_t    - Length of handled message.
 */
static uint16_t sp_gatt_msg_handler(gatt_msg_t *p_msg)
{
    
    switch(p_msg->msg_evt)
    {
    
        case GATTC_MSG_READ_REQ:
            sp_gatt_read_cb((uint8_t *)(p_msg->param.msg.p_msg_data), &(p_msg->param.msg.msg_len), p_msg->att_idx);
            break;
        
        case GATTC_MSG_WRITE_REQ:
            sp_gatt_write_cb((uint8_t*)(p_msg->param.msg.p_msg_data), (p_msg->param.msg.msg_len), p_msg->att_idx,p_msg->conn_idx);
            break;
            
        default:
            break;
    }
    return p_msg->param.msg.msg_len;
}

四、【SDK组件二】操作系统抽象层OSAL

本次使用os_user_loop_event_set创建了循环任务读取max30102的心率数据。OSAL有以下部分组成:

  • os_task_create:创建一个任务。 最多支持 20 个任务。 任务不分优先级。 消息按抛送的顺序进行处理
  • os_task_delete:删除一个已经创建的任务。
  • os_msg_post:向某个已经创建的目标任务抛一个消息事件
  • os_user_loop_event_set:用户设置一个跑在 while(1)循环中的函数, 便于用户做一些循环检测或者操作处理。 该循环处理事件优先级最低, 另外用户在需要睡眠时应先清除这个事件。
  • os_user_loop_event_clear:清除循环处理事件。

五、【SDK组件三】系统定时任务CLOCK

软件定时器用来创建一个定时任务,比如10秒钟处理一次任务A,20秒处理一次任务B。

  • os_timer_init:初始化一个软件定时器。 最多支持 50 个定时器。 使用软件定时器之前, 必须调用该函数进行初始化。
  • os_timer_start:启动一个软件定时器
  • os_timer_stop:停止一个软件定时器

六、测试

连接图

(FR8016) PC6 ->SCL(MAX30102)
(FR8016) PC7 ->SDA(MAX30102)
(FR8016) PA5 ->INT(MAX30102)
在这里插入图片描述

测试一:功能验证

手机在应用商店下载一个 蓝牙调试器。可见我的心率在80~90之间,完成了心率数据通过BLE上传到我的安卓手机。
在这里插入图片描述

测试二:BLE安全

通过USB dongle抓包,可见fr8016与我的安卓手机建立了加密通信。
在这里插入图片描述

测试三:逻辑分析仪分析

由下图可见,fr8016与max30102能正常的进行i2c通信。
在这里插入图片描述

项目地址

修改后上传

视频链接

拍摄后上传

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43810563/article/details/115440618

智能推荐

稀疏编码的数学基础与理论分析-程序员宅基地

文章浏览阅读290次,点赞8次,收藏10次。1.背景介绍稀疏编码是一种用于处理稀疏数据的编码技术,其主要应用于信息传输、存储和处理等领域。稀疏数据是指数据中大部分元素为零或近似于零的数据,例如文本、图像、音频、视频等。稀疏编码的核心思想是将稀疏数据表示为非零元素和它们对应的位置信息,从而减少存储空间和计算复杂度。稀疏编码的研究起源于1990年代,随着大数据时代的到来,稀疏编码技术的应用范围和影响力不断扩大。目前,稀疏编码已经成为计算...

EasyGBS国标流媒体服务器GB28181国标方案安装使用文档-程序员宅基地

文章浏览阅读217次。EasyGBS - GB28181 国标方案安装使用文档下载安装包下载,正式使用需商业授权, 功能一致在线演示在线API架构图EasySIPCMSSIP 中心信令服务, 单节点, 自带一个 Redis Server, 随 EasySIPCMS 自启动, 不需要手动运行EasySIPSMSSIP 流媒体服务, 根..._easygbs-windows-2.6.0-23042316使用文档

【Web】记录巅峰极客2023 BabyURL题目复现——Jackson原生链_原生jackson 反序列化链子-程序员宅基地

文章浏览阅读1.2k次,点赞27次,收藏7次。2023巅峰极客 BabyURL之前AliyunCTF Bypassit I这题考查了这样一条链子:其实就是Jackson的原生反序列化利用今天复现的这题也是大同小异,一起来整一下。_原生jackson 反序列化链子

一文搞懂SpringCloud,详解干货,做好笔记_spring cloud-程序员宅基地

文章浏览阅读734次,点赞9次,收藏7次。微服务架构简单的说就是将单体应用进一步拆分,拆分成更小的服务,每个服务都是一个可以独立运行的项目。这么多小服务,如何管理他们?(服务治理 注册中心[服务注册 发现 剔除])这么多小服务,他们之间如何通讯?这么多小服务,客户端怎么访问他们?(网关)这么多小服务,一旦出现问题了,应该如何自处理?(容错)这么多小服务,一旦出现问题了,应该如何排错?(链路追踪)对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对每一个问题提供了相应的组件来解决它们。_spring cloud

Js实现图片点击切换与轮播-程序员宅基地

文章浏览阅读5.9k次,点赞6次,收藏20次。Js实现图片点击切换与轮播图片点击切换<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <script type="text/ja..._点击图片进行轮播图切换

tensorflow-gpu版本安装教程(过程详细)_tensorflow gpu版本安装-程序员宅基地

文章浏览阅读10w+次,点赞245次,收藏1.5k次。在开始安装前,如果你的电脑装过tensorflow,请先把他们卸载干净,包括依赖的包(tensorflow-estimator、tensorboard、tensorflow、keras-applications、keras-preprocessing),不然后续安装了tensorflow-gpu可能会出现找不到cuda的问题。cuda、cudnn。..._tensorflow gpu版本安装

随便推点

物联网时代 权限滥用漏洞的攻击及防御-程序员宅基地

文章浏览阅读243次。0x00 简介权限滥用漏洞一般归类于逻辑问题,是指服务端功能开放过多或权限限制不严格,导致攻击者可以通过直接或间接调用的方式达到攻击效果。随着物联网时代的到来,这种漏洞已经屡见不鲜,各种漏洞组合利用也是千奇百怪、五花八门,这里总结漏洞是为了更好地应对和预防,如有不妥之处还请业内人士多多指教。0x01 背景2014年4月,在比特币飞涨的时代某网站曾经..._使用物联网漏洞的使用者

Visual Odometry and Depth Calculation--Epipolar Geometry--Direct Method--PnP_normalized plane coordinates-程序员宅基地

文章浏览阅读786次。A. Epipolar geometry and triangulationThe epipolar geometry mainly adopts the feature point method, such as SIFT, SURF and ORB, etc. to obtain the feature points corresponding to two frames of images. As shown in Figure 1, let the first image be ​ and th_normalized plane coordinates

开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先抽取关系)_语义角色增强的关系抽取-程序员宅基地

文章浏览阅读708次,点赞2次,收藏3次。开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先关系再实体)一.第二代开放信息抽取系统背景​ 第一代开放信息抽取系统(Open Information Extraction, OIE, learning-based, 自学习, 先抽取实体)通常抽取大量冗余信息,为了消除这些冗余信息,诞生了第二代开放信息抽取系统。二.第二代开放信息抽取系统历史第二代开放信息抽取系统着眼于解决第一代系统的三大问题: 大量非信息性提取(即省略关键信息的提取)、_语义角色增强的关系抽取

10个顶尖响应式HTML5网页_html欢迎页面-程序员宅基地

文章浏览阅读1.1w次,点赞6次,收藏51次。快速完成网页设计,10个顶尖响应式HTML5网页模板助你一臂之力为了寻找一个优质的网页模板,网页设计师和开发者往往可能会花上大半天的时间。不过幸运的是,现在的网页设计师和开发人员已经开始共享HTML5,Bootstrap和CSS3中的免费网页模板资源。鉴于网站模板的灵活性和强大的功能,现在广大设计师和开发者对html5网站的实际需求日益增长。为了造福大众,Mockplus的小伙伴整理了2018年最..._html欢迎页面

计算机二级 考试科目,2018全国计算机等级考试调整,一、二级都增加了考试科目...-程序员宅基地

文章浏览阅读282次。原标题:2018全国计算机等级考试调整,一、二级都增加了考试科目全国计算机等级考试将于9月15-17日举行。在备考的最后冲刺阶段,小编为大家整理了今年新公布的全国计算机等级考试调整方案,希望对备考的小伙伴有所帮助,快随小编往下看吧!从2018年3月开始,全国计算机等级考试实施2018版考试大纲,并按新体系开考各个考试级别。具体调整内容如下:一、考试级别及科目1.一级新增“网络安全素质教育”科目(代..._计算机二级增报科目什么意思

conan简单使用_apt install conan-程序员宅基地

文章浏览阅读240次。conan简单使用。_apt install conan