stm32——can(二)发送与接收

一、引言 

        书接上篇can基础

二、数据发送 

2.1 发送邮箱

         共有3个发送邮箱供软件来发送报文,发送调度器根据优先级决定哪个邮箱的报文先被发送。

2.2 发送流程 

        发送报文的流程为:应用程序选择1个空置的发送邮箱;设置标识符,数据长度和待发送数据;然后对CAN_TIxR寄存器的TXRQ位置’1’,来请求发送。TXRQ位置’1’后,邮箱就不再是空邮箱;而一旦邮箱不再为空置,软件对邮箱寄存器就不再有写的权限。TXRQ位置1后,邮箱马上进入挂起状态,并等待成为最高优先级的邮箱,参见发送优先级。一旦邮箱成为最高优先级的邮箱,其状态就变为预定发送状态。一旦CAN总线进入空闲状态,预定发送邮箱中的报文就马上被发送(进入发送状态)。一旦邮箱中的报文被成功发送后,它马上变为空置邮箱;硬件相应地对CAN_TSR寄存器的RQCP和TXOK位置1,来表明一次成功发送。

2.3 发送优先级

        通过对CAN_MCR寄存器的TXFP位的设置可以对报文发送优先级模式进行选择。TXFP置0时报文发送优先级按照报文的标识符来决定,TXFP置1时报文发送优先级按照先入先出的方式进行,相当于把发送邮箱配置为FIFO,发送的优先级由发送请求次序决定。

 2.4 数据发送相关寄存器

        1)CAN TX mailbox identifier register (CAN_TIxR) (x=0..2)——发送邮箱标识符寄存器

Bit 0 TXRQ: Transmit mailbox request 

        发送数据时由软件将相应邮箱的寄存器该位置1,发送完成后由硬件清零;

Bit 1 RTR: Remote transmission request
        0: Data frame
        1: Remote frame

Bit 2 IDE: Identifier extension
        This bit defines the identifier type of message in the mailbox.
        0: Standard identifier.
        1: Extended identifier.

Bits 20:3 EXID[17:0]: Extended identifier
        The LSBs of the extended identifier.

Bits 31:21 STID[10:0]/EXID[28:18]: Standard identifier or extended identifier
        The standard identifier or the MSBs of the extended identifier (depending on the IDE bit
value).

        2)CAN mailbox data length control and time stamp register (CAN_TDTxR) (x=0..2)——发送邮箱数据长度和时间戳寄存器

Bits 3:0 DLC[3:0]: Data length code

        1个报文包含0到8个字节数据,而这由DLC决定。

Bits 7:4 Reserved, must be kept at reset value. 

Bit 8 TGT: Transmit global time
        只有在CAN处于时间触发通信模式,即CAN_MCR寄存器的TTCM位为’1’时,该位才有效。
        0:不发送时间戳TIME[15:0];
        1:发送时间戳TIME[15:0]。在长度为8的报文中,时间戳TIME[15:0]是最后2个发送的字节:TIME[7:0]作为第7个字节,TIME[15:8]为第8个字节,它们替换了写入CAN_TDHxR[31:16]的数据(DATA6[7:0]和DATA7[7:0])。为了把时间戳的2个字节发送出去,DLC必须编程为8。

Bits 15:9 Reserved, must be kept at reset value. 

Bits 31:16 TIME[15:0]: Message time stamp

         该域包含了,在发送该报文SOF时刻的16位时间值。

        3) CAN mailbox data low register (CAN_TDLxR) (x=0..2)——发送邮箱的低字节数据寄存器

        4) CAN mailbox data high register (CAN_TDHxR) (x=0..2)——发送邮箱的高字节数据寄存器

Note: If TGT of this message and TTCM are active, DATA7 and DATA6 will be replaced by
the TIME stamp value. 

        5)CAN transmit status register (CAN_TSR)——发送状态寄存器

Bit 0 RQCP0: Request completed mailbox0(该位只能写1或读)
        当上次对邮箱0的发送或停止请求完成时,由硬件对其置1
        软件对该位写’1’可以对其清’0’;当硬件接收到发送请求时也对该位清’0’(CAN_TI0R 寄存器的TXRQ位被置’1’)。
        该位被清’0’时,邮箱0的其它发送状态位(TXOK0, ALST0和TERR0)也被清’0’。

