|
硬件平臺(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);
}
|
|