国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā)

這篇具有很好參考價(jià)值的文章主要介紹了stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

??最近在使用can總線,由于這個(gè)以前接觸的比較少,所以調(diào)試代碼的時(shí)候直接是下載的正點(diǎn)原子的例程,在這個(gè)基礎(chǔ)上修改調(diào)試的。現(xiàn)在將調(diào)試中遇到的問題,總結(jié)一下,避免以后踩坑。目前寫了一個(gè)查詢方式的,一個(gè)中斷方式的。項(xiàng)目代碼下載地址:
https://download.csdn.net/download/qq_20222919/87793221

查詢方式

??首先說查詢模式,查詢模式直接使用原子的例程就可以使用。初始化代碼如下:

CAN_HandleTypeDef   g_canx_handler;     /* CANx句柄 */
CAN_TxHeaderTypeDef g_canx_txheader;    /* 發(fā)送參數(shù)句柄 */
CAN_RxHeaderTypeDef g_canx_rxheader;    /* 接收參數(shù)句柄 */

uint8_t can_init( uint32_t tsjw, uint32_t tbs2, uint32_t tbs1, uint16_t brp, uint32_t mode )
{
    g_canx_handler.Instance = CAN1;
    g_canx_handler.Init.Prescaler = brp;                /* 分頻系數(shù)(Fdiv)為brp+1 */
    g_canx_handler.Init.Mode = mode;                    /* 模式設(shè)置 */
    g_canx_handler.Init.SyncJumpWidth = tsjw;           /* 重新同步跳躍寬度(Tsjw)為tsjw+1個(gè)時(shí)間單位 CAN_SJW_1TQ~CAN_SJW_4TQ */
    g_canx_handler.Init.TimeSeg1 = tbs1;                /* tbs1范圍CAN_BS1_1TQ~CAN_BS1_16TQ */
    g_canx_handler.Init.TimeSeg2 = tbs2;                /* tbs2范圍CAN_BS2_1TQ~CAN_BS2_8TQ */
    g_canx_handler.Init.TimeTriggeredMode = DISABLE;    /* 非時(shí)間觸發(fā)通信模式 */
    g_canx_handler.Init.AutoBusOff = DISABLE;           /* 軟件自動(dòng)離線管理 */
    g_canx_handler.Init.AutoWakeUp = DISABLE;           /* 睡眠模式通過軟件喚醒(清除CAN->MCR的SLEEP位) */
     //報(bào)文自動(dòng)傳送開啟后,當(dāng)數(shù)據(jù)發(fā)送失敗時(shí),can芯片會(huì)自動(dòng)重發(fā)數(shù)據(jù),直到數(shù)據(jù)發(fā)送成功,會(huì)造成程序假死狀態(tài)。
    g_canx_handler.Init.AutoRetransmission = DISABLE;    /* 禁止報(bào)文自動(dòng)傳送 */
    g_canx_handler.Init.ReceiveFifoLocked = DISABLE;    /* 報(bào)文不鎖定,數(shù)據(jù)溢出后新的數(shù)據(jù)覆蓋舊的,如果使能鎖定,數(shù)據(jù)溢出后新的數(shù)據(jù)會(huì)被丟掉 */
    g_canx_handler.Init.TransmitFifoPriority = DISABLE; /* 優(yōu)先級(jí)由報(bào)文標(biāo)識(shí)符決定 */
    if ( HAL_CAN_Init( &g_canx_handler ) != HAL_OK )
    {
        return 1;
    }
    CAN_FilterTypeDef sFilterConfig;
    /*配置CAN過濾器*/
    sFilterConfig.FilterBank = 0;                             /* 過濾器0 */
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh = 0x0000;                      /* 32位ID */
    sFilterConfig.FilterIdLow = 0x0000;
    sFilterConfig.FilterMaskIdHigh = 0x0000;                  /* 32位MASK */
    sFilterConfig.FilterMaskIdLow = 0x0000;
    sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;    /* 過濾器0關(guān)聯(lián)到FIFO0 */
    sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;       /* 激活濾波器0 */
    sFilterConfig.SlaveStartFilterBank = 14;

    /* 過濾器配置 */
    if ( HAL_CAN_ConfigFilter( &g_canx_handler, &sFilterConfig ) != HAL_OK )
    {
        return 2;
    }
    /* 啟動(dòng)CAN外圍設(shè)備 */
    if ( HAL_CAN_Start( &g_canx_handler ) != HAL_OK )
    {
        return 3;
    }
    return 0;
}
void HAL_CAN_MspInit( CAN_HandleTypeDef *hcan )
{
    if ( CAN1 == hcan->Instance )
    {
        CAN_RX_GPIO_CLK_ENABLE();       /* CAN_RX腳時(shí)鐘使能 */
        CAN_TX_GPIO_CLK_ENABLE();       /* CAN_TX腳時(shí)鐘使能 */
        __HAL_RCC_CAN1_CLK_ENABLE();    /* 使能CAN1時(shí)鐘 */
        GPIO_InitTypeDef gpio_init_struct;
        gpio_init_struct.Pin = CAN_TX_GPIO_PIN;
        gpio_init_struct.Mode = GPIO_MODE_AF_PP;
        gpio_init_struct.Pull = GPIO_PULLUP;
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
        gpio_init_struct.Alternate = GPIO_AF9_CAN1;
        HAL_GPIO_Init( CAN_TX_GPIO_PORT, &gpio_init_struct ); /* CAN_TX腳 模式設(shè)置 */
        gpio_init_struct.Pin = CAN_RX_GPIO_PIN;
        HAL_GPIO_Init( CAN_RX_GPIO_PORT, &gpio_init_struct ); /* CAN_RX腳 必須設(shè)置成輸入模式 */
    }
}