Bit 1 TXOK0: Transmission OK of mailbox0
        每次在邮箱0进行发送尝试后,硬件对该位进行更新:
        0:上次发送尝试失败;
        1:上次发送尝试成功。
Bit 2 ALST0: Arbitration lost for mailbox0
        当邮箱0因为仲裁丢失而导致发送失败时,对该位置’1’

Bit 3 TERR0: Transmission error of mailbox0
        当邮箱0因为出错而导致发送失败时,对该位置’1’。

Bits 6:4 Reserved, must be kept at reset value. 

Bit 7 ABRQ0: Abort request for mailbox0
        该位置1时终止邮箱0的发送,如果邮箱为空则无效。当邮箱0中的报文数据被清除时,该位由硬件置0。

Bit 8~Bit15、Bit16~Bit23与邮箱0一致;

Bits 25:24 CODE[1:0]: Mailbox code
        当有至少1个发送邮箱为空时,这2位表示下一个空的发送邮箱号。
        当所有的发送邮箱都为空时,这2位表示优先级最低的那个发送邮箱号。

Bit 26 TME0: Transmit mailbox 0 empty(该位只读)
        当邮箱1中没有待发送数据时,该位由硬件置1;

Bit 27 TME1: Transmit mailbox 1 empty(该位只读)
        当邮箱1中没有待发送数据时,该位由硬件置1;

Bit 28 TME2: Transmit mailbox 2 empty(该位只读)        

        当邮箱2中没有待发送数据时,该位由硬件置1;

Bit 29 LOW0: Lowest priority flag for mailbox 0(该位只读)

        当多个邮箱等待发送且邮箱0的优先级最低时,该位由硬件置1;

Bit 30 LOW1: Lowest priority flag for mailbox 1(该位只读)
        当多个邮箱等待发送且邮箱1的优先级最低时,该位由硬件置1; 

Bit 31 LOW2: Lowest priority flag for mailbox 2(该位只读)
        当多个邮箱等待发送且邮箱2的优先级最低时,该位由硬件置1;

        如果三个邮箱只有一个邮箱等待发送,则LOW[2:0]被清零。

 2.5 hal库相关函数

