找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 5218|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

STM32F10X CAN+TJA1050中斷 接受例程詳解,測(cè)試無(wú)誤

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:105323 發(fā)表于 2016-3-4 17:40 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
硬件平臺(tái):stm32F10X內(nèi)部CAN模塊 + TJA1050 + JLink
軟件平臺(tái):Keil 4

一、結(jié)果演示



二、接受程序例程
程序涉及的模塊有:
USART:通用同步異步收發(fā)器,即串口,用于發(fā)送數(shù)據(jù)至上位機(jī)顯示已接收到的數(shù)據(jù);
RCC:復(fù)位及時(shí)鐘控制模塊,用于初始化STM32 外設(shè)時(shí)鐘及設(shè)置CAN總線通信的波特率;
GPIO:通用輸入輸出口;
NVIC:中斷服務(wù)程序;
CAN:STM32F10X自帶的CAN通信模塊,F(xiàn)1系列只有1個(gè)CAN,F(xiàn)4系列含有2個(gè)CAN,大容量的由2個(gè),小容量的只有一個(gè);
Delay:延時(shí)等待模塊
Led:用led燈來(lái)指示是否正常發(fā)送,系統(tǒng)是否工作正常。
RCC
#include "Rcc.h"  
void RCC_Init(void)  
{      
     ErrorStatus HSEStartUpStatus;  //定義枚舉類(lèi)型錯(cuò)誤狀態(tài)變量         
     RCC_DeInit();//復(fù)位系統(tǒng)時(shí)鐘設(shè)置         
     RCC_HSEConfig(RCC_HSE_ON); //打開(kāi)外部高速時(shí)鐘晶振,使能HSE  
    /*RCC_HSE_ON  開(kāi)  
     _off 關(guān)  _bypass hse晶振被外部時(shí)鐘旁路*/        
    HSEStartUpStatus = RCC_WaitForHSEStartUp();  
    /*RCC_WaitForHSEStartUp()返回一個(gè)ErrorStatus枚舉值,  
    success好,error未好*/   
     if(HSEStartUpStatus == SUCCESS)//HES就緒  
     {         
         RCC_HCLKConfig(RCC_SYSCLK_Div1);  
         //AHB時(shí)鐘(HCLK)=系統(tǒng)時(shí)鐘   
         RCC_PCLK1Config(RCC_HCLK_Div2);  
         //設(shè)置低速AHB時(shí)鐘(APB1)為HCLK的2分頻   
         RCC_PCLK2Config(RCC_HCLK_Div1);  
         //設(shè)置高速AHB時(shí)鐘(APB2)=HCLK時(shí)鐘  
         FLASH_SetLatency(FLASH_Latency_2);  
         //設(shè)置FLASH延時(shí)周期數(shù)為2  
         //使能領(lǐng)取指緩存  
         FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);  
         RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  
         //設(shè)置PLL時(shí)鐘源及倍頻系數(shù),為HSE的9倍頻 8MHz * 9 = 72MHz  
         /*void RCC_PLLConfig(u32 RCC_PLLSource, u32 RCC_PLLMul)  
         RCC_PLLSource_HSI_Div2   pll輸入時(shí)鐘=hsi/2;  
         RCC_PLLSource_HSE_Div1   pll輸入時(shí)鐘 =hse  
         RCC_PLLSource_HSE_Div2   pll輸入時(shí)鐘=hse/2  
         RCC_PLLMul_2  ------_16       pll輸入時(shí)鐘*2---16  
         pll輸出時(shí)鐘不得超過(guò)72MHZ*/   
         RCC_PLLCmd(ENABLE);  
         //ENABLE  / DISABLE  
         while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);//等待PLL輸出穩(wěn)定  
         /*FlagStatus RCC_GetFlagStatus(u8 RCC_FLAG)  檢查指定RCC標(biāo)志位  
         返回SET OR RESET  
         RCC_FLAG_HSIRDY  HSI晶振就緒  
         RCC_FLAG_HSERDY  
         RCC_FLAG_PLLRDY  
         RCC_FLAG_LSERDY   
         RCC_FLAG_LSIRDY.......*/     
         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  
         //設(shè)置PLL為系統(tǒng)時(shí)鐘源  
         /*void RCC_SYSCLKConfig(u32 RCC_SYSCLKSource)  設(shè)置系統(tǒng)時(shí)鐘  
         RCC_SYSCLKSource_HSI   
         RCC_SYSCLKSource_HSE   
         RCC_SYSCLKSource_PLLCLK  選HSI  HSE PLL 作為系統(tǒng)時(shí)鐘*/                 while(RCC_GetSYSCLKSource() != 0x08);  
         //判斷PLL是否是系統(tǒng)時(shí)鐘  
         /*u8 RCC_GetSYSCLKSource(void)  返回用作系統(tǒng)時(shí)鐘的時(shí)鐘源  
         0x00:HSI   0x04:HSE 0x08:PLL */  
     }     
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |   
                                                    RCC_APB2Periph_AFIO , ENABLE);  
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);  
     //U2  U3 時(shí)鐘在APB1  
     //打開(kāi)GPIO時(shí)鐘,復(fù)用功能,串口1的時(shí)鐘                                      RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1時(shí)鐘        
     /*void RCC_APB2PeriphClockCmd(u32 RCC_APB2Periph, FunctionalState NewState)   
        enable 或 disable apb2 外設(shè)時(shí)鐘  
     RCC_APB2Periph_AFIO  功能復(fù)用IO 時(shí)鐘  
     RCC_APB2Periph_GPIOA/B/C/D/E   GPIOA/B/C/D/E 時(shí)鐘  
     RCC_APB2Periph_ADC1/ADC2           ADC1/2 時(shí)鐘  
     RCC_APB2Periph_TIM1   
     RCC_APB2Periph_SPI1  
     RCC_APB2Periph_USART1   
     RCC_APB2Periph_ALL         全部APB2外設(shè)時(shí)鐘*/  
}  

