STM32 cubemx CAN

接收用到的结构体如下:CAN概念:

        全称Controller Area Network,是一种半双工,异步通讯。

物理层:

        闭环:允许总线最长40m,最高速1Mbps,规定总线两端各有一个120Ω电阻,闭环

       开环:最大传输距离1Km,最高速125Kbps,规定每根线串联一个2.2kΩ的电阻,开环

CAN协议基本特点

       基本特点如下:

       可多主控制: 当CAN总线空闲时,所有在总线上的终端都可以发送报文,根据标识符(CAN ID)决定优先级,当总线上有两个以上的终端发送消息时,对各消息CAN ID的每个位进行逐个仲裁比较。CAN ID值越低,报文优先级越高速度快,距离远:CAN 协议最快可达1Mbps(距离小于40m),最远可达10KM(速率小于 5Kbps)
       CAN 帧种类:CAN 通信中包含五种帧种类,数据帧、遥控帧、错误帧、过载帧、间隔帧。其中最重要的是数据帧,用于通讯节点向外传送数据。数据帧中有数据段,用于承载数据的内容,一帧可发送0~8个字节的数据,MSB先行。
简单了解上述基本特点即可快速上手CAN总线的配置。

       显性电平对应“0”,隐性电平对应“1”。隐性电平(1)两条线电压都是2.5V,即压差为0;显性电平(0)CAN_High和CAN_Low分别为3.5V和1.5V,压差为2V。

       总线上,只要有一个节点输出显性,则总线上为显性电平;只有所有节点都是隐性电平,总线才为隐性电平

CAN网络由CAN控制器和CAN收发器组成,STM32仅集成了CAN控制器。

1、硬件-芯片使用:STM32F103Cx系列

cubeMX配置时钟

can外设挂载在APB1上。

 

一般通信都会打开接收中断,在这里打开CAN1 RX0的中断,优先级可以通过NVIC进行更改。 

CAN 的波特率及位同步

位时序分解

 Prescaler:预分频,确定CAN最小时间单位Tq。

这里以F103C8T6为例,APB1时钟为36Mhz
计算波特率的方法:36M/分频系数/(BS1 + BS2 + 1)
如图设置,波特率是1000Kbps,36M / 4 /(4 + 4 + 1) =1M = 1000K

波特率计算公式:

配置工作模式:

CAN数据帧格式

 CAN波特率计算小工具

STM32 CAN Baud Rate CalculatorV1.0-STM32 CAN Baud Rate Calculator官方下载_3DM软件

STM32的CAN通信波特率计算器

 

 CANPro协议分析平台软件为CANalyst-II+的标配软件

CAN基本函数
函数         功能
HAL_CAN_Start                                    开启CAN通讯
HAL_CAN_Stop                                    关闭CAN通讯
HAL_CAN_RequestSleep                     使CAN模块完成当前操作后尝试进入休眠模式
HAL_CAN_WakeUp                              从休眠模式中唤醒
HAL_CAN_IsSleepActive                      检查是否成功处于休眠模式
HAL_CAN_AddTxMessage                   向 Tx 邮箱中增加一个消息,并且激活对应的传输请求
HAL_CAN_AbortTxRequest                  请求中断传输
HAL_CAN_GetTxMailboxesFreeLevel  查询空闲的发送邮箱个数
HAL_CAN_IsTxMessagePending          检查是否有传输请求在指定的 Tx 邮箱上等待
HAL_CAN_GetRxMessage                    从Rx FIFO 收取一个 CAN 帧
HAL_CAN_GetRxFifoFillLevel               查询接收邮箱未读邮箱的个数

STM32HAL库学习——CAN笔记_hal库can_jdhfusk的博客-CSDN博客

发送用到的结构体如下:

typedef struct
{
  uint32_t StdId;    //标准ID
  uint32_t ExtId;    //扩展ID
  uint32_t IDE;      //用来决定报文是使用标准ID还是扩准ID
  uint32_t RTR;      //用来决定报文是数据帧要是遥控帧
  uint32_t DLC;      //数据长度,取值为0-8
  FunctionalState TransmitGlobalTime; 
//最后这个是时间触发模式用的,开启后会自动把时间戳添加到最后两字节的数据中。目前没有用到,选择 DISABLE 
} CAN_TxHeaderTypeDef;