/**
  * @brief  Add a message to the first free Tx mailbox and activate the
  *         corresponding transmission request.
  * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
  *         the configuration information for the specified CAN.
  * @param  pHeader pointer to a CAN_TxHeaderTypeDef structure.
  * @param  aData array containing the payload of the Tx frame.
  * @param  pTxMailbox pointer to a variable where the function will return
  *         the TxMailbox used to store the Tx message.
  *         This parameter can be a value of @arg CAN_Tx_Mailboxes.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, const CAN_TxHeaderTypeDef *pHeader,
                                       const uint8_t aData[], uint32_t *pTxMailbox)
{
  uint32_t transmitmailbox;
  HAL_CAN_StateTypeDef state = hcan->State;
  uint32_t tsr = READ_REG(hcan->Instance->TSR);

  /* Check the parameters */
  assert_param(IS_CAN_IDTYPE(pHeader->IDE));
  assert_param(IS_CAN_RTR(pHeader->RTR));
  assert_param(IS_CAN_DLC(pHeader->DLC));
  if (pHeader->IDE == CAN_ID_STD)
  {
    assert_param(IS_CAN_STDID(pHeader->StdId));
  }
  else
  {
    assert_param(IS_CAN_EXTID(pHeader->ExtId));
  }
  assert_param(IS_FUNCTIONAL_STATE(pHeader->TransmitGlobalTime));

  if ((state == HAL_CAN_STATE_READY) ||
      (state == HAL_CAN_STATE_LISTENING))
  {
    //读取CAN_TST寄存器后判断TME0、1、2是否有空邮箱
    /* Check that all the Tx mailboxes are not full */
    if (((tsr & CAN_TSR_TME0) != 0U) ||
        ((tsr & CAN_TSR_TME1) != 0U) ||
        ((tsr & CAN_TSR_TME2) != 0U))
    {
      //选择相应的邮箱并填入需要发送的数据
      /* Select an empty transmit mailbox */
      transmitmailbox = (tsr & CAN_TSR_CODE) >> CAN_TSR_CODE_Pos;

      /* Store the Tx mailbox */
      *pTxMailbox = (uint32_t)1 << transmitmailbox;

      /* Set up the Id */
      if (pHeader->IDE == CAN_ID_STD)
      {
        hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->StdId << CAN_TI0R_STID_Pos) |
                                                           pHeader->RTR);
      }
      else
      {
        hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->ExtId << CAN_TI0R_EXID_Pos) |
                                                           pHeader->IDE |
                                                           pHeader->RTR);
      }

      /* Set up the DLC */
      hcan->Instance->sTxMailBox[transmitmailbox].TDTR = (pHeader->DLC);

      /* Set up the Transmit Global Time mode */
      if (pHeader->TransmitGlobalTime == ENABLE)
      {
        SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TDTR, CAN_TDT0R_TGT);
      }

      /* Set up the data field */
      WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDHR,
                ((uint32_t)aData[7] << CAN_TDH0R_DATA7_Pos) |
                ((uint32_t)aData[6] << CAN_TDH0R_DATA6_Pos) |
                ((uint32_t)aData[5] << CAN_TDH0R_DATA5_Pos) |
                ((uint32_t)aData[4] << CAN_TDH0R_DATA4_Pos));
      WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDLR,
                ((uint32_t)aData[3] << CAN_TDL0R_DATA3_Pos) |
                ((uint32_t)aData[2] << CAN_TDL0R_DATA2_Pos) |
                ((uint32_t)aData[1] << CAN_TDL0R_DATA1_Pos) |
                ((uint32_t)aData[0] << CAN_TDL0R_DATA0_Pos));

      /* Request transmission */
      SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TIR, CAN_TI0R_TXRQ);

      /* Return function status */
      return HAL_OK;
    }
    else
    {
      /* Update error code */
      hcan->ErrorCode |= HAL_CAN_ERROR_PARAM;

      return HAL_ERROR;
    }
  }
  else
  {
    /* Update error code */
    hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;

    return HAL_ERROR;
  }
}

三、数据接收

3.1 接收FIFO

        CAN外设一共有2个接收FIFO,每个FIFO中有3个邮箱,即最多可以缓存6个接收到的报文。can收发器接收数据后报文先经过标识符过滤器识别帧的ID,再决定是否将该报文存入FIFO及存入过滤器关联的哪个FIFO。

3.2 FIFO接收流程

        FIFO从空状态开始,在接收到第一个有效的报文后,FIFO状态变为pending_1,硬件相应地把CAN_RFR寄存器的FMP[1:0]设置为’01’(二进制01b)。软件可以读取FIFO输出邮箱来读出邮箱中的报文,然后通过对CAN_RFR寄存器的RFOM位设置’1’来释放邮箱,这样FIFO又变为空状态了。如果在释放邮箱的同时,又收到了一个有效的报文,那么FIFO仍然保留在pending_1状态,软件可以读取FIFO输出邮箱来读出新收到的报文。
        如果应用程序不释放邮箱,在接收到下一个有效的报文后,FIFO状态变为pending_2,硬件相应地把FMP[1:0]设置为’10’(二进制10b)。重复上面的过程,第三个有效的报文把FIFO变为pending_3状态(FMP[1:0]=11b)。此时,软件必须对RFOM位设置1来释放邮箱,以便FIFO可以有空间来存放下一个有效的报文;否则,下一个有效的报文到来时就会导致一个报文的丢失。

        当FIFO处于pending_3状态(即FIFO的3个邮箱都是满的),下一个有效的报文就会导致溢出,并且一个报文会丢失。此时,硬件对CAN_RFR寄存器的FOVR位进行置’1’来表明溢出情况。至于哪个报文会被丢弃,取决于对FIFO的设置:
● 如果禁用了FIFO锁定功能(CAN_MCR寄存器的RFLM位被清’0’),那么FIFO中最后收到的报文就被新报文所覆盖。这样,最新收到的报文不会被丢弃掉。
● 如果启用了FIFO锁定功能(CAN_MCR寄存器的RFLM位被置’1’),那么新收到的报文就被丢弃,软件可以读到FIFO中最早收到的3个报文。 

3.3 数据接收相关寄存器:

        1)CAN receive FIFO 0 register (CAN_RF0R)——can接收FIFO0寄存器

Bits 1:0 FMP0[1:0]: FIFO0 message pending
        表示当前FIFO0中的存储的报文数量,每新增一个报文到FIFO0中,硬件对FMP加1;

Bit 2 Reserved, must be kept at reset value.

Bit 3 FULL0: FIFO 0 full

        Set by hardware when three messages are stored in the FIFO.

Bit 4 FOVR0: FIFO 0 overrun
        This bit is set by hardware when a new message has been received and passed the filter
while the FIFO was full.

Bit 5 RFOM0: Release FIFO 0 output mailbox

        软件通过对该位置’1’来释放接收FIFO的输出邮箱

        

        2)CAN receive FIFO 1 register (CAN_RF1R)——can接收FIFO1寄存器(与CAN_RF0R类似)

        3)CAN receive FIFO mailbox identifier register (CAN_RIxR) (x=0..1)—— 接收FIFO邮箱标识符寄存器

        4) CAN receive FIFO mailbox data length control and time stamp register
(CAN_RDTxR) (x=0..1)——接收FIFO邮箱数据长度及时间戳寄存器

  Bits 15:8 FMI[7:0]: Filter match index

        包含过滤器的序号; 

         5)CAN receive FIFO mailbox data low register (CAN_RDLxR) (x=0..1)——接收FIFO邮箱低字节数据寄存器

        6)CAN receive FIFO mailbox data high register (CAN_RDHxR) (x=0..1) ——接收FIFO邮箱高字节数据寄存器 

 3.4 hal库相关函数