GPIO
#include "GPIO.h"  
void MYGPIO_Init(void)  
{  
     GPIO_InitTypeDef GPIO_InitStructure;  
    //GPIO_InitStructure初始化結(jié)構(gòu)體為GPIO_InitTypeDef結(jié)構(gòu)  
     GPIO_DeInit(GPIOA);  
     GPIO_StructInit(&GPIO_InitStructure);  
    //函數(shù):指向結(jié)構(gòu)GPIO_InitTypeDef的指針,待初始化  

    //CAN TX  : A12  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽  
    GPIO_Init(GPIOA, &GPIO_InitStructure);          //初始化IO  
    //CAN TX  : A11  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //上拉輸入  
    GPIO_Init(GPIOA, &GPIO_InitStructure);          //初始化IO  

    // USART TX :A9  
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;   
    //GPIO_SPEED:GPIO_SPEED_10MHz/_2MHz/_50MHz   最高輸出速率  
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    /*Mode,工作狀態(tài):GPIO_MODE_AIN  ----- 模擬輸入  
                                                        _IN_FLOATING  ----- 浮空輸入  
                                                        _IPD  ----- 上拉輸出  
                                                        _IPU  ----- 上拉輸入  
                                                        _OUT_OD  ----- 開(kāi)漏輸出  
                                                        _OUT_PP  ----- 推挽輸出  
                                                        _AF_OD  ----- 復(fù)用開(kāi)漏輸出  
                                                        _AF_PP  ----- 復(fù)用推挽輸出*/   
     GPIO_Init(GPIOA , &GPIO_InitStructure);  

     // USART RX :A10  
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;   
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
     //IO浮空輸入  
     GPIO_Init(GPIOA, &GPIO_InitStructure);  
     //初始化  
}  

CAN
#include "can.h"  
#include "delay.h"  
#include "usart.h"  