StdId :如果将要发送的报文使用标准ID,那么这个成员便记录标准ID的值
取值: 0x0 ~ 0x7FF

ExtId :如果将要发送的报文使用扩展ID,那么这个成员便记录扩展ID的值
取值: 0x0 ~ 0x1FFFFFFF

IDE :用来决定报文使用标准ID还是扩准ID
取值: CAN_ID_STD 或 CAN_ID_EXT

RTR :用来决定报文是数据帧要是遥控帧
取值: CAN_RTR_DATA 或 CAN_RTR_REMOTE

DLC :用来记录数据帧的数据长度,单位字节(如果要发送的是遥控帧,该成员中的内容不起作用)
取值:0 ~ 8

TransmitGlobalTime :目前没有用到,选择 DISABLE
取值: ENABLE 或 DISABLE

发送用到的函数如下:

HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox);

CAN_TxHeaderTypeDef can_Tx;
uint8_t sendBuf[5] = {"hello"};
uint32_t box;

int main(void)
{
  	HAL_Init();
 	SystemClock_Config();
  	MX_GPIO_Init();
  	MX_CAN_Init();

    HAL_CAN_Start(&hcan1);
  
    can_Tx.StdId = 0x123;
    can_Tx.ExtId = 0;
    can_Tx.IDE = CAN_ID_STD;
    can_Tx.RTR = CAN_RTR_DATA;
    can_Tx.DLC = 5;
    can_Tx.TransmitGlobalTime = DISABLE;

  	while (1)
  	{
      	HAL_CAN_AddTxMessage(&hcan1, &can_Tx, sendBuf, &box);
      	HAL_Delay(100);
  	}
}

效果:每隔100ms发送一条报文

 筛选器

 typedef struct
{
  uint32_t FilterIdHigh;          //CAN_FiR1寄存器的高16位
  uint32_t FilterIdLow;           //CAN_FiR1寄存器的低16位
  uint32_t FilterMaskIdHigh;      //CAN_FiR2寄存器的高16位
  uint32_t FilterMaskIdLow;       //CAN_FiR2寄存器的低16位
  uint32_t FilterFIFOAssignment;  //通过筛选器的报文存在FIFO0还是FIFO1中
  uint32_t FilterBank;            //此次配置用的是哪个筛选器。用单CAN的取值为0-13
  uint32_t FilterMode;            //掩码模式或列表模式
  uint32_t FilterScale;           //32位或16位
  uint32_t FilterActivation;      //使能或失能
  uint32_t SlaveStartFilterBank;  //CAN1和CAN2一起用的时候,为CAN2分配筛选器的个数
} CAN_FilterTypeDef;

成员:

FilterIdHigh :CAN_FiR1寄存器的高16位,用于填写筛选码。具体的格式要根据16位、32位;掩码模式、列表模式来确定。
取值: 0x0 ~ 0xFFFF

FilterIdLow :CAN_FiR1寄存器的低16位

FilterMaskIdHigh :CAN_FiR2寄存器的高16位

FilterMaskIdLow :CAN_FiR2寄存器的低16位

FilterFIFOAssignment :通过筛选器的报文存在FIFO0还是FIFO1中
取值:CAN_FILTER_FIFO0 或 CAN_FILTER_FIFO1

FilterBank :本次配置的筛选器号
取值:对于单CAN为 0 ~ 13;对于双CAN为 0 ~ 27

FilterMode :筛选模式,掩码模式或列表模式。
取值:CAN_FILTERMODE_IDMASK 或 CAN_FILTERMODE_IDMASK

FilterScale :筛选码大小,16位或32位。
取值:CAN_FILTERSCALE_16BIT 或 CAN_FILTERSCALE_32BIT

FilterActivation :使能或失能此筛选器。
取值:CAN_FILTER_DISABLE 或 CAN_FILTER_ENABLE

SlaveStartFilterBank :为从CAN(CAN2)分配的筛选器个数。如果只使用单个CAN,可忽略此成员
取值:0 ~ 27

填好筛选器结构体,然后调用下面这个函数即可生效:

HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig);

CAN_FilterTypeDef can_Filter = {0};