/**
  * @brief  Get an CAN frame from the Rx FIFO zone into the message RAM.
  * @param  hcan pointer to an CAN_HandleTypeDef structure that contains
  *         the configuration information for the specified CAN.
  * @param  RxFifo Fifo number of the received message to be read.
  *         This parameter can be a value of @arg CAN_receive_FIFO_number.
  * @param  pHeader pointer to a CAN_RxHeaderTypeDef structure where the header
  *         of the Rx frame will be stored.
  * @param  aData array where the payload of the Rx frame will be stored.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo,
                                       CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])
{
  HAL_CAN_StateTypeDef state = hcan->State;

  assert_param(IS_CAN_RX_FIFO(RxFifo));

  if ((state == HAL_CAN_STATE_READY) ||
      (state == HAL_CAN_STATE_LISTENING))
  {
    /* Check the Rx FIFO */
    //通过判断FIFO0或者FIFO1的RF0R或者RF1R寄存器的FMP位段是否为0,确定FIFO中是否有接收的数据
    if (RxFifo == CAN_RX_FIFO0) /* Rx element is assigned to Rx FIFO 0 */
    {
      /* Check that the Rx FIFO 0 is not empty */
      if ((hcan->Instance->RF0R & CAN_RF0R_FMP0) == 0U)
      {
        /* Update error code */
        hcan->ErrorCode |= HAL_CAN_ERROR_PARAM;

        return HAL_ERROR;
      }
    }
    else /* Rx element is assigned to Rx FIFO 1 */
    {
      /* Check that the Rx FIFO 1 is not empty */
      if ((hcan->Instance->RF1R & CAN_RF1R_FMP1) == 0U)
      {
        /* Update error code */
        hcan->ErrorCode |= HAL_CAN_ERROR_PARAM;

        return HAL_ERROR;
      }
    }

    /* Get the header */
    //根据FIFO先入先出的规则,从最先接收报文的邮箱读出报文数据
    pHeader->IDE = CAN_RI0R_IDE & hcan->Instance->sFIFOMailBox[RxFifo].RIR;
    if (pHeader->IDE == CAN_ID_STD)
    {
      pHeader->StdId = (CAN_RI0R_STID & hcan->Instance->sFIFOMailBox[RxFifo].RIR) >> CAN_TI0R_STID_Pos;
    }
    else
    {
      pHeader->ExtId = ((CAN_RI0R_EXID | CAN_RI0R_STID) &
                        hcan->Instance->sFIFOMailBox[RxFifo].RIR) >> CAN_RI0R_EXID_Pos;
    }
    pHeader->RTR = (CAN_RI0R_RTR & hcan->Instance->sFIFOMailBox[RxFifo].RIR);
    if (((CAN_RDT0R_DLC & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_DLC_Pos) >= 8U)
    {
      /* Truncate DLC to 8 if received field is over range */
      pHeader->DLC = 8U;
    }
    else
    {
      pHeader->DLC = (CAN_RDT0R_DLC & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_DLC_Pos;
    }
    pHeader->FilterMatchIndex = (CAN_RDT0R_FMI & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_FMI_Pos;
    pHeader->Timestamp = (CAN_RDT0R_TIME & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_TIME_Pos;

    /* Get the data */
    aData[0] = (uint8_t)((CAN_RDL0R_DATA0 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA0_Pos);
    aData[1] = (uint8_t)((CAN_RDL0R_DATA1 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA1_Pos);
    aData[2] = (uint8_t)((CAN_RDL0R_DATA2 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA2_Pos);
    aData[3] = (uint8_t)((CAN_RDL0R_DATA3 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA3_Pos);
    aData[4] = (uint8_t)((CAN_RDH0R_DATA4 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA4_Pos);
    aData[5] = (uint8_t)((CAN_RDH0R_DATA5 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA5_Pos);
    aData[6] = (uint8_t)((CAN_RDH0R_DATA6 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA6_Pos);
    aData[7] = (uint8_t)((CAN_RDH0R_DATA7 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA7_Pos);

    /* Release the FIFO */
    //将RF0R或者FR1R寄存器的RFOM位置1,释放输出邮箱
    if (RxFifo == CAN_RX_FIFO0) /* Rx element is assigned to Rx FIFO 0 */
    {
      /* Release RX FIFO 0 */
      SET_BIT(hcan->Instance->RF0R, CAN_RF0R_RFOM0);
    }
    else /* Rx element is assigned to Rx FIFO 1 */
    {
      /* Release RX FIFO 1 */
      SET_BIT(hcan->Instance->RF1R, CAN_RF1R_RFOM1);
    }

    /* Return function status */
    return HAL_OK;
  }
  else
  {
    /* Update error code */
    hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;

    return HAL_ERROR;
  }
}

3.5 例程——通过中断读取接收数据

int MX_CAN_Init(void)
{

    /* USER CODE BEGIN CAN_Init 0 */
	HAL_StatusTypeDef HAL_Status = HAL_OK;
	CAN_FilterTypeDef hCAN_Filter;
    /* USER CODE END CAN_Init 0 */

    /* USER CODE BEGIN CAN_Init 1 */

    /* USER CODE END CAN_Init 1 */
    hcan.Instance = CAN1;
    hcan.Init.Mode = CAN_MODE_NORMAL;
    hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
	//baudrate=APB1Clock/((1+bs1+bs2)*Prescaler)=36M/(8*9)=500k
    hcan.Init.Prescaler = 8;
	hcan.Init.TimeSeg1 = CAN_BS1_7TQ;
	hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
    hcan.Init.TimeTriggeredMode = DISABLE;
    hcan.Init.AutoBusOff = DISABLE;
    hcan.Init.AutoWakeUp = DISABLE;
    hcan.Init.AutoRetransmission = DISABLE;
    hcan.Init.ReceiveFifoLocked = DISABLE;
    hcan.Init.TransmitFifoPriority = DISABLE;
    HAL_Status |= HAL_CAN_Init(&hcan);
    /* USER CODE BEGIN CAN_Init 2 */

    /* USER CODE END CAN_Init 2 */
	hCAN_Filter.FilterBank = 0;
	hCAN_Filter.FilterMode = CAN_FILTERMODE_IDMASK;
	hCAN_Filter.FilterScale = CAN_FILTERSCALE_32BIT;
	hCAN_Filter.FilterIdHigh = 0;
	hCAN_Filter.FilterIdLow = 0;
	hCAN_Filter.FilterMaskIdHigh = 0;
	hCAN_Filter.FilterMaskIdLow = 0;
	hCAN_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
	hCAN_Filter.FilterActivation = ENABLE;
	hCAN_Filter.SlaveStartFilterBank = 0;
    HAL_Status |= HAL_CAN_ConfigFilter(&hcan, &hCAN_Filter);

    /*-3- 启动CAN ---------------------------------------------------*/
	HAL_Status |= HAL_CAN_Start(&hcan);

    /*-4- 使能中断通知 ----------------------------------------------*/
    HAL_Status = HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING|CAN_IT_RX_FIFO1_MSG_PENDING);
	if(HAL_Status != HAL_OK)
	{
		printf("halCan init fail\r\n");
	}
	return 0;
}

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(canHandle->Instance==CAN1)
    {
        /* CAN1 clock enable */
        __HAL_RCC_CAN1_CLK_ENABLE();

        __HAL_RCC_GPIOA_CLK_ENABLE();
        /**CAN1 GPIO Configuration
        PA11     ------> CAN1_RX
        PA12     ------> CAN1_TX
        */
        GPIO_InitStruct.Pin = GPIO_PIN_12;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

		GPIO_InitStruct.Pin=GPIO_PIN_11;
		GPIO_InitStruct.Mode=GPIO_MODE_AF_INPUT;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
		HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        /* CAN1 interrupt Init */
        HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
    }
}

void USB_LP_CAN1_RX0_IRQHandler(void)
{
	/* USER CODE BEGIN USB_LP_CAN_RX0_IRQn 0 */

	/* USER CODE END USB_LP_CAN_RX0_IRQn 0 */
	HAL_CAN_IRQHandler(&hcan);
	/* USER CODE BEGIN USB_LP_CAN_RX0_IRQn 1 */

	/* USER CODE END USB_LP_CAN_RX0_IRQn 1 */
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    uint8_t aRxData[8];
	CAN_RxHeaderTypeDef RxHeader;
    if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, aRxData) == HAL_OK)
    {

    }
}

void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    uint8_t aRxData[8];
	CAN_RxHeaderTypeDef RxHeader;
    if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO1, &RxHeader, aRxData) == HAL_OK)
    {

    }
}

  

STM32F205是意法半导体(STMicroelectronics)推出的一款高性能32位ARM Cortex-M3处理器系列单片机。 串口是一种常用的通信方式,用于实现数据在两个设备之间的传输。STM32F205通过提供多个串口接口,方便用户进行通信。DMA(Direct Memory Access)是一种直接内存访问技术,可以在不占用CPU资源的情况下实现数据的高效传输。 STM32F205提供了多个串口接口,包括USART、UART和SPI等通信接口,用户可以根据实际需求选择合适的接口进行数据通信。对于串口的数据传输,STM32F205支持使用DMA进行数据的发送接收。 在使用DMA进行串口发送时,用户可以通过设置相应的寄存器来配置DMA传输的参数,如源地址、目的地址和数据长度等。然后,可以使用HAL库提供的函数来启动DMA传输,如HAL_UART_Transmit_DMA()函数。通过启动DMA传输,数据将从内存中的源地址传输到串口的数据寄存器中,然后通过串口发送出去。在传输完成后,可以通过检查相应的中断标志位来判断传输是否成功。 在使用DMA进行串口接收时,用户可以通过设置相应的寄存器来配置DMA传输的参数,如源地址、目的地址和数据长度等。然后,可以使用HAL库提供的函数来启动DMA传输,如HAL_UART_Receive_DMA()函数。通过启动DMA传输,数据将从串口的数据寄存器中传输到内存中的目的地址中,然后可以通过检查相应的中断标志位来判断接收是否成功。 总结而言,STM32F205可以通过配置寄存器和使用DMA来实现串口的高效发送接收。使用DMA可以减轻CPU的负担,提高数据传输的效率,为用户提供更好的开发性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值