STM32F7xx —— CAN通信

目录

STM32F7xx —— CAN通信

一、CAN基础

二、几个重要的CAN函数

三、几个重要的结构

四、接口设计


一、CAN基础

差分信号:显性电平对应逻辑0,CAN_H和CAN_L差为2.5V;隐形电平对应逻辑1,CAN_H和CAN_L差为0V。

CAN总线的开始和结束都有一个120Ω的终端电阻。

数据帧:标准帧11位,  扩展帧29位。

其他的一些理论知识就不再赘述了,可以参考维基百科对于CAN的描述。

STM32F7xx的bxCAN主要特点:支持CAN2.0A和CAN2.0B,波特率高达1Mbps,支持时间触发,具有3个发送邮箱,2个接收邮箱,可变的过滤器组等。

二、几个重要的CAN函数

HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan); // CAN初始化HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout); // CAN发送HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef *hcan, uint8_t FIFONumber, uint32_t Timeout); // CAN接收

三、几个重要的结构

// CAN操作句柄 包含CAN基地址(CAN1/CAN2/CAN3) 初始化结构 发送接收结构体 其余三个是过程变量
typedef struct
{CAN_TypeDef                 *Instance;  /*!< Register base address          */CAN_InitTypeDef             Init;       /*!< CAN required parameters        */CanTxMsgTypeDef*            pTxMsg;     /*!< Pointer to transmit structure  */CanRxMsgTypeDef*            pRxMsg;     /*!< Pointer to reception structure */__IO HAL_CAN_StateTypeDef   State;      /*!< CAN communication state        */HAL_LockTypeDef             Lock;       /*!< CAN locking object             */__IO uint32_t               ErrorCode;  /*!< CAN Error code                 */}CAN_HandleTypeDef;
// CAN配置结构体
// 前5个参数来设置 CAN_BTR —— 波特率
// 后6个参数用来设置 CAN_MCR —— 通信相关的控制位
typedef struct
{uint32_t Prescaler;  /*!< Specifies the length of a time quantum.This parameter must be a number between Min_Data = 1 and Max_Data = 1024 */uint32_t Mode;       /*!< Specifies the CAN operating mode.This parameter can be a value of @ref CAN_operating_mode */uint32_t SJW;        /*!< Specifies the maximum number of time quantathe CAN hardware is allowed to lengthen orshorten a bit to perform resynchronization.This parameter can be a value of @ref CAN_synchronisation_jump_width */uint32_t BS1;        /*!< Specifies the number of time quanta in Bit Segment 1.This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_1 */uint32_t BS2;        /*!< Specifies the number of time quanta in Bit Segment 2.This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */uint32_t TTCM;       /*!< Enable or disable the time triggered communication mode.This parameter can be set to ENABLE or DISABLE. */uint32_t ABOM;       /*!< Enable or disable the automatic bus-off management.This parameter can be set to ENABLE or DISABLE */uint32_t AWUM;       /*!< Enable or disable the automatic wake-up mode.This parameter can be set to ENABLE or DISABLE */uint32_t NART;       /*!< Enable or disable the non-automatic retransmission mode.This parameter can be set to ENABLE or DISABLE */uint32_t RFLM;       /*!< Enable or disable the receive FIFO Locked mode.This parameter can be set to ENABLE or DISABLE */uint32_t TXFP;       /*!< Enable or disable the transmit FIFO priority.This parameter can be set to ENABLE or DISABLE */
}CAN_InitTypeDef;
// 过滤器设置
typedef struct
{uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bitconfiguration, first one for a 16-bit configuration).This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bitconfiguration, second one for a 16-bit configuration).This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,according to the mode (MSBs for a 32-bit configuration,first one for a 16-bit configuration).This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,according to the mode (LSBs for a 32-bit configuration,second one for a 16-bit configuration).This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1) which will be assigned to the filter.This parameter can be a value of @ref CAN_filter_FIFO */uint32_t FilterNumber;          /*!< Specifies the filter which will be initialized.This parameter must be a number between Min_Data = 0 and Max_Data = 27 */uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized.This parameter can be a value of @ref CAN_filter_mode */uint32_t FilterScale;           /*!< Specifies the filter scale.This parameter can be a value of @ref CAN_filter_scale */uint32_t FilterActivation;      /*!< Enable or disable the filter.This parameter can be set to ENABLE or DISABLE. */uint32_t BankNumber;            /*!< Select the start slave bank filter.This parameter must be a number between Min_Data = 0 and Max_Data = 28 */}CAN_FilterConfTypeDef;
// 模式  我们使用普通模式
#define CAN_MODE_NORMAL             ((uint32_t)0x00000000U)                     /*!< Normal mode   */
#define CAN_MODE_LOOPBACK           ((uint32_t)CAN_BTR_LBKM)                   /*!< Loopback mode */
#define CAN_MODE_SILENT             ((uint32_t)CAN_BTR_SILM)                   /*!< Silent mode   */
#define CAN_MODE_SILENT_LOOPBACK    ((uint32_t)(CAN_BTR_LBKM | CAN_BTR_SILM))  /*!< Loopback combined with silent mode */
// 标准帧 扩展帧
#define CAN_ID_STD             ((uint32_t)0x00000000U)  /*!< Standard Id */
#define CAN_ID_EXT             ((uint32_t)0x00000004U)  /*!< Extended Id */
// 数据帧 远程帧
#define CAN_RTR_DATA                ((uint32_t)0x00000000U)  /*!< Data frame */
#define CAN_RTR_REMOTE              ((uint32_t)0x00000002U)  /*!< Remote frame */
// CAN中断使能
__HAL_CAN_ENABLE_IT(__HANDLE__, __INTERRUPT__) 
// 接收中断
#define CAN_IT_FMP0                 ((uint32_t)CAN_IER_FMPIE0)  /*!< FIFO 0 message pending interrupt */
#define CAN_IT_FF0                  ((uint32_t)CAN_IER_FFIE0)   /*!< FIFO 0 full interrupt            */
#define CAN_IT_FOV0                 ((uint32_t)CAN_IER_FOVIE0)  /*!< FIFO 0 overrun interrupt         */
#define CAN_IT_FMP1                 ((uint32_t)CAN_IER_FMPIE1)  /*!< FIFO 1 message pending interrupt */
#define CAN_IT_FF1                  ((uint32_t)CAN_IER_FFIE1)   /*!< FIFO 1 full interrupt            */
#define CAN_IT_FOV1                 ((uint32_t)CAN_IER_FOVIE1)  /*!< FIFO 1 overrun interrupt         */