can_Filter.FilterIdHigh = 0;
can_Filter.FilterIdLow = 0;
can_Filter.FilterMaskIdHigh = 0;
can_Filter.FilterMaskIdLow = 0;
can_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
can_Filter.FilterBank = 0;
can_Filter.FilterMode = CAN_FILTERMODE_IDMASK;
can_Filter.FilterScale = CAN_FILTERSCALE_32BIT;
can_Filter.FilterActivation = CAN_FILTER_ENABLE;

HAL_CAN_ConfigFilter(&hcan1, &can_Filter);

效果:CAN总线上所有的报文都会被接收,并存入FIFO0中。

CAN_FilterTypeDef can_Filter = {0};

can_Filter.FilterIdHigh = 0;
can_Filter.FilterIdLow = 0;
can_Filter.FilterMaskIdHigh = 0;
can_Filter.FilterMaskIdLow = 2;
can_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
can_Filter.FilterBank = 0;
can_Filter.FilterMode = CAN_FILTERMODE_IDLIST;
can_Filter.FilterScale = CAN_FILTERSCALE_32BIT;
can_Filter.FilterActivation = CAN_FILTER_ENABLE;

HAL_CAN_ConfigFilter(&hcan1, &can_Filter);

效果:仅接收标准ID为0x0的数据帧和遥控帧,并存入FIFO0中。

接收

​ CAN的接收通常是使用中断方式来实现(因为没有DMA,而查询法又难以保证实时性),因此首先要在CubeMX中打开接收的全局中断。

以看到有两个中断,一个是FIFO0收到数据的RX0中断,另一个是FIFO1收到数据的RX1中断,这里只用到了FIFO0,所以只勾选这个。(这里也说一说自己的理解,由于一个FIFO只能保存3条报文,有了两个FIFO就能保存6条报文。我们可以通过筛选器把不同ID的报文装进不同的FIFO,比如我们可以让FIFO0来接收关键、重要的报文,用FIFO1来接收不那么重要的报文,并且这两个中断是独立的,我们甚至可以给它们配置不一样的中断优先级。)

​ 光打开全局中断还不够,我们还需要打开CAN的FIFO消息挂起中断请求(也就是CAN外设的中断使能位)。

HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);

​ 这样,当CAN收到了符合筛选器的报文时,就会触发这个中断,我们便可以在这个中断回调函数中接收并处理收到的报文。(由于FIFO0和FIFO1用到的中断函数是独立的,因此这里的回调函数也是不一样的,大家要看清楚是FIFO0的还是1的)

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &can_Rx, recvBuf);

	/*下面是你用来处理收到数据的代码,
	可以通过串口把内容发送出来,
	也可以用来控制某些外设*/
}

 接收用到的结构体如下:

typedef struct
{
  uint32_t StdId;    
  uint32_t ExtId;    
  uint32_t IDE;      
  uint32_t RTR;      
  uint32_t DLC;      
  uint32_t Timestamp; 
  uint32_t FilterMatchIndex; 
} CAN_RxHeaderTypeDef;

和发送结构体非常类似,不过这个结构体并不需要我们来赋值,而是作为接收函数的输出参数。这里仅介绍发送结构体没有的成员:

  1. Timestamp :只有使能了时间触发模式才有用,记录时间戳
  2. FilterMatchIndex :这条报文被接收是通过哪个筛选器

接收用到的函数如下:

HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);

参数:

  1. *hcan :can的句柄,由CubeMX自动帮我们定义
  2. RxFifo :接收FIFO号。参数: CAN_RX_FIFO0 或 CAN_RX_FIFO1
  3. pHeader :接收结构体,这里作为输出参数
  4. aData[] :接收数组,这里作为输出参数

示例:

#include <stdio.h>

CAN_RxHeaderTypeDef can_Rx;
uint8_t recvBuf[8];

uint8_t uartBuf[64];