?? 接收函數(shù)使用查詢的方式,在接收函數(shù)值會(huì)不停的查詢FIFO中數(shù)據(jù)的長度,如果數(shù)據(jù)長度不為0,說明就接收到了數(shù)據(jù)。在主函數(shù)中不停地讀取接收函數(shù)返回的數(shù)據(jù)長度,通過數(shù)據(jù)長度判斷是否接收到了數(shù)據(jù)。

uint8_t can_receive_msg( uint32_t id, uint8_t *buf )
{
    if ( HAL_CAN_GetRxFifoFillLevel( &g_canx_handler, CAN_RX_FIFO0 ) == 0 ) /* 沒有接收到數(shù)據(jù) */
    {
        return 0;
    }
    if ( HAL_CAN_GetRxMessage( &g_canx_handler, CAN_RX_FIFO0, &g_canx_rxheader, buf ) != HAL_OK ) /* 讀取數(shù)據(jù) */
    {
        return 0;
    } 
    return g_canx_rxheader.DLC;
}

?? 發(fā)送函數(shù)

uint8_t can_send_msg( uint32_t id, uint8_t *msg, uint8_t len )
{
    uint32_t TxMailbox = CAN_TX_MAILBOX0;
    g_canx_txheader.StdId = id;         /* 標(biāo)準(zhǔn)標(biāo)識(shí)符 */
    g_canx_txheader.ExtId = id;         /* 擴(kuò)展標(biāo)識(shí)符(29位) */
    // g_canx_txheader.IDE = CAN_ID_STD;   /* 使用標(biāo)準(zhǔn)幀 */
    g_canx_txheader.IDE = CAN_ID_EXT; /* 使用擴(kuò)展幀 */
    g_canx_txheader.RTR = CAN_RTR_DATA; /* 數(shù)據(jù)幀 */
    g_canx_txheader.DLC = len;
    if ( HAL_CAN_AddTxMessage( &g_canx_handler, &g_canx_txheader, msg, &TxMailbox ) != HAL_OK ) /* 發(fā)送消息 */
    {
        return 1;
    }
    while (HAL_CAN_GetTxMailboxesFreeLevel(&g_canx_handler) != 3); /* 等待發(fā)送完成,所有郵箱為空 */
    return 0;
}

?? 在主函數(shù)中不停的查詢接收數(shù)據(jù)長度,如果接收到了數(shù)據(jù),就把接收到的數(shù)據(jù)發(fā)送出去。

