STM32 cubemx CAN

news2024/12/27 11:16:57

接收用到的结构体如下: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;
}  

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习笔记整理-DOM-02-事件监听

一、什么是"事件监听" DOM允许书写JavaScript代码以让HTML元素对事件作出反应什么是"事件": 用户与网页的交互动作当用户点击元素时当鼠标移动到元素上时当文本框的内容被改变时当键盘在文本框中被按下时当网页已加载完毕时… “监听”&#xff0c;顾名思义…

项目实战 — 博客系统② {项目构建}

目录 一、创建项目 二、添加数据库 三、设置配置文件相关信息 四、 添加前端页面 五、构建项目分层 六、编写基本类 一、创建项目 二、添加数据库 -- 创建数据库 drop database if exists cat_blog; create database cat_blog DEFAULT CHARACTER SET utf8mb4;-- 使用数…

这四种订货系统不能选(一):不能独立品牌

随着商业环境的日益竞争和客户需求的不断变化&#xff0c;订货系统正逐渐成为企业管理中不可或缺的一部分。不少企业在订货系统的选择上不知从哪入手&#xff0c;今天我分享哪四种订货系统不能选。大家点个关注点个赞&#xff0c;我们接着往下看。 一、不能独立品牌的订货系统不…

C语言学习笔记---数据的存储详解

C语言程序设计笔记---015 C语言数据的存储1、数据类型的意义1.1、unsigned与signed数据类型例程11.2、补码与原码相互转换例程2 2、大小端的介绍2.1、大小端的例程12.2、大小端的例程2 --- 判断当前编译器环境属于大端或小端 3、综合练习题探究数据的存储3.1、练习题13.2、练习…

Qt 杂项(Qwt、样式等)

Qt隐藏窗口边框 this->setWindowFlags(Qt::FramelessWindowHint);Qt模态框 this->setWindowModality(Qt::ApplicationModal);QLable隐藏border 代码中设置 lable->setStyleSheet("border:0px");或者UI中直接设置样式&#xff1a;“border:0px” Qwt开源…

vue3 使用@vue-office/excel预览本地excel文件 demo

vue3 使用vue-office/excel预览excel文件 demo 显示如下&#xff1a; npm地址&#xff1a;https://www.npmjs.com/package/vue-office/excel vue-office还有pdf和docx&#xff0c;按需下载对应插件 npm install vue-office/excel vue-demivue代码如下 app.vue <templ…

2.Model、ModelMap和ModelAndView的使用详解

1.前言 最近SSM框架开发web项目&#xff0c;用得比较火热。spring-MVC肯定用过&#xff0c;在请求处理方法可出现和返回的参数类型中&#xff0c;最重要就是Model和ModelAndView了&#xff0c;对于MVC框架&#xff0c;控制器Controller执行业务逻辑&#xff0c;用于产生模型数据…

腾讯云国际站代充-阿里云ECS怎么一键迁移到腾讯云cvm?

今天主要来介绍一下如何通过阿里云国际ECS控制台一键迁移至腾讯云国际CVM。腾讯云国际站云服务器CVM提供全面广泛的服务内容。无-需-绑-定PayPal&#xff0c;代-充-值腾讯云国际站、阿里云国际站、AWS亚马逊云、GCP谷歌云&#xff0c;官方授权经销商&#xff01;靠谱&#xff0…

嵌入式Qt开发—Excel表格数据导出

有一个嵌入式Excel表格数据导出的需求&#xff1a;应用软件运行于嵌入式Linux平台上&#xff0c;在设备运行过程中&#xff0c;存储了许多数据&#xff0c;这些数据想以表格的形式导出。考虑到Windows平台的普遍性&#xff0c;需要将数据以excel表格形式导出&#xff0c;故选择…

基于机器学习的假新闻检测 -- 机器学习项目基础篇(14)

不同平台上的假新闻正在广泛传播&#xff0c;这是一个令人严重关切的问题&#xff0c;因为它导致社会稳定和人们之间建立的纽带的永久破裂。很多研究已经开始关注假新闻的分类。 在这里&#xff0c;我们将尝试在Python中的机器学习的帮助下解决这个问题。 主要步骤 导入库和数…