int main(void)
{
  	HAL_Init();
 	SystemClock_Config();
  	MX_GPIO_Init();
  	MX_CAN_Init();
    MX_USART1_UART_Init()

    CAN_FilterTypeDef can_Filter = {0};
    
    can_Filter.FilterIdHigh = 0;
    can_Filter.FilterIdLow = 0;
    can_Filter.FilterMaskIdHigh = 0;
    can_Filter.FilterMaskIdLow = 0;
    can_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
    can_Filter.FilterBank = 0;
    can_Filter.FilterMode = CAN_FILTERMODE_IDMASK;
    can_Filter.FilterScale = CAN_FILTERSCALE_32BIT;
    can_Filter.FilterActivation = CAN_FILTER_ENABLE;
    HAL_CAN_ConfigFilter(&hcan1, &can_Filter);
    
    HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
    
    HAL_CAN_Start(&hcan1);

  	while (1)
  	{

  	}
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    uint16_t len = 0;
    
    HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &can_Rx, recvBuf);

    if(can_Rx.IDE == CAN_ID_STD)
    {
        len += sprintf((char *)&uartBuf[len], "标准ID:%#X; ", can_Rx.StdId);
    }
    else if(can_Rx.IDE == CAN_ID_EXT)
    {
        len += sprintf((char *)&uartBuf[len], "扩展ID:%#X; ", can_Rx.ExtId);
    }
    
    if(can_Rx.RTR == CAN_RTR_DATA)
    {
        len += sprintf((char *)&uartBuf[len], "数据帧; 数据为:");
        
        for(int i = 0; i < can_Rx.DLC; i ++)
        {
            len += sprintf((char *)&uartBuf[len], "%X ", recvBuf[i]);
        }
        
        len += sprintf((char *)&uartBuf[len], "\r\n");
        HAL_UART_Transmit(&huart1, uartBuf, len, 100);        
    }
    else if(can_Rx.RTR == CAN_RTR_REMOTE)
    {
        len += sprintf((char *)&uartBuf[len], "遥控帧\r\n");
        HAL_UART_Transmit(&huart1, uartBuf, len, 100);        
    }    
}

效果:接收CAN总线上所有数据,并将内容通过串口打印出来

 

STM32 CAN初始化详解

CAN是控制器域网 (Controller Area Network, CAN) 的简称,是由研发和生产汽车电子产品著称的德国BOSCH公司开发了的,并最终成为国际标准(ISO11898)。是国际上应用最广泛的现场总线之一。 在北美和西欧,CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。近年来,其所具有的高可靠性和良好的错误检测能力受到重视,被广泛应用于汽车计算机控制系统和环境温度恶劣、电磁辐射强和振动大的工业环境。
原文链接:https://blog.csdn.net/qq_20017379/article/details/125902421