int main( void )
{  
    uint8_t i = 0, t = 0;
    uint8_t cnt = 0;
    uint8_t canbuf[8];
    uint8_t rxlen = 0;
    uint8_t res;
    uint8_t mode = 1; /* CAN工作模式: 0,普通模式; 1,環(huán)回模式 */
    uint16_t count = 0;

    HAL_Init();                             /* 初始化HAL庫 */
    sys_stm32_clock_init( 336, 10, 2, 7 );   /* 設(shè)置時(shí)鐘,168Mhz */
    delay_init( 168 );                      /* 延時(shí)初始化 */
    usart_init( 115200 );                   /* 串口初始化為115200 */
 
    // can_init(CAN_SJW_1TQ, CAN_BS2_6TQ, CAN_BS1_7TQ, 6, CAN_MODE_LOOPBACK);  /* CAN初始化, 環(huán)回模式, 波特率500Kbps  采樣點(diǎn)位置占57% */
    can_init( CAN_SJW_1TQ, CAN_BS2_6TQ, CAN_BS1_7TQ, 24, CAN_MODE_NORMAL ); /* CAN初始化, 正常模式, 波特率125Kbps  采樣點(diǎn)位置占 57.1% */

    RE_DE( 1 );						  /* 485 設(shè)置為發(fā)送模式 */
    printf( "stm32f407 can test! \r\n" );
    while ( 1 )
    {
        rxlen = can_receive_msg( 0x12, canbuf ); /* CAN ID = 0x12, 接收數(shù)據(jù)查詢 */
        if ( rxlen ) /* 接收到有數(shù)據(jù) */
        {            
            printf( "接收到數(shù)據(jù) %d : ID:0x%08X  data: ", count++, g_canx_rxheader.ExtId );
            for ( i = 0; i < 8; i++ )
            {
                printf( "%02X ", canbuf[i] );   /* 輸出接收到的數(shù)據(jù) */
            }
            printf( "\r\n" );
            can_send_msg( 0x02A300F0 + t, canbuf, 8 ); /* ID = 0x12, 發(fā)送8個(gè)字節(jié) */
        }            
        t++;
        delay_ms( 10 );
        if ( t == 200 )
        {
            t = 0;
            cnt++;
            for ( i = 0; i < 8; i++ )
            {
                canbuf[i] = cnt + i;    /* 填充發(fā)送緩沖區(qū) */
            }
//   res = can_send_msg(0x12, canbuf, 8);    /* ID = 0x12, 發(fā)送8個(gè)字節(jié) */
        }
    }
}

??這里需要注意一個(gè)小問題,在初始化的時(shí)候,有一個(gè)報(bào)文自動(dòng)傳送的的屬性g_canx_handler.Init.AutoRetransmission,原子在這里設(shè)置的是ENABLE。
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
??經(jīng)過測(cè)試后發(fā)現(xiàn),如果這個(gè)屬性設(shè)置為ENABLE,那么發(fā)送數(shù)據(jù)的過程中,如果硬件電路上出現(xiàn)了故障,比如單片機(jī)can口上的連接線松動(dòng)了,或者是連接線斷了。can控制發(fā)送數(shù)據(jù)時(shí)就會(huì)失敗,此時(shí)控制器就會(huì)一直嘗試著繼續(xù)發(fā)送,can口上就會(huì)一直有高低電平變化,此時(shí)代碼就會(huì)卡在等待數(shù)據(jù)發(fā)送完成這條語句位置處。

while (HAL_CAN_GetTxMailboxesFreeLevel(&g_canx_handler) != 3);

stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
??此時(shí)程序就會(huì)處于假死狀態(tài),如果發(fā)送函數(shù)后面還要執(zhí)行其他代碼的話,就執(zhí)行不了了,除非can控制器將數(shù)據(jù)成功發(fā)送出去。

??如果不想要這種一直等待發(fā)送成功的方式,就將自動(dòng)傳送的屬性設(shè)置為DISABLE,這樣發(fā)送數(shù)據(jù)失敗后,還會(huì)繼續(xù)執(zhí)行下面的代碼。程序不會(huì)形成假死狀態(tài)。

g_canx_handler.Init.AutoRetransmission = DISABLE;

中斷方式

??中斷模式原子的代碼中雖然有一個(gè)宏定義可以開啟中斷,但是宏定義開啟后,中斷的功能依然使用不了。
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
??相當(dāng)于使用中斷接收的功能沒有實(shí)現(xiàn),于是就自己邊查資料邊測(cè)試,摸索著將中斷功能實(shí)現(xiàn)了。
??首先進(jìn)行初始化。

CAN_HandleTypeDef   g_canx_handler;     /* CANx句柄 */
CAN_TxHeaderTypeDef g_canx_txheader;    /* 發(fā)送參數(shù)句柄 */
CAN_RxHeaderTypeDef g_canx_rxheader;    /* 接收參數(shù)句柄 */