四、接口设计

与串口类似,使用中断接收。先封装单路CAN需要的几个小接口,再顶一个列表,最后使用统一的接口扫描这个列表。

typedef enum
{CAN_CHANNEL_NONE,CAN_CHANNEL_1,CAN_CHANNEL_2,CAN_CHANNEL_NUM
} can_channel_t;#define CAN1_CHANNEL              CAN1
#define CAN1_PREEMPT_PRIO         CAN1_RX_PRIORITY
#define CAN1_RX_IRQ               CAN1_RX0_IRQn
#define CAN1_RX_IRQ_FUNC          CAN1_RX0_IRQHandler
#define CAN1_CLK_ENABLE()         __HAL_RCC_CAN1_CLK_ENABLE()
#define CAN1_TX_PORT              GPIOA
#define CAN1_TX_PIN               GPIO_PIN_12
#define CAN1_TX_AF                GPIO_AF9_CAN1
#define CAN1_TX_CONFIG()          GPIOConfigExt(CAN1_TX_PORT, CAN1_TX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, CAN1_TX_AF)
#define CAN1_RX_PORT              GPIOA
#define CAN1_RX_PIN               GPIO_PIN_11
#define CAN1_RX_AF                GPIO_AF9_CAN1
#define CAN1_RX_CONFIG()          GPIOConfigExt(CAN1_RX_PORT, CAN1_RX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, CAN1_RX_AF)#define CAN2_CHANNEL              CAN2
#define CAN2_PREEMPT_PRIO         CAN2_RX_PRIORITY
#define CAN2_RX_IRQ               CAN2_RX0_IRQn
#define CAN2_RX_IRQ_FUNC          CAN2_RX0_IRQHandler
#define CAN2_CLK_ENABLE()         __HAL_RCC_CAN2_CLK_ENABLE()
#define CAN2_TX_PORT              GPIOB
#define CAN2_TX_PIN               GPIO_PIN_6
#define CAN2_TX_AF                GPIO_AF9_CAN2
#define CAN2_TX_CONFIG()          GPIOConfigExt(CAN2_TX_PORT, CAN2_TX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, CAN2_TX_AF)
#define CAN2_RX_PORT              GPIOB
#define CAN2_RX_PIN               GPIO_PIN_5
#define CAN2_RX_AF                GPIO_AF9_CAN2
#define CAN2_RX_CONFIG()          GPIOConfigExt(CAN2_RX_PORT, CAN2_RX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, CAN2_RX_AF)
// 抽象出一个CAN设备结构体
typedef struct
{CAN_HandleTypeDef handle; // CAN操作句柄CanTxMsgTypeDef tx;       // CAN发送CanRxMsgTypeDef rx;       // CAN接收can_queue_t recv;         // 接收队列} can_dev_t;
// 将每路CAN封装成几个小函数
static can_dev_t can1_dev, can2_dev;static void can1_var_init(void)
{can1_dev.recv = can1_queue_recv;CanQueueInit(&can1_dev.recv);
}static void can1_gpio_init(void)
{CAN1_TX_CONFIG();CAN1_RX_CONFIG();
}// 波特率 = Fpclk1 / ((ts1+ts2+3) * brp)  Fpclk1 = 54M
static void can1_mode_init(void)
{CAN1_CLK_ENABLE();can1_dev.handle.Instance = CAN1_CHANNEL;can1_dev.handle.pTxMsg = &can1_dev.tx;can1_dev.handle.pRxMsg = &can1_dev.rx;can1_dev.handle.Init.Prescaler = 6;can1_dev.handle.Init.Mode = CAN_MODE_NORMAL;can1_dev.handle.Init.SJW = CAN_SJW_1TQ; // 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1TQ~CAN_SJW_4TQcan1_dev.handle.Init.BS1 = CAN_BS1_11TQ;// tbs1范围CAN_BS1_1TQ~CAN_BS1_16TQcan1_dev.handle.Init.BS2 = CAN_BS2_6TQ; // tbs2范围CAN_BS2_1TQ~CAN_BS2_8TQcan1_dev.handle.Init.TTCM = DISABLE;    // 非时间触发通信模式can1_dev.handle.Init.ABOM = ENABLE;     // 软件自动离线管理can1_dev.handle.Init.AWUM = DISABLE;    // 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)can1_dev.handle.Init.NART = ENABLE;     // 禁止报文自动传送can1_dev.handle.Init.RFLM = DISABLE;    // 报文不锁定,新的覆盖旧的can1_dev.handle.Init.TXFP = DISABLE;    // 优先级由报文标识符决定HAL_CAN_Init(&can1_dev.handle);
}static void can1_filter_init(void)
{CAN_FilterConfTypeDef  filter;filter.FilterNumber     = 0; // 过滤器0filter.FilterMode       = CAN_FILTERMODE_IDMASK;filter.FilterScale      = CAN_FILTERSCALE_32BIT;filter.FilterIdHigh     = 0;filter.FilterIdLow      = 0;filter.FilterMaskIdHigh = 0;filter.FilterMaskIdLow  = 0;filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; // 过滤器0关联到FIFO0filter.FilterActivation = ENABLE; //激活滤波器0//filter.BankNumber=14;HAL_CAN_ConfigFilter(&can1_dev.handle, &filter);
}static void can1_nvic_init(void)
{__HAL_CAN_ENABLE_IT(&can1_dev.handle, CAN_IT_FMP0); //FIFO0消息挂号中断允许.HAL_NVIC_SetPriority(CAN1_RX_IRQ, CAN1_RX_PRIORITY, 0);HAL_NVIC_EnableIRQ(CAN1_RX_IRQ);
}static void can2_var_init(void)
{can2_dev.recv = can2_queue_recv;CanQueueInit(&can2_dev.recv);
}static void can2_gpio_init(void)
{CAN2_TX_CONFIG();CAN2_RX_CONFIG();
}// 波特率 = Fpclk1 / ((ts1+ts2+3) * brp)  Fpclk1 = 54M
static void can2_mode_init(void)
{CAN2_CLK_ENABLE();can2_dev.handle.Instance = CAN2_CHANNEL;can2_dev.handle.Init.Prescaler = 6;can2_dev.handle.Init.Mode = CAN_MODE_LOOPBACK;can2_dev.handle.Init.SJW = CAN_SJW_1TQ; // 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1TQ~CAN_SJW_4TQcan2_dev.handle.Init.BS1 = CAN_BS1_11TQ;// tbs1范围CAN_BS1_1TQ~CAN_BS1_16TQcan2_dev.handle.Init.BS2 = CAN_BS2_6TQ; // tbs2范围CAN_BS2_1TQ~CAN_BS2_8TQcan2_dev.handle.Init.TTCM = DISABLE;    // 非时间触发通信模式can2_dev.handle.Init.ABOM = ENABLE;     // 软件自动离线管理can2_dev.handle.Init.AWUM = DISABLE;    // 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)can2_dev.handle.Init.NART = ENABLE;     // 禁止报文自动传送can2_dev.handle.Init.RFLM = DISABLE;    // 报文不锁定,新的覆盖旧的can2_dev.handle.Init.TXFP = DISABLE;    // 优先级由报文标识符决定HAL_CAN_Init(&can2_dev.handle);
}static void can2_filter_init(void)
{CAN_FilterConfTypeDef  CAN_FilterInitStructure;CAN_FilterInitStructure.FilterNumber     = 14;CAN_FilterInitStructure.FilterMode       = CAN_FILTERMODE_IDMASK;CAN_FilterInitStructure.FilterScale      = CAN_FILTERSCALE_32BIT;CAN_FilterInitStructure.FilterIdHigh     = 0;CAN_FilterInitStructure.FilterIdLow      = 0;CAN_FilterInitStructure.FilterMaskIdHigh = 0;CAN_FilterInitStructure.FilterMaskIdLow  = 0;CAN_FilterInitStructure.FilterFIFOAssignment = CAN_FILTER_FIFO0; // 过滤器0关联到FIFO0CAN_FilterInitStructure.FilterActivation = ENABLE; //激活滤波器0//CAN_FilterInitStructure.BankNumber=14;HAL_CAN_ConfigFilter(&can2_dev.handle, &CAN_FilterInitStructure);
}static void can2_nvic_init(void)
{__HAL_CAN_ENABLE_IT(&can2_dev.handle, CAN_IT_FMP0); //FIFO0消息挂号中断允许1HAL_NVIC_SetPriority(CAN2_RX_IRQ, CAN2_RX_PRIORITY, 0);HAL_NVIC_EnableIRQ(CAN2_RX_IRQ);
}
// 每路CAN都有的几个操作,使用列表包含,然后统一扫描处理
typedef struct
{uint8_t channel;can_dev_t *dev;void (* var_init_cb)(void);void (* gpio_init_cb)(void);void (* mode_init_cb)(void);void (* filter_init_cb)(void);void (* nvic_init_cb)(void);
} can_config_t;static const can_config_t can_configs[] =
{{CAN_CHANNEL_1, &can1_dev, can1_var_init, can1_gpio_init, can1_mode_init, can1_filter_init, can1_nvic_init},{CAN_CHANNEL_2, &can2_dev, can2_var_init, can2_gpio_init, can2_mode_init, can2_filter_init, can2_nvic_init},
};static can_dev_t *can_dev_get(uint8_t channel)
{uint8_t i;for(i = 0; i < ARRAY_SIZE(can_configs); ++i){if(channel == can_configs[i].channel){return can_configs[i].dev;}}return 0;
}static void can_var_init(uint8_t channel)
{uint8_t i;for(i = 0; i < ARRAY_SIZE(can_configs); ++i){if(channel == can_configs[i].channel){can_configs[i].var_init_cb();return;}}
}static void can_gpio_init(uint8_t channel)
{uint8_t i;for(i = 0; i < ARRAY_SIZE(can_configs); ++i){if(channel == can_configs[i].channel){can_configs[i].gpio_init_cb();return;}}
}static void can_mode_init(uint8_t channel)
{uint8_t i;for(i = 0; i < ARRAY_SIZE(can_configs); ++i){if(channel == can_configs[i].channel){can_configs[i].mode_init_cb();return;}}
}static void can_filter_init(uint8_t channel)
{uint8_t i;for(i = 0; i < ARRAY_SIZE(can_configs); ++i){if(channel == can_configs[i].channel){can_configs[i].filter_init_cb();return;}}
}static void can_nvic_init(uint8_t channel)
{uint8_t i;for(i = 0; i < ARRAY_SIZE(can_configs); ++i){if(channel == can_configs[i].channel){can_configs[i].nvic_init_cb();return;}}
}
// 对外的接口 初始化 发送和接收
void CanInit(uint8_t channel)
{can_var_init(channel);can_gpio_init(channel);can_mode_init(channel);can_filter_init(channel);can_nvic_init(channel);
}void CanSend(uint8_t channel, can_frame_t *frame)
{can_dev_t *dev = can_dev_get(channel);if(dev == 0){return;}dev->handle.pTxMsg->StdId = frame->StdId;dev->handle.pTxMsg->IDE   = frame->IDE;dev->handle.pTxMsg->RTR   = frame->RTR;dev->handle.pTxMsg->DLC   = frame->DLC;memcpy(dev->handle.pTxMsg->Data, frame->Data, frame->DLC);HAL_CAN_Transmit(&dev->handle, 10);
}uint8_t CanRecv(uint8_t channel, can_frame_t *frame)
{can_dev_t *dev = can_dev_get(channel);if(dev == 0){return 0;}return CanQueueRead(&can1_dev.recv, frame);
}
// CAN中断
void CAN1_RX_IRQ_FUNC(void)
{HAL_CAN_IRQHandler(&can1_dev.handle);
}void CAN2_RX_IRQ_FUNC(void)
{HAL_CAN_IRQHandler(&can2_dev.handle);
}void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef *hcan)
{if(hcan == (&can1_dev.handle)){//CAN_Receive_IT()函数会关闭FIFO0消息挂号中断,因此我们需要重新打开__HAL_CAN_ENABLE_IT(&can1_dev.handle, CAN_IT_FMP0);//重新开启FIF00消息挂号中断CanQueueWrite(&can1_dev.recv, can1_dev.handle.pRxMsg);}else if(hcan == (&can2_dev.handle)){//CAN_Receive_IT()函数会关闭FIFO0消息挂号中断,因此我们需要重新打开__HAL_CAN_ENABLE_IT(&can2_dev.handle, CAN_IT_FMP0);//重新开启FIF00消息挂号中断CanQueueWrite(&can2_dev.recv, can2_dev.handle.pRxMsg);}
}

之所以使用列表的形式,是为了方便增加和删除CAN通道和使对外的接口更统一,不会出现CAN1Init() CAN2Init(),个人习惯问题。

CAN队列可参考:CAN队列

STM32F7xx —— CAN通信相关推荐

  1. STM32F7xx —— LAN8720(FreeRTOS+LWIP)

    STM32F7xx -- LAN8720 STM32F767自带以太网模块,需要外接PHY芯片,完成以太网通信(MII/RMII接口).LAN8720详细资料看手册.LWIP:1.4.1 FreeRT ...

  2. STM32F7xx —— QSPI

    STM32F7xx -- QSPI 目录 STM32F7xx -- QSPI 一.QSPI 二.几个重要的函数 三.几个重要的结构 四.QSPI接口设计(仅供参考) 五.QSPI驱动W25Q256 一 ...

  3. RPC 笔记(05)— socket 通信(单线程服务器)

    1. Python 标准库 1.1 socket 提供 RPC 服务的网络通信功能,方便用户编写 tcp/udp 相关的代码.两个不同机器的进程需要通信时,可以通过 socket 来传输数据. ​ 客 ...

  4. Python 多进程笔记 — 启动进程的方式、守护进程、进程间通信、进程池、进程池之间通信、多进程生产消费模型

    1 面向过程启动多进程 Python 操作进程的类都定义在 multiprocessing 模块,该模块提供了一个 Process 类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另 ...

  5. HTTP 协议入门 — (TCP/IP协议族、通信传输流、URI 与 URL 的区别、Cookie 状态管理、HTTP 支持的方法、状态码类别、HTTP 首部字段)

    TCP/IP协议族 在介绍 HTTP 协议之前,我们先对 TCP/IP 协议族有个大概的了解,TCP/IP 协议从上到下主要分为应用层.传输层.网络层和数据链路层,各层的主要功能如下表所示: 协议层 ...

  6. python第三方库之学习pyserial库--串口通信

    pyserial串口通信库 1.安装pyserial库 2.填写串口参数的注意事项 3.简单封装一下 4.碰到的bug 1.安装pyserial库 pip install pyserial versi ...

  7. python 网络编程之Socket通信案例消息发送与接收

    背景 网络编程是python编程中的一项基本技术.本文将实现一个简单的Socket通信案例消息发送与接收 正文 在python中的socket编程的大致流程图如上所示 我们来首先编写客户端的代码: # ...

  8. NVIDIA空中导航SDK改造5G通信

    NVIDIA空中导航SDK改造5G通信 Transforming Next-Generation Wireless with 5T for 5G and the NVIDIA Aerial SDK N ...

  9. 十五天精通WCF——第六天 你必须要了解的3种通信模式

    十五天精通WCF--第六天 你必须要了解的3种通信模式 原文:十五天精通WCF--第六天 你必须要了解的3种通信模式 wcf已经说到第六天了,居然还没有说到这玩意有几种通信模式,惭愧惭愧,不过很简单啦 ...

最新文章

  1. skiller v3 beta2_S10全球总决赛:赛前叫嚣却遭打脸!V3被LGD踢出S10,日本撸友彻底炸锅:真是悲哀...
  2. 如果list中既包含字符串,又包含整数,由于非字符串类型没有lower()方法,所以列表生成式会报错:...
  3. 纯CSS 实现组织架构图,学习
  4. 城市轨道交通运营票务管理论文_城市轨道交通运营管理专业就业前景怎么样?中职优选告诉你...
  5. java同时输出多个数字_java从命令行接收多个数字,求和之后输出结果
  6. DPDK内存篇(一): 基本概念
  7. python什么是堆什么是栈_顶置篇:CPython的内存概念:栈、堆和引用
  8. 微软与 OpenAI 达成合作,获得 GPT-3 独家使用授权!
  9. 惯性力偶矩公式中j_惯性力偶矩的计算
  10. Android 获取经纬度。2018年写
  11. HashMap底层——解决Hash冲突(链地址法)
  12. 腾讯产品/策划笔试面试经验
  13. 关于http的Authorization
  14. 【GIT-3】GIT 的基础教程 分支管理 fixbug分支 Featur 冲突处理 标签管理 操作
  15. 入选数据库顶会 VLDB:如何有效降低产品级内存数据库快照尾延迟?
  16. STM32F4xx的时钟树
  17. Gunicorn 部署flask-socketio项目,项目访问慢的问题
  18. “博客无双”第二期拍卖活动将于2011年1月26日14:00开始
  19. There is no getter for property named 'depart' in 'class com.xuezhixin.mls.web.model.Major'
  20. 用计算机按出童话,算盘与计算器

热门文章

  1. c# Ftp下载程序源代码解析
  2. linux nfs配置
  3. Linux中配置ftp服务器
  4. Django中的class Meta知识点
  5. java递归空瓶换饮料_问题描述:一次买n瓶可乐,k个空瓶可以换一瓶饮料,那么一共能喝多少瓶饮料? | 学步园...
  6. 获取系统信息3——proc文件系统介绍和使用
  7. c++远征之模板篇——函数模板、类模板
  8. 初二计算机辅导记录,信息技术指导老师的讲课笔记十篇(2)
  9. Window系统下安装Redis
  10. [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)...