u8 CAN1_Mode_Init(u8 tsjw, u8 tbs2,u8 tbs1, u16 brp, u8 mode)
{

    /* gpio结构体 */
    GPIO_InitTypeDef GPIO_InitStructure;

    /* can 初始化结构体 */
    CAN_InitTypeDef        CAN_InitStructure;

    /* can过滤器结构体 */
    CAN_FilterInitTypeDef  CAN_FilterInitStructure;

    /* 使能时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                                    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

    /* 初始化gpio
        设置引脚
        复用模式
        推挽
        速率100
        上拉
    */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* 复用pa11 pa12为can功能 */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1);

    /* 初始化can结构体 */
    /*事件触发消息传输机制
    在TTCAN模式下,CAN硬件的内部定时器被激活,并且被用于产生发送与接收邮箱的)时间戳
    为了使can满足,适合实时性和可靠性要求特别高或有安全性要求的场合
    路上各节点取得同步后, 消息只能根据调度表在规定的时间隙传输, 避免了消息传输的冲突、仲裁,消息传 
 输时延短, 且可预知
    */
    CAN_InitStructure.CAN_TTCM=DISABLE;

    /* 软件自动离线管理
    ENABLE:一旦硬件检测到128 次11位连续的隐性位,则自动退出离线状态
    将ABOM设1后,一旦检测到条件会自动恢复的,不需要人工干预
    如果ABOM位为’1’,bxCAN进入离线状态后,就自动开启恢复过程。
    如果ABOM位为’0’,软件必须先请求bxCAN进入然后再退出初始化模式,随后恢复过程才被开启
    */
    CAN_InitStructure.CAN_ABOM=DISABLE;

    /* 睡眠模式禁用
    软件通过对CAN_MCR寄存器的SLEEP位置’1’,来请求进入这一模式。在该模式下,bxCAN的时钟停止了,但软件仍然可以访问邮箱寄存器。
    当bxCAN处于睡眠模式,软件必须对CAN_MCR寄存器的INRQ位置’1’并且同时对SLEEP位清’0’,才能进入初始化模式。
    有2种方式可以唤醒(退出睡眠模式)bxCAN:通过软件对SLEEP位清’1’,或硬件检测到CAN总线的活动。
    如果CAN_MCR寄存器的AWUM位为’1’,一旦检测到CAN总线的活动,硬件就自动对SLEEP位清’0’来唤醒bxCAN。如果CAN_MCR寄存器的AWUM位为’0’,软件必须在唤醒中断里对SLEEP位清’0’才能退出睡眠状态。

    注: 如果唤醒中断被允许(CAN_IER寄存器的WKUIE位为’1’),那么一旦检测到CAN总线活动就会产生唤醒中断,而不管硬件是否会自动唤醒bxCAN。
    在对SLEEP位清’0’后,睡眠模式的退出必须与CAN总线同步,当硬件对SLAK位清’0’时,就确认了睡眠模式的退出。
    */
    CAN_InitStructure.CAN_AWUM=DISABLE;

    /* 自动重传使能
    该模式主要用于满足CAN标准中,时间触发通信选项的需求。通过对CAN_MCR寄存器的NART位置’1’,来让硬件工作在该模式。
    在该模式下,发送操作只会执行一次。如果发送操作失败了,不管是由于仲裁丢失或出错,硬件都不会再自动发送该报文。
    */
    CAN_InitStructure.CAN_NART=ENABLE;

    /*
    报文不锁定,新报文覆盖旧报文
    */
    CAN_InitStructure.CAN_RFLM=DISABLE;

    /* 优先级由报文标识符决定
    本成员用于选择CAN报文发送优先级判定方法
    用于选择CAN报文发送优先级判定方法
    */
    CAN_InitStructure.CAN_TXFP=DISABLE;

    /*
        #define CAN_Mode_Normal   正常模式
        #define CAN_Mode_LoopBack 回环模式 自己发,自己收
        回环模式下,它自己的输出端的所有内容都直接传输到自己的输入端,输出端的内容同时也会被传输到总线上,
        即也可使用总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。使用回环模式可以进行自检。
        #define CAN_Mode_Silent   静默模式
        静默模式下,它自己的输出端的逻辑 0 数据会直接传输到它自己的输入端,逻辑1
        可以被发送到总线,所以它不能向总线发送显性位(逻辑 0),只能发送隐性位(逻辑 1)。
        输入端可以从总线接收内容。由于它只可发送的隐性位不会强制影响总线的状态,
        所以把它称为静默模式。这种模式一般用于监测,它可以用于分析总线上的流量,但又不会因为发送显性位而影响总线
        #define CAN_Mode_Silent_LoopBack    静默回环模式
        回环静默模式是以上两种模式的结合,自己的输出端的所有内容都直接传输到自己的输入端,并且不会向总线发送显性位影响总线,
        不能通过总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。
        这种方式可以在“热自检”时使用,即自我检查的时候,不会干扰总线
    */
    CAN_InitStructure.CAN_Mode= mode;

    /*
        重新同步跳跃宽度(SJW) 。定义了在每位中可以延长或缩短多少个时间单元的上限。其值可以编程为1到4个时间单元
    */
    CAN_InitStructure.CAN_SJW=tsjw;

    /*
        时间段1(BS1):定义采样点的位置。其值可以编程为1到16个时间单元,但也可以被自动延长,
        以补偿因为网络中不同节点的频率差异所造成的相位的正向漂移。
    */
    CAN_InitStructure.CAN_BS1=tbs1;

    /*
        时间段2(BS2):定义发送点的位置。其值可以编程为1到8个时间单元,但也可以被自动缩短以补偿相位的负向漂移。
    */
    CAN_InitStructure.CAN_BS2=tbs2;

    /*
        分频率
    */
    CAN_InitStructure.CAN_Prescaler=brp;

    /* 初始化结构体 */
    CAN_Init(CAN1, &CAN_InitStructure);

    /* 初始化过滤器 */
    /*
      选择过滤器0~13 for one can register
    */
    CAN_FilterInitStructure.CAN_FilterNumber = 0;

    /*
        屏蔽位模式和标识符列表模式
        #define CAN_FilterMode_IdMask       ((uint8_t)0x00)  
        #define CAN_FilterMode_IdList       ((uint8_t)0x01)
    */
    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;

    /*  过滤器的位数
        #define CAN_FilterScale_16bit       ((uint8_t)0x00)
        #define CAN_FilterScale_32bit       ((uint8_t)0x01)
    */
    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;

    /*
        32位ID 高位
    */
    CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32??ID

    /*
        32位ID 低位
    */
    CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;

    /* 屏蔽位高字节 */
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;

    /* 屏蔽位低字节 */
    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;

    /* 设定接收FIFO */
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;

    /* 激活过滤组 */
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;

    /* 初始化过滤器 */
    CAN_FilterInit(&CAN_FilterInitStructure);

    /* 配置can中断*/
    NVIC_InitTypeDef  NVIC_InitStructure;
    CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
    NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    return 0;
}  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/79781.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IC流程中 DFT 学习笔记(2)