uint8_t can_init( uint32_t tsjw, uint32_t tbs2, uint32_t tbs1, uint16_t brp, uint32_t mode )
{
    g_canx_handler.Instance = CAN1;
    g_canx_handler.Init.Prescaler = brp;                /* 分頻系數(shù)(Fdiv)為brp+1 */
    g_canx_handler.Init.Mode = mode;                    /* 模式設(shè)置 */
    g_canx_handler.Init.SyncJumpWidth = tsjw;           /* 重新同步跳躍寬度(Tsjw)為tsjw+1個(gè)時(shí)間單位 CAN_SJW_1TQ~CAN_SJW_4TQ */
    g_canx_handler.Init.TimeSeg1 = tbs1;                /* tbs1范圍CAN_BS1_1TQ~CAN_BS1_16TQ */
    g_canx_handler.Init.TimeSeg2 = tbs2;                /* tbs2范圍CAN_BS2_1TQ~CAN_BS2_8TQ */
    g_canx_handler.Init.TimeTriggeredMode = DISABLE;    /* 非時(shí)間觸發(fā)通信模式 */
    g_canx_handler.Init.AutoBusOff = DISABLE;           /* 軟件自動(dòng)離線管理 */
    g_canx_handler.Init.AutoWakeUp = DISABLE;           /* 睡眠模式通過軟件喚醒(清除CAN->MCR的SLEEP位) */
    //報(bào)文自動(dòng)傳送開啟后,當(dāng)數(shù)據(jù)發(fā)送失敗時(shí),can芯片會(huì)自動(dòng)重發(fā)數(shù)據(jù),直到數(shù)據(jù)發(fā)送成功,會(huì)造成程序假死狀態(tài)。
    g_canx_handler.Init.AutoRetransmission = DISABLE;    /* 禁止報(bào)文自動(dòng)傳送 */
    g_canx_handler.Init.ReceiveFifoLocked = DISABLE;    /* 報(bào)文不鎖鎖定,FIFO裝滿后新的覆蓋舊的,如果設(shè)置報(bào)文鎖定后,F(xiàn)IFO裝滿后新的就會(huì)被丟棄*/
    g_canx_handler.Init.TransmitFifoPriority = DISABLE; /* 優(yōu)先級(jí)由報(bào)文標(biāo)識(shí)符決定 */
    if ( HAL_CAN_Init( &g_canx_handler ) != HAL_OK )
    {
        return 1;
    }

    /* 使用中斷接收 */
    __HAL_CAN_ENABLE_IT( &g_canx_handler, CAN_IT_RX_FIFO0_MSG_PENDING ); /* FIFO0消息掛號(hào)中斷允許 */
    HAL_NVIC_EnableIRQ( CAN1_RX0_IRQn );                        /* 使能CAN中斷 */
    HAL_NVIC_SetPriority( CAN1_RX0_IRQn, 7, 0 );                /* 搶占優(yōu)先級(jí)7,子優(yōu)先級(jí)0 */

    /* HAL_CAN_ActivateNotification() 函數(shù)中會(huì)調(diào)用 __HAL_CAN_ENABLE_IT(hcan, ActiveITs);來開啟指定的中斷,
    所以如果使用了__HAL_CAN_ENABLE_IT()函數(shù)開啟了中斷,就不需要使用HAL_CAN_ActivateNotification()這個(gè)函數(shù)激活中斷   */
    /* 如果不使用 __HAL_CAN_ENABLE_IT()函數(shù)  也可以單獨(dú)使用HAL_CAN_ActivateNotification()函數(shù)  */                                                         /* 啟動(dòng)CAN1 */
//    HAL_CAN_ActivateNotification(&g_canx_handler,CAN_IT_RX_FIFO0_MSG_PENDING);    /* 啟動(dòng)CAN接收中斷-FIFO0接收新消息*/

    CAN_FilterTypeDef sFilterConfig;
    /*配置CAN過濾器*/
    sFilterConfig.FilterBank = 0;                             /* 過濾器0 */
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh = 0x0000;                      /* 32位ID */
    sFilterConfig.FilterIdLow = 0x0000;
    sFilterConfig.FilterMaskIdHigh = 0x0000;                  /* 32位MASK */
    sFilterConfig.FilterMaskIdLow = 0x0000;
    sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;    /* 過濾器0關(guān)聯(lián)到FIFO0 */
    sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;       /* 激活濾波器0 */
    sFilterConfig.SlaveStartFilterBank = 14;

    /* 過濾器配置 */
    if ( HAL_CAN_ConfigFilter( &g_canx_handler, &sFilterConfig ) != HAL_OK )
    {
        return 2;
    }
    /* 啟動(dòng)CAN外圍設(shè)備 */
    if ( HAL_CAN_Start( &g_canx_handler ) != HAL_OK )
    {
        return 3;
    }
    return 0;
}