一生一芯4——使用星火应用商店在ubuntu下载QQ、微信、百度网盘

星火应用商店可以非常方便的完成一些应用的下载&#xff0c;下面是官方网址 http://spark-app.store/download 我使用的是intel处理器&#xff0c;无需下载依赖项&#xff0c;直接点击软件本体 我这里下载amd64,根据自己的处理器下载对应版本 sudo apt install ./spark-stor…

影响股票数据接口l2传输数据快慢因素有哪些?(l2数据接口)

股票数据接口l2是一种用于获取股票市场相关数据的编程接口。它允许开发者通过编程的方式获取、查询、订阅和更新股票相关数据&#xff0c;如股票价格、成交量、财务数据等&#xff0c;并将这些数据用于自己的应用或系统中。l2数据接口通常提供实时行情数据、历史行情数据、财务…

如何批量替换文件名称的一部分?

如何批量替换文件名称的一部分&#xff1f;在工作和生活中&#xff0c;我们经常需要对一些文件和文件夹进行批量修改操作&#xff0c;其中最常见的是对文件名进行部分更改&#xff0c;例如批量替换文件名中的一部分分子。这些操作不仅可以提高工作效率&#xff0c;还能帮助我们…

elementUI 的上传组件<el-upload>,自定义上传按钮样式

方法一&#xff1a; 原理&#xff1a;调用<el-upload>组件的方法唤起选择文件事件 效果&#xff1a; 页面代码&#xff1a; 1、选择图片按钮 <div class"flex_row_spacebetween btn" click"chooseImg"><span class"el-icon-plus ic…

Boost开发指南-4.4assign

assign 许多情况下我们都需要为容器初始化或者赋值&#xff0c;填入大量的数据&#xff0c;比如初始错误代码和错误信息&#xff0c;或者是一些测试用的数据。在C98中标准容器仅提供了容纳这些数据的方法&#xff0c;但填充的步骤却是相当地麻烦&#xff0c;必须重复调用inser…

财报解读:继续押注Disney+,迪士尼距离盈利还有多远?

迪士尼最新一季的“答卷”&#xff0c;透露着不小的寒气。 近日&#xff0c;迪士尼披露了2023财年第三季度&#xff08;自然年2023年Q2&#xff09;业绩报告&#xff0c;营收223.3亿美元&#xff0c;同比仅增长4%&#xff0c;低于市场预期的225.1亿美元&#xff1b;归母净亏损…

Python第三方库 - Pandas库

文章目录 1. Pandas介绍2. Pandas基础2.1 引入2.2 数据结构2.2.1 Series2.3 DataFrame2.3.1 概念 3 Pandas CSV 文件3.1 语法3.2 遇到的问题 参考文档 1. Pandas介绍 概念: Pandas 是 Python 的核心数据分析支持库&#xff0c;提供了快速、灵活、明确的数据结构&#xff0c;旨…

【Vue-Router】重定向

First.vue <template><h1>First Seciton</h1> </template>Second.vue&#xff0c;Third.vue代码同理 UserSettings.vue <template><h1>UserSettings</h1><router-link to"/settings/children1">children1</ro…

41、可靠传输——停等ARQ

前面两节内容我们学习了传输层的基本概况的一些知识&#xff0c;包括传输层在TCP/IP协议栈中负责的任务、传输层的两大协议&#xff0c;以及端口号、套接字等一些基本的概念。从这一节开始&#xff0c;我们将开启两大协议中TCP协议的学习。 但是&#xff0c;经过之前的学习&am…

企望制造ERP系统 RCE漏洞复现(HW0day)

0x01 产品简介 企望制造纸箱业erp系统由深知纸箱行业特点和业务流程的多位IT专家打造&#xff0c;具有国际先进的管理方式&#xff0c;将现代化的管理方式融入erp软件中&#xff0c;让企业分分钟就拥有科学的管理经验。 erp的功能包括成本核算、报价定价、订单下达、生产下单、…