引言 DFT是ASIC芯片设计流程中不可或缺的环节。其主要目的是在芯片前端设计验证完成后插入一些诸如寄存器链等可供测试的逻辑&#xff0c;算是IC后端设计的范畴&#xff0c;属于结构测试而非功能测试。主要是在ASIC芯片流片完成后&#xff0c;通过这些已插入的逻辑&#xff0c…

国家一带一路和万众创业创新的方针政策指引下,Live Market探索跨境产业的创新发展

现代社会&#xff0c;全球经济互联互通&#xff0c;跨境产业也因此而崛起。为了推动跨境产业的创新发展&#xff0c;中国政府提出了“一带一路”和“万众创业、万众创新”的方针政策&#xff0c;旨在促进全球经济的互联互通和创新发展。在这个大环境下&#xff0c;Live Market积…

华为PPPOE配置实验

华为PPPOE配置实验 网络拓扑图拓扑说明电信ISP设备配置用户拨号路由器配置查看是否拨上号是否看不懂&#xff1f; 看不懂就对了&#xff0c;只是记录一下命令。至于所有原理&#xff0c;等想写了再写 网络拓扑图 拓扑说明 用户路由器用于模拟家用拨号路由器&#xff0c;该设备…

github以及上传代码处理

最近在github上传代码的时候出现了&#xff1a; /video_parser# git push -u origin main Username for https://github.com: gtnyxxx Password for https://gtny2010github.com: remote: Support for password authentication was removed on August 13, 2021. remote: Plea…

STM32——SPI外设总线

SPI外设简介 STM32内部集成了硬件SPI收发电路&#xff0c;可以由硬件自动执行时钟生成、数据收发等功能&#xff0c;减轻CPU的负担 可配置8位/16位数据帧、高位先行/低位先行 时钟频率&#xff1a; fPCLK / (2, 4, 8, 16, 32, 64, 128, 256) 支持多主机模型、主或从操作 可…

HTTP与HTTPS的区别

面试常见问题&#xff0c;HTTPS优化总结易记版&#xff1a; 1、HSTS重定向技术&#xff1a;将http自动转换为https&#xff0c;减少301重定向 2、TLS握手优化&#xff1a;在TLS握手完成前客户端就提前向服务器发送数据 3、会话标识符&#xff1a;服务器记录下与某客户端的会…

C#语音播报问题之 无法嵌入互操作类型SpVoiceClass,请改用适用的窗口

C#语音播报问题之 无法嵌入互操作类型SpVoiceClass&#xff0c;请改用适用的窗口 解决办法如下&#xff1a; 只需要将引入的Interop.SpeechLib的属性嵌入互操作类型改为false 改为false 即可解决&#xff01;

微服务最佳实践,零改造实现 Spring Cloud Apache Dubbo 互通

作者&#xff1a;孙彩荣 很遗憾&#xff0c;这不是一篇关于中间件理论或原理讲解的文章&#xff0c;没有高深晦涩的工作原理分析&#xff0c;文后也没有令人惊叹的工程数字统计。本文以实际项目和代码为示例&#xff0c;一步一步演示如何以最低成本实现 Apache Dubbo 体系与 S…