??中斷模式初始化比查詢模式初始化多了下面三行代碼。

  __HAL_CAN_ENABLE_IT( &g_canx_handler, CAN_IT_RX_FIFO0_MSG_PENDING ); /* FIFO0消息掛號(hào)中斷允許 */
    HAL_NVIC_EnableIRQ( CAN1_RX0_IRQn );     /* 使能CAN中斷 */
    HAL_NVIC_SetPriority( CAN1_RX0_IRQn, 7, 0 );  /* 搶占優(yōu)先級(jí)7,子優(yōu)先級(jí)0 */

?? 首先使用 __HAL_CAN_ENABLE_IT函數(shù)設(shè)置中斷源,接收中斷有下面幾種方式。

/* Receive Interrupts */
#define CAN_IT_RX_FIFO0_MSG_PENDING ((uint32_t)CAN_IER_FMPIE0)  /*!< FIFO 0 message pending interrupt */
#define CAN_IT_RX_FIFO0_FULL        ((uint32_t)CAN_IER_FFIE0)   /*!< FIFO 0 full interrupt            */
#define CAN_IT_RX_FIFO0_OVERRUN     ((uint32_t)CAN_IER_FOVIE0)  /*!< FIFO 0 overrun interrupt         */
#define CAN_IT_RX_FIFO1_MSG_PENDING ((uint32_t)CAN_IER_FMPIE1)  /*!< FIFO 1 message pending interrupt */
#define CAN_IT_RX_FIFO1_FULL        ((uint32_t)CAN_IER_FFIE1)   /*!< FIFO 1 full interrupt            */
#define CAN_IT_RX_FIFO1_OVERRUN     ((uint32_t)CAN_IER_FOVIE1)  /*!< FIFO 1 overrun interrupt         */

?? 這幾種中斷的差異就不一一解釋了,這里使用FIFO0的消息掛起中斷。還有一個(gè)函數(shù) HAL_CAN_ActivateNotification 也可以設(shè)置中斷源。

 HAL_CAN_ActivateNotification(&g_canx_handler,CAN_IT_RX_FIFO0_MSG_PENDING);  
 HAL_NVIC_EnableIRQ( CAN1_RX0_IRQn );     /* 使能CAN中斷 */
 HAL_NVIC_SetPriority( CAN1_RX0_IRQn, 7, 0 );  /* 搶占優(yōu)先級(jí)7,子優(yōu)先級(jí)0 */  

?? 其實(shí)HAL_CAN_ActivateNotification 函數(shù)內(nèi)部也是通過調(diào)用 __HAL_CAN_ENABLE_IT函數(shù)來設(shè)置中斷源的。
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
?? 接下來在初始化回調(diào)函數(shù)中配置IO口。

void HAL_CAN_MspInit( CAN_HandleTypeDef* hcan )
{
    if ( CAN1 == hcan->Instance )
    {
        CAN_RX_GPIO_CLK_ENABLE();       /* CAN_RX腳時(shí)鐘使能 */
        CAN_TX_GPIO_CLK_ENABLE();       /* CAN_TX腳時(shí)鐘使能 */
        __HAL_RCC_CAN1_CLK_ENABLE();    /* 使能CAN1時(shí)鐘 */
        GPIO_InitTypeDef gpio_init_struct;
        gpio_init_struct.Pin = CAN_TX_GPIO_PIN;
        gpio_init_struct.Mode = GPIO_MODE_AF_PP;
        gpio_init_struct.Pull = GPIO_PULLUP;
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
        gpio_init_struct.Alternate = GPIO_AF9_CAN1;
        HAL_GPIO_Init( CAN_TX_GPIO_PORT, &gpio_init_struct ); /* CAN_TX腳 模式設(shè)置 */
        gpio_init_struct.Pin = CAN_RX_GPIO_PIN;
        HAL_GPIO_Init( CAN_RX_GPIO_PORT, &gpio_init_struct ); /* CAN_RX腳 必須設(shè)置成輸入模式 */
    }
}