//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);  
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回環(huán)模式;  
u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)  
{   
    CAN_InitTypeDef         CAN_InitStructure;  
    CAN_FilterInitTypeDef   CAN_FilterInitStructure;  
NVIC_InitTypeDef        NVIC_InitStructure;  

CAN_DeInit(CAN1);//重置can1為復(fù)位狀態(tài)  
    //f10x的庫(kù)函數(shù)文件里面居然定義了兩個(gè)CAN!  
    CAN_StructInit(&CAN_InitStructure);//復(fù)位重置所有的成員變量  
    CAN_InitStructure.CAN_TTCM=DISABLE;   
    //enable or disable 時(shí)間觸發(fā)通訊模式  
    //非時(shí)間觸發(fā)通信模式   
    CAN_InitStructure.CAN_ABOM=DISABLE;      
    //enable or disable 自動(dòng)離線管理  
    //軟件自動(dòng)離線管理     
    CAN_InitStructure.CAN_AWUM=DISABLE;      
    //enable or disable 自動(dòng)喚醒模式  
    //睡眠模式通過(guò)軟件喚醒(清除CAN->MCR的SLEEP位)  

    CAN_InitStructure.CAN_NART=ENABLE;            
    //enable or disable 非自動(dòng)重傳  
    //禁止報(bào)文自動(dòng)傳送   

    CAN_InitStructure.CAN_RFLM=DISABLE;           
    //enable or disable 接收FIFO 鎖定模式  
    //報(bào)文不鎖定,新的覆蓋舊的   
    CAN_InitStructure.CAN_TXFP=DISABLE;           
    //enable or disable 發(fā)送FIFO 優(yōu)先級(jí)  
    //優(yōu)先級(jí)由報(bào)文標(biāo)識(shí)符決定   
    CAN_InitStructure.CAN_Mode= mode;           
    /*CAN_Mode_Normal  CAN硬件工作在正常模式  
        CAN_Mode_silent  CAN硬件工作在靜默模式  
        CAN_Mode_LoopBack 環(huán)回模式  
        CAN_Mode_Silent_LoopBack  靜默環(huán)回模式*/  
    //模式設(shè)置: mode:0,普通模式;1,回環(huán)模式;   
    //設(shè)置波特率  
    CAN_InitStructure.CAN_SJW=tsjw;               
    /*重新同步跳躍寬度(Tsjw),每位中可以延長(zhǎng)或縮短多少個(gè)時(shí)間單位的上限  
    為tsjw+1個(gè)時(shí)間單位   
    CAN_SJW_1tq  重新同步跳躍寬度為 1 個(gè)時(shí)間單位  
    CAN_SJW_2tq   
    CAN_SJW_3tq   
    CAN_SJW_4tq*/  
    CAN_InitStructure.CAN_BS1=tbs1;               
    /*時(shí)間段 1 的時(shí)間單位數(shù)目  為1--16個(gè)時(shí)間單位*/  
    //Tbs1=tbs1+1個(gè)時(shí)間單位CAN_BS1_1tq ~CAN_BS1_16tq  
    CAN_InitStructure.CAN_BS2=tbs2;               
    /*時(shí)間段 2 的時(shí)間單位數(shù)目  為1--8個(gè)時(shí)間單位*/  
    //Tbs2=tbs2+1個(gè)時(shí)間單位CAN_BS2_1tq ~ CAN_BS2_8tq  
    CAN_InitStructure.CAN_Prescaler=brp;         
    /*設(shè)定一個(gè)時(shí)間單位的長(zhǎng)度,范圍是1---1024,實(shí)際會(huì)減一,這是什么鬼???*/   
    //分頻系數(shù)(Fdiv)為 brp+1 因?yàn)閷?shí)際會(huì)減一,所以這里有加一???  
    CAN_Init(CAN1, &CAN_InitStructure);         //初始化CAN1   

    //can 過(guò)濾器設(shè)置  
    CAN_FilterInitStructure.CAN_FilterNumber=0;   
    //指定待初始化的過(guò)濾器,范圍是1---13  
    //過(guò)濾器0  
    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;     
    /*CAN_FilterMode_IdMask   標(biāo)識(shí)符屏蔽位模式  
        CAN_FilterMode_IdList   標(biāo)識(shí)符列表模式*/  
    //屏蔽位模式  
    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;   
    /*過(guò)濾器位寬   
    CAN_FilterScale_Two16bit  2 個(gè) 16 位過(guò)濾器  
    CAN_FilterScale_One32bit  1 個(gè) 32 位過(guò)濾器  
    因?yàn)榘姹景?CAN_FilterScale_One32bit 已變?yōu)?CAN_FilterScale_32bit*/  
    //32位寬   
    CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;      
    /*設(shè)定過(guò)濾器標(biāo)識(shí)符,范圍是0x0000---0xFFFF  
    32 位位寬時(shí)為其高段位,16 位位寬時(shí)為第一個(gè)*/  
    //32位ID  
    CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;  
    /*設(shè)定過(guò)濾器標(biāo)識(shí)符,范圍是0x0000---0xFFFF  
    32 位位寬時(shí)為其低段位,16 位位寬時(shí)為第二個(gè)*/  

    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;  
    /*設(shè)定過(guò)濾器屏蔽標(biāo)識(shí)符或者過(guò)濾器標(biāo)識(shí)符,范圍是0x0000---0xFFFF  
    32 位位寬時(shí)為其高段位,16 位位寬時(shí)為第一個(gè)*/  
    //32位MASK  
    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;  
    /*設(shè)定過(guò)濾器屏蔽標(biāo)識(shí)符或者過(guò)濾器標(biāo)識(shí)符,范圍是0x0000---0xFFFF  
    32 位位寬時(shí)為其低段位,16 位位寬時(shí)為第二個(gè)*/  

    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;  
    //設(shè)定了過(guò)濾器指向的FIFO : 0或1  
    /*CAN_FilterFIFO0  過(guò)濾器 FIFO 指向 過(guò)濾器x  
      CAN_FilterFIFO1       過(guò)濾器 FIF1 指向 過(guò)濾器x  */  
    //過(guò)濾器0關(guān)聯(lián)到FIFO0  
    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;  
    //激活過(guò)濾器0   enable or disable  

    CAN_FilterInit(&CAN_FilterInitStructure);           //濾波器初始化  

CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);               
    /*enable or disable can中斷  
    CAN_IT_FMP0   FIFO0消息掛號(hào)中斷允許.        */   

    NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;  
    //USB 低優(yōu)先級(jí) or CAN 接收 0 中斷  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;      
    // 主優(yōu)先級(jí)為1  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;              
    // 次優(yōu)先級(jí)為0  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    NVIC_Init(&NVIC_InitStructure);   

return 0; //配置成功返回 0   
}  

//如果是開(kāi)啟了,就有中斷服務(wù)函數(shù)                 
void USB_LP_CAN1_RX0_IRQHandler(void)  
{  
  CanRxMsg RxMessage;  
    int i=0;  
    can_ack = 1;  
  CAN_Receive(CAN1, 0, &RxMessage);  
    for(i=0;i<8;i++)  
    can_rx[ i ]=RxMessage.Data[ i ];  
}  

Led

[html] view plain copy 在CODE上查看代碼片派生到我的代碼片
#include "led.h"  

//初始化PB12和13為輸出口.并使能這兩個(gè)口的時(shí)鐘           

void LED_Init(void)  
{   
GPIO_InitTypeDef  GPIO_InitStructure;   
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   //使能PB端口時(shí)鐘   
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13;               
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //推挽輸出  
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //IO口速度為50MHz  
GPIO_Init(GPIOB, &GPIO_InitStructure);             //根據(jù)設(shè)定參數(shù)初始化GPIOB  
GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);  
}  
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:486587 發(fā)表于 2019-6-17 02:44 | 只看該作者
謝謝樓主
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表