面试之ReentrantLock

一&#xff0c;ReentrantLock 1.ReentrantLock是什么&#xff1f; ReentrantLock实现了Lock接口&#xff0c;是一个可重入且独占式的锁&#xff0c;和Synchronized关键字类似&#xff0c;不过ReentrantLock更灵活&#xff0c;更强大&#xff0c;增加了轮询、超时、中断、公平锁…

k8s v1.27.4二进制部署记录

记录二进制部署过程 #!/bin/bash#升级内核 update_kernel() {rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.orgyum -y install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpmyum --disablerepo"*" --enablerepo"elrepo-kernel&q…

carla中lka实现(二)

前言&#xff1a; 首先计算之前检测出来的车道线的中线与输入图像的中线进行计算距离&#xff0c;&#xff0c;并设置不同的阈值对于不同的方向进行相关的调整。 一、车辆中心线 一般而言将摄像头架设在车辆的正中心轴上&#xff0c;所获得的图像的中间线极为车辆的中心。 …

Element Plus el-table 数据为空时自定义内容【默认为 No Data】

1. 通过 Table 属性设置 <div class"el-plus-table"><el-table empty-text"暂无数据" :data"tableData" style"width: 100%"><el-table-column prop"date" label"Date" width"180" /&g…

[HDLBits] Exams/m2014 q4d

Implement the following circuit: module top_module (input clk,input in, output out);always(posedge clk) beginout<out^in;end endmodule直接写out^in就行

前端如何安全的渲染HTML字符串?

在现代的Web 应用中&#xff0c;动态生成和渲染 HTML 字符串是很常见的需求。然而&#xff0c;不正确地渲染HTML字符串可能会导致安全漏洞&#xff0c;例如跨站脚本攻击&#xff08;XSS&#xff09;。为了确保应用的安全性&#xff0c;我们需要采取一些措施来在安全的环境下渲染…

Docker 常规软件安装

1. 总体安装步骤 1. 搜索镜像 search 2. 拉取镜像 pull 3. 查看镜像 images 4. 启动镜像 - 端口映射 run 5. 停止容器 stop 6. 移除容器 rm 2. 安装tomcat 1. 搜索 docker search tomcat 2. 拉取 docker pull tomcat 3. 查看本地镜像 docker images tomcat 4. 创建容器实…

python Requests

Requests概述 官方文档&#xff1a;http://cn.python-requests.org/zh_CN/latest/,Requests是python的HTTP的库&#xff0c;我们可以安全的使用 Requests安装 pip install Requests -i https://pypi.tuna.tsinghua.edu.cn/simple Requests的使用 Respose的属性 属性说明url响…

TCP中窗口和滑动窗口的含义以及流量控制

一.窗口 在TCP中由于要保证可靠性&#xff0c;所以每发送一条数据后&#xff0c;都需要接收方返回一条应答报文&#xff0c;要是我们每发送一条数据&#xff0c;发送方就等待接收应答报文&#xff0c;收到之后再去发送下一条数据&#xff0c;这样我们就会花费大量的时间在等待应…

【数据结构】栈和队列常见题目

文章目录 有效的括号用队列实现栈两个队列实现栈一个队列实现栈 用栈实现队列设计循环队列最小栈栈的压入&弹出序列逆波兰表达式 队列&#xff1a;先进先出 栈&#xff1a;后进先出 有效的括号 https://leetcode.cn/problems/valid-parentheses/ class Solution { public:b…

Linux —— 进程间通信

目录 一&#xff0c;进程间通信 二&#xff0c;管道 匿名管道 命名管道 一&#xff0c;进程间通信 进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09;&#xff0c;即在不同进程之间进行信息的传播或交换&#xff1b;由于一般进程用户地址空间是…

高效使用ChatGPT之ChatGPT客户端

ChatGPT客户端&#xff0c;支持Mac, Windows, and Linux 下载地址见文章结尾 软件截图 Windows: Mac&#xff1a; 说明 chatgpt桌面版&#xff0c;相比于网页版的chatgpt&#xff0c;最大的特色是支持历史聊天对话记录导出&#xff0c;且支持三种格式&#xff1a;PNG、PDF、…