?? 初始化完成之后,下面就該設(shè)置中斷函數(shù)的入口了,這個(gè)中斷函數(shù)的名稱可以在startup_stm32f407xx.s 文件里面找。
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
?? 在匯編代碼的中斷向量表里面有中斷函數(shù)的名稱,這里有個(gè)CAN1_RX0_IRQHandler 還有個(gè) CAN1_RX1_IRQHandler,那么要使用哪個(gè)呢?
在網(wǎng)上找到相關(guān)資料如下
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
?? 經(jīng)過驗(yàn)證,紅線里面圈出來的說法是正確的,同時(shí)要注意如果要使用FIFO1,那么程序中所有設(shè)置FIFO的地方都得寫成FIFO1.

stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
?? 其中包括中斷號(hào),中斷名稱,中斷入庫函數(shù)名稱,中斷回調(diào)函數(shù)名稱。
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
?? 由于上面初始化的時(shí)候設(shè)置的是使用FIFO0,那么這里的函數(shù)入口名稱就選擇CAN1_RX0_IRQHandler。

void CAN1_RX0_IRQHandler( void )
{
      /* 調(diào)用HAL庫 CAN 中斷入口函數(shù)*/
}

?? 接下來就需要在這個(gè)中斷入口函數(shù)中調(diào)用HAL庫的通用CAN中斷處理函數(shù),那這個(gè)函數(shù)在哪去找呢? 直接打開 stm32f4xx_hal_can.h 頭文件在里面搜索以 IRQHandler結(jié)尾的函數(shù)名。

stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
?? 查找后發(fā)現(xiàn)這個(gè)里面只有一個(gè)函數(shù) HAL_CAN_IRQHandler符合,那么這個(gè)函數(shù)肯定就是HAL庫中CAN中斷的通用入口函數(shù)了。直接在中斷函數(shù)里面添加這個(gè)通用函數(shù)。

void CAN1_RX0_IRQHandler( void )
{
    HAL_CAN_IRQHandler( &g_canx_handler );      /* 調(diào)用HAL庫 CAN 中斷入口函數(shù)*/
}

?? 接下來根據(jù)HAL庫的慣例,在中斷函數(shù)里面肯定還有一個(gè)回調(diào)函數(shù)。接下來就需要去找這個(gè)中斷回調(diào)函數(shù)??梢灾苯犹D(zhuǎn)到 HAL_CAN_IRQHandler函數(shù)內(nèi)部進(jìn)行查看。
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
?? 但是這個(gè)函數(shù)內(nèi)部的代碼有些長,找起來不是很方便,那么就可以在 stm32f4xx_hal_can.h頭文件里直接去找。由于回掉函數(shù)都是以Callback結(jié)尾的,那么就可以直接在 stm32f4xx_hal_can.h文件中搜索 Callback結(jié)尾的函數(shù)。
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷

?? 可以找到一個(gè)Callbacks functions的注釋,那么下面這些函數(shù)就是中斷回調(diào)函數(shù),如果程序?qū)懙帽容^多的時(shí)候,可以不用查找的方法,直接用鼠標(biāo)拖動(dòng)右邊的滾動(dòng)條就可以定位到回調(diào)函數(shù)這一塊。
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
?? 但是這么多函數(shù),到底是哪一個(gè)呢?別著急,還記得在初始化的時(shí)候,使能中斷時(shí)開啟了一個(gè)FIFO0的消息掛起中斷,可以根據(jù)這個(gè)中斷使能的名字去對(duì)比,可以發(fā)現(xiàn)在右邊HAL_CAN_RxFifo0MsgPendingCallback這個(gè)函數(shù)的名字和CAN_IT_RX_FIFO0_MSG_PENDING名稱基本一樣,那么HAL_CAN_RxFifo0MsgPendingCallback這個(gè)函數(shù)肯定就是FIFO0消息掛起中斷的回調(diào)函數(shù)。
stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā),STM32學(xué)習(xí)筆記,軟件技巧,電子知識(shí)分享,單片機(jī),stm32,嵌入式硬件,can,中斷
?? 接下來就可以編寫中斷回調(diào)函數(shù)了。

void  HAL_CAN_RxFifo0MsgPendingCallback( CAN_HandleTypeDef* hcan )
{
    uint8_t rxbuf[8];
    uint32_t id;
    uint8_t i;
    HAL_CAN_GetRxMessage( hcan, CAN_RX_FIFO0, &g_canx_rxheader, rxbuf );  /* 讀取數(shù)據(jù) */
    printf( "接收到 %d 位數(shù)據(jù) : ID:0x%08X  data: ", g_canx_rxheader.DLC, g_canx_rxheader.ExtId );
    for ( i = 0; i < 8; i++ )
    {
        printf( "%02X ", rxbuf[i] );   /* 輸出接收到的數(shù)據(jù) */
    }
    printf( "\r\n" );
}

