STM32F10X CAN+TJA1050中断 接受例程详解,测试无误
生活随笔
收集整理的這篇文章主要介紹了
STM32F10X CAN+TJA1050中断 接受例程详解,测试无误
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
硬件平臺:STM32F10X內部CAN模塊?+?TJA1050?+?JLink
軟件平臺:Keil?4?
一、結果演示
二、接受程序例程
程序涉及的模塊有:
USART:通用同步異步收發器,即串口,用于發送數據至上位機顯示已接收到的數據;
RCC:復位及時鐘控制模塊,用于初始化STM32?外設時鐘及設置CAN總線通信的波特率;
GPIO:通用輸入輸出口;
NVIC:中斷服務程序;
CAN:STM32F10X自帶的CAN通信模塊,F1系列只有1個CAN,F4系列含有2個CAN,大容量的由2個,小容量的只有一個;
Delay:延時等待模塊
Led:用led燈來指示是否正常發送,系統是否工作正常。
RCC
#include "Rcc.h"void RCC_Init(void){ ErrorStatus HSEStartUpStatus; //定義枚舉類型錯誤狀態變量 RCC_DeInit();//復位系統時鐘設置 RCC_HSEConfig(RCC_HSE_ON); //打開外部高速時鐘晶振,使能HSE/*RCC_HSE_ON 開_off 關 _bypass hse晶振被外部時鐘旁路*/ HSEStartUpStatus = RCC_WaitForHSEStartUp();/*RCC_WaitForHSEStartUp()返回一個ErrorStatus枚舉值,success好,error未好*/ if(HSEStartUpStatus == SUCCESS)//HES就緒{ RCC_HCLKConfig(RCC_SYSCLK_Div1);//AHB時鐘(HCLK)=系統時鐘 RCC_PCLK1Config(RCC_HCLK_Div2);//設置低速AHB時鐘(APB1)為HCLK的2分頻 RCC_PCLK2Config(RCC_HCLK_Div1);//設置高速AHB時鐘(APB2)=HCLK時鐘FLASH_SetLatency(FLASH_Latency_2);//設置FLASH延時周期數為2//使能領取指緩存FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);//設置PLL時鐘源及倍頻系數,為HSE的9倍頻 8MHz * 9 = 72MHz/*void RCC_PLLConfig(u32 RCC_PLLSource, u32 RCC_PLLMul)RCC_PLLSource_HSI_Div2 pll輸入時鐘=hsi/2;RCC_PLLSource_HSE_Div1 pll輸入時鐘 =hseRCC_PLLSource_HSE_Div2 pll輸入時鐘=hse/2RCC_PLLMul_2 ------_16 pll輸入時鐘*2---16pll輸出時鐘不得超過72MHZ*/ RCC_PLLCmd(ENABLE);//ENABLE / DISABLEwhile(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);//等待PLL輸出穩定/*FlagStatus RCC_GetFlagStatus(u8 RCC_FLAG) 檢查指定RCC標志位返回SET OR RESETRCC_FLAG_HSIRDY HSI晶振就緒RCC_FLAG_HSERDYRCC_FLAG_PLLRDYRCC_FLAG_LSERDY RCC_FLAG_LSIRDY.......*/ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//設置PLL為系統時鐘源/*void RCC_SYSCLKConfig(u32 RCC_SYSCLKSource) 設置系統時鐘RCC_SYSCLKSource_HSI RCC_SYSCLKSource_HSE RCC_SYSCLKSource_PLLCLK 選HSI HSE PLL 作為系統時鐘*/ while(RCC_GetSYSCLKSource() != 0x08);//判斷PLL是否是系統時鐘/*u8 RCC_GetSYSCLKSource(void) 返回用作系統時鐘的時鐘源0x00:HSI 0x04:HSE 0x08:PLL */} RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO , ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//U2 U3 時鐘在APB1//打開GPIO時鐘,復用功能,串口1的時鐘 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1時鐘 /*void RCC_APB2PeriphClockCmd(u32 RCC_APB2Periph, FunctionalState NewState) enable 或 disable apb2 外設時鐘RCC_APB2Periph_AFIO 功能復用IO 時鐘RCC_APB2Periph_GPIOA/B/C/D/E GPIOA/B/C/D/E 時鐘RCC_APB2Periph_ADC1/ADC2 ADC1/2 時鐘RCC_APB2Periph_TIM1 RCC_APB2Periph_SPI1RCC_APB2Periph_USART1 RCC_APB2Periph_ALL 全部APB2外設時鐘*/}GPIO
#include "GPIO.h"void MYGPIO_Init(void){GPIO_InitTypeDef GPIO_InitStructure;//GPIO_InitStructure初始化結構體為GPIO_InitTypeDef結構GPIO_DeInit(GPIOA);GPIO_StructInit(&GPIO_InitStructure);//函數:指向結構GPIO_InitTypeDef的指針,待初始化//CAN TX : A12GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO//CAN TX : A11GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO// USART TX :A9GPIO_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,工作狀態:GPIO_MODE_AIN ----- 模擬輸入_IN_FLOATING ----- 浮空輸入_IPD ----- 上拉輸出_IPU ----- 上拉輸入_OUT_OD ----- 開漏輸出_OUT_PP ----- 推挽輸出_AF_OD ----- 復用開漏輸出_AF_PP ----- 復用推挽輸出*/ GPIO_Init(GPIOA , &GPIO_InitStructure);// USART RX :A10GPIO_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,回環模式;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為復位狀態//f10x的庫函數文件里面居然定義了兩個CAN!CAN_StructInit(&CAN_InitStructure);//復位重置所有的成員變量CAN_InitStructure.CAN_TTCM=DISABLE; //enable or disable 時間觸發通訊模式//非時間觸發通信模式 CAN_InitStructure.CAN_ABOM=DISABLE; //enable or disable 自動離線管理//軟件自動離線管理 CAN_InitStructure.CAN_AWUM=DISABLE; //enable or disable 自動喚醒模式//睡眠模式通過軟件喚醒(清除CAN->MCR的SLEEP位)CAN_InitStructure.CAN_NART=ENABLE; //enable or disable 非自動重傳//禁止報文自動傳送 CAN_InitStructure.CAN_RFLM=DISABLE; //enable or disable 接收FIFO 鎖定模式//報文不鎖定,新的覆蓋舊的 CAN_InitStructure.CAN_TXFP=DISABLE; //enable or disable 發送FIFO 優先級//優先級由報文標識符決定 CAN_InitStructure.CAN_Mode= mode; /*CAN_Mode_Normal CAN硬件工作在正常模式CAN_Mode_silent CAN硬件工作在靜默模式CAN_Mode_LoopBack 環回模式CAN_Mode_Silent_LoopBack 靜默環回模式*///模式設置: mode:0,普通模式;1,回環模式; //設置波特率CAN_InitStructure.CAN_SJW=tsjw; /*重新同步跳躍寬度(Tsjw),每位中可以延長或縮短多少個時間單位的上限為tsjw+1個時間單位 CAN_SJW_1tq 重新同步跳躍寬度為 1 個時間單位CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq*/CAN_InitStructure.CAN_BS1=tbs1; /*時間段 1 的時間單位數目 為1--16個時間單位*///Tbs1=tbs1+1個時間單位CAN_BS1_1tq ~CAN_BS1_16tqCAN_InitStructure.CAN_BS2=tbs2; /*時間段 2 的時間單位數目 為1--8個時間單位*///Tbs2=tbs2+1個時間單位CAN_BS2_1tq ~ CAN_BS2_8tqCAN_InitStructure.CAN_Prescaler=brp; /*設定一個時間單位的長度,范圍是1---1024,實際會減一,這是什么鬼???*/ //分頻系數(Fdiv)為 brp+1 因為實際會減一,所以這里有加一???CAN_Init(CAN1, &CAN_InitStructure); //初始化CAN1 //can 過濾器設置CAN_FilterInitStructure.CAN_FilterNumber=0; //指定待初始化的過濾器,范圍是1---13//過濾器0CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; /*CAN_FilterMode_IdMask 標識符屏蔽位模式CAN_FilterMode_IdList 標識符列表模式*///屏蔽位模式CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; /*過濾器位寬 CAN_FilterScale_Two16bit 2 個 16 位過濾器CAN_FilterScale_One32bit 1 個 32 位過濾器因為版本吧 CAN_FilterScale_One32bit 已變為 CAN_FilterScale_32bit*///32位寬 CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; /*設定過濾器標識符,范圍是0x0000---0xFFFF32 位位寬時為其高段位,16 位位寬時為第一個*///32位IDCAN_FilterInitStructure.CAN_FilterIdLow=0x0000;/*設定過濾器標識符,范圍是0x0000---0xFFFF32 位位寬時為其低段位,16 位位寬時為第二個*/CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;/*設定過濾器屏蔽標識符或者過濾器標識符,范圍是0x0000---0xFFFF32 位位寬時為其高段位,16 位位寬時為第一個*///32位MASKCAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;/*設定過濾器屏蔽標識符或者過濾器標識符,范圍是0x0000---0xFFFF32 位位寬時為其低段位,16 位位寬時為第二個*/CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//設定了過濾器指向的FIFO : 0或1/*CAN_FilterFIFO0 過濾器 FIFO 指向 過濾器xCAN_FilterFIFO1 過濾器 FIF1 指向 過濾器x *///過濾器0關聯到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活過濾器0 enable or disableCAN_FilterInit(&CAN_FilterInitStructure); //濾波器初始化CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE); /*enable or disable can中斷CAN_IT_FMP0 FIFO0消息掛號中斷允許. */ NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;//USB 低優先級 or CAN 接收 0 中斷NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主優先級為1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次優先級為0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure); return 0; //配置成功返回 0 }//如果是開啟了,就有中斷服務函數 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
#include "led.h"//初始化PB12和13為輸出口.并使能這兩個口的時鐘 void LED_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口時鐘 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口速度為50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //根據設定參數初始化GPIOBGPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);}歡迎討論,共同學習
總結
以上是生活随笔為你收集整理的STM32F10X CAN+TJA1050中断 接受例程详解,测试无误的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAN总线接口芯片SIT1050Q和TJ
- 下一篇: 功能强大的开源网络监控工具:LibreN