?? 在中斷回調(diào)函數(shù)里面使用HAL_CAN_GetRxMessage函數(shù)讀取接收到的數(shù)據(jù),并打印出來。到此中斷函數(shù)的代碼就編寫完成了。

?? 接下來就是下載驗(yàn)證的過程了,這里就不一一列舉了。中斷部分的函數(shù),需要注意的地方,在上面基本都分析過了。在調(diào)試的過程中,暫時(shí)也沒發(fā)現(xiàn)其他需要注意的地方。文章來源地址http://www.zghlxwxcb.cn/news/detail-697394.html

到了這里,關(guān)于stm32f407單片機(jī)上通過HAL庫實(shí)現(xiàn)can總線數(shù)據(jù)的收發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 洋桃電子STM32F407單片機(jī)入門教程筆記九:低功耗模式

    洋桃電子STM32F407單片機(jī)入門教程筆記九:低功耗模式

    ??此文檔作為對(duì)洋桃電子STM32F407單片機(jī)視頻的整理,B站鏈接: 第28集)低功耗模式_嗶哩嗶哩_bilibili ????????在之前的程序里應(yīng)用程序在while(1)主循環(huán)中反復(fù)執(zhí)行,ARM內(nèi)核以100%的功率工作。這樣的設(shè)計(jì)簡(jiǎn)單穩(wěn)定,內(nèi)核全速運(yùn)行的功耗也只有幾十毫安,對(duì)于外接電源的設(shè)備

    2024年01月23日
    瀏覽(21)
  • 基于stm32F407的hal庫,移植FreeRTOS的具體步驟和遇到的問題(看正點(diǎn)原子的視頻)

    基于stm32F407的hal庫,移植FreeRTOS的具體步驟和遇到的問題(看正點(diǎn)原子的視頻)

    因?yàn)榘遄邮莝tm32F407的第二版的,所以開始下的資料是舊版本的,但是舊版本的FreeRTOS工程沒有hal庫的,都是標(biāo)準(zhǔn)庫的,這里是下載stm32F407最新版的資料,進(jìn)行移植。 資料可以在正點(diǎn)原子官網(wǎng)下載,如下: http://www.openedv.com/docs/boards/stm32/index.html 一定要下載最新的資料(開始用

    2024年02月06日
    瀏覽(25)
  • 洋桃電子STM32F407單片機(jī)入門教程筆記一:RCC時(shí)鐘設(shè)置

    洋桃電子STM32F407單片機(jī)入門教程筆記一:RCC時(shí)鐘設(shè)置

    此文檔作為對(duì)洋桃電子STM32F407單片機(jī)視頻的整理,B站鏈接:2023更新 STM32入門F4= STM32F407單片機(jī)入門教程=WIFI連接阿里云物聯(lián)網(wǎng)+CubeMX+HAL庫+TFT彩屏+杜洋主講_嗶哩嗶哩_bilibili 由于單片機(jī)內(nèi)部的時(shí)鐘結(jié)構(gòu)都是相互關(guān)聯(lián)的,一個(gè)時(shí)鐘源出發(fā)可以供給多個(gè)功能,類似于樹根、樹桿、樹

    2024年02月04日
    瀏覽(21)
  • STM32F407使用Helix庫軟解MP3并通過DAC輸出,最精簡(jiǎn)的STM32+SD卡實(shí)現(xiàn)MP3播放器

    STM32F407使用Helix庫軟解MP3并通過DAC輸出,最精簡(jiǎn)的STM32+SD卡實(shí)現(xiàn)MP3播放器

    只用STM32單片機(jī)+SD卡+耳機(jī)插座,實(shí)現(xiàn)播放MP3播放器! 看過很多STM32軟解MP3的方案,即不通過類似VS1053之類的解碼器芯片,直接用STM32和軟件庫解碼MP3文件,通常使用了labmad或者Helix解碼庫實(shí)現(xiàn),Helix相對(duì)labmad占用的RAM更少。但是大多數(shù)參考的方案還是用了外接IIS接口WM98xx之類的

    2024年02月12日
    瀏覽(29)
  • 6、單片機(jī)與AT24C02的通訊(IIC)實(shí)驗(yàn)(STM32F407)

    6、單片機(jī)與AT24C02的通訊(IIC)實(shí)驗(yàn)(STM32F407)

    IIC簡(jiǎn)介 I2C(IIC,Inter-Integrated Circuit),兩線式串行總線,由PHILIPS公司開發(fā)用于連接微控制器及其外圍設(shè)備。 它是由數(shù)據(jù)線SDA和時(shí)鐘SCL構(gòu)成的串行總線,可發(fā)送和接收數(shù)據(jù)。在CPU與被控IC之間、IC與IC之間進(jìn)行雙向傳送,高速IIC總線一般可達(dá)400kbps以上。 IIC是半雙工通信方式。 多主機(jī)

    2024年02月20日
    瀏覽(24)
  • 【DRV8323】電機(jī)驅(qū)動(dòng)芯片寄存器配置指南,通過STM32F407的SPI通信配置

    【DRV8323】電機(jī)驅(qū)動(dòng)芯片寄存器配置指南,通過STM32F407的SPI通信配置

    筆者計(jì)劃使用一塊使用到STM32F407控制芯片與DRV8323s驅(qū)動(dòng)芯片的板子,驅(qū)動(dòng)BLDC。了解到需要使用SPI通信來配置DRV8323s驅(qū)動(dòng)芯片,配置過程中涉及DRV8323數(shù)據(jù)手冊(cè)中提及的幾個(gè)寄存器,故寫此文做個(gè)記錄。 另外,DRV8323芯片和DRV8302、DRV8303、DRV8353都有極大的相似之處,可以相互參考

    2024年02月02日
    瀏覽(90)
  • STM32F407實(shí)現(xiàn)1588v2(ptpd)

    STM32F407實(shí)現(xiàn)1588v2(ptpd)

    硬件: STM32F407ZGT6開發(fā)板 軟件: VSCode arm-none-eabi-gcc openOCD st-link 在github搜到一個(gè)在NUCLEO-F429ZI開發(fā)板上移植ptpd的example,因?yàn)楹虵407差別很小,所以就打算用這個(gè)demo移植到手頭的開發(fā)板上。因?yàn)槟壳爸恍枰猻lave,所以只調(diào)試了slave。據(jù)介紹,master好像原作者沒有充分測(cè)試過。 源項(xiàng)

    2024年02月08日
    瀏覽(26)
  • 在Proteus中添加元件庫所沒有的單片機(jī)芯片(STM32F407ZGT6為例)

    在Proteus中添加元件庫所沒有的單片機(jī)芯片(STM32F407ZGT6為例)

    今天在畫仿真圖時(shí)發(fā)現(xiàn)proteus元件庫里的stm32系列并沒有我所需要的。通過百度才到了官網(wǎng)下載相應(yīng)的元件,后自己導(dǎo)入到元件庫! 1、官網(wǎng)鏈接為:https://componentsearchengine.com/part-view/STM32F407ZGT6/STMicroelectronics 先注冊(cè)賬號(hào)后下載相應(yīng)的元件即可。 2、解壓元件的壓縮包 3、打開p

    2024年02月16日
    瀏覽(25)
  • 基于STM32F407實(shí)現(xiàn)超聲波測(cè)距(SR04)

    基于STM32F407實(shí)現(xiàn)超聲波測(cè)距(SR04)

    今天要實(shí)現(xiàn)的功能是超聲波測(cè)距,這一功能在很多的地方都能用到,比如:在智能小車上可以添加超聲波避障功能。今天需要用到SR04超聲波模塊,在使用這一模塊的時(shí)候我很會(huì)接觸到時(shí)序圖。 模塊如圖所示: 模塊有四個(gè)引腳 VCC 供 5V電源, GND 為地線, TRIG 觸 發(fā) 控 制 信 號(hào)

    2024年02月11日
    瀏覽(21)
  • 從STM32F407到AT32F407(一)

    從STM32F407到AT32F407(一)

    雅特力公司的MCU有著性能超群,價(jià)格優(yōu)越的巨大優(yōu)勢(shì),缺點(diǎn)是相關(guān)資料少一些,我們可以充分利用ST的現(xiàn)有資源來開發(fā)它。 我用雅特力的STM32F437開發(fā)板,使用原子?stm32f407的開發(fā)板自帶程序,測(cè)試串口程序,原設(shè)定串口波特率為115200,但是輸出亂碼,波特率改成230400,串口輸

    2024年02月02日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包