新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 基于STM32的CAN總線通信程序

基于STM32的CAN總線通信程序

作者: 時間:2016-11-24 來源:網(wǎng)絡(luò) 收藏
#include

#include "sys.h"
#include "delay.h"
#include "CAN.h"
CAN_msg CAN_TxMsg; //發(fā)送郵箱
CAN_msg CAN_RxMsg; //接收郵箱
u8 CAN_TxRdy=0; //發(fā)送就緒標(biāo)志
u8 CAN_RxRdy=0; //接收就緒標(biāo)志
u8CAN_TDTxR_DLC; //數(shù)據(jù)長度,最高為1111
/////////////////CAN設(shè)置/////////////////////////////////////
void CAN_setup(void)
{
u8 brp=20; //獲取主時鐘頻率 APB1ENR時鐘頻率為36M
RCC->APB1ENR|=1<<25; //RCC_APB1ENR_CANEN; //開啟CAN使能時鐘
RCC->APB2ENR|=1<<0; //RCC_APB2ENR_AFIOEN; //開啟輔助時鐘
AFIO->MAPR&=0XFFFF9FFF;//清除復(fù)用重映射配置寄存器13,14位,
AFIO->MAPR|=0X00004000;//配置為10;IO口重映射至PB8.PB9
RCC->APB2ENR|=1<<3; //RCC_APB2ENR_IOPBEN;//開啟IO口B時鐘
GPIOB->CRH&=~(0X0F<<0);//清除PB8狀態(tài)寄存器~(1111<<0)
GPIOB->CRH|=(0X08<<0);//設(shè)定pb8上下拉輸入1000
GPIOB->CRH&=~(0XF<<4);//清空pb9狀態(tài)寄存器
GPIOB->CRH|=(0X0B<<4);//設(shè)定PB9推挽輸出
MY_NVIC_Init(1,1,USB_HP_CAN_TX_IRQChannel,2);//發(fā)送中斷使能
MY_NVIC_Init(1,1,USB_LP_CAN_RX0_IRQChannel,2);//接收中斷使能
CAN->MCR|=1<<4;//置NART位為1,禁止自動重傳 403
CAN->MCR|=1<<0; //置INRQ位為1,請求初始化 403 (CAN_MCR_NART|CAN_MCR_INRQ);//初始化模式,禁止重傳
CAN->IER|=1<<0;//發(fā)送郵箱空中斷允許 409
CAN->IER|=1<<1; //FIFO0消息掛號中斷允許 409 (CAN_IER_FMPIE0|CAN_IER_TMEIE);
//brp=(brp/18)/500000;//波特率設(shè)置500Kb/s,計算波特率分頻器值
CAN->BTR&=~(((0X03)<<24)|((0x07)<<20)|((0x0f)<<16)|(0x1ff)); //清空BTR寄存器相關(guān)位 410 400
CAN->BTR|=(((1&0X03)<<24)|((7&0X07)<<20)|((8&0X0F)<<16)|(brp-1));//設(shè)置BTR寄存器 410 400

}
//////////////從初始化模式進入正常工作模式/////////////////////////////////////////////
void CAN_start(void)
{
CAN->MCR&=0xfffffffe;
while(CAN->MSR&(0x01));
CAN->MCR&=0xfffffffd; //清零INRQ位,進入正常模式
//while(~(CAN->MSR&0x01)); //等待硬件對INAK位清零,確認退出初始化
}
//////////////設(shè)置工作模式///////////////////////////////////////////
void CAN_testmode(void)
{
CAN->BTR&=0x3fffffff;//清空BTR 的SILM LBKM位410
CAN->BTR|=0XC0000000;//設(shè)置BTR 的LBKM位為高,環(huán)回模式 410

}
///////////////檢測發(fā)送郵箱為空////////////////////////////////////////////////
void CAN_waitReady(void)
{
while((CAN->TSR&(1<<26))==0); //檢測發(fā)送郵箱0標(biāo)志位,為1則為空,為0不為空
CAN_TxRdy=1; //置發(fā)送就緒標(biāo)志位為1
}
///////////////發(fā)送數(shù)據(jù)//////////////////////////////////////
void CAN_wrMsg(CAN_msg *msg)
{
CAN->sTxMailBox[0].TIR=(u8)0; //發(fā)送郵箱標(biāo)示符寄存器復(fù)位 清零
if(msg->format ==STANDARD_FORMAT)//如果是標(biāo)準(zhǔn)11位標(biāo)示符幀
{msg->id=33 ;
CAN->sTxMailBox[0].TIR|=0x4200000;//(msg->id<<21)|CAN_ID_STD; //則標(biāo)示符左移21位,高11位為標(biāo)準(zhǔn)標(biāo)示符,標(biāo)示符選擇位置0 411
}
else //如果是29位擴展標(biāo)示符幀
{
CAN->sTxMailBox[0].TIR|=(u8)(msg->id<<3)|CAN_ID_EXT; //標(biāo)示符左移3位,高29位為標(biāo)示符(擴展標(biāo)示符)標(biāo)示符選擇位置1 411
}
if(msg->type==DATA_FRAME) //如果消息為數(shù)據(jù)幀
{
CAN->sTxMailBox[0].TIR|=CAN_RTR_DATA;//標(biāo)示符寄存器RTR位置0,數(shù)據(jù)幀
}
else //如果為遠程幀
{
CAN->sTxMailBox[0].TIR|=CAN_RTR_REMOTE;//標(biāo)示符寄存器RTR置1,遠程幀
}
CAN->sTxMailBox[0].TDLR=(((u8)msg->data[3]<<24)|((u8)msg->data[2]<<16)|((u8)msg->data[1]<<8)|((u8)msg->data[0])); //數(shù)據(jù)位低4字節(jié)寫入發(fā)送郵箱0



CAN->sTxMailBox[0].TDHR=(((u8)msg->data[7]<<24)|((u8)msg->data[6]<<16)|((u8)msg->data[5]<<8)|((u8)msg->data[4])); //數(shù)據(jù)位高4字節(jié)寫入發(fā)送郵箱0



CAN->sTxMailBox[0].TDTR&=0xfffffff0;//設(shè)置消息長度DLC清0
CAN->sTxMailBox[0].TDTR|=0x00000004;//設(shè)置消息長度為4個字節(jié)
CAN->IER|=1<<0; //發(fā)送郵箱空中斷使能 409
CAN->sTxMailBox[0].TIR|=1<<0; //發(fā)送消息411

}
///////////////讀取郵箱數(shù)據(jù)并釋放//////////////////////////////////////////////////////////////
void CAN_rdMsg(CAN_msg *msg)
{
if((CAN->sFIFOMailBox[0].RIR&CAN_ID_EXT)==0) //如果是11位標(biāo)準(zhǔn)標(biāo)識符
{
msg->format=STANDARD_FORMAT; //消息為標(biāo)準(zhǔn)格式
msg->id=(u32)0x000007ff&(CAN->sFIFOMailBox[0].RIR>>21); //標(biāo)示符等于標(biāo)示符位右移21位與0x7ff
}
else //如果是29位擴展標(biāo)識符
{
msg->format=EXTENDED_FORMAT; //消息格式為擴展標(biāo)示符格式
msg->id=(u32)0x0003ffff&(CAN->sFIFOMailBox[0].RIR>>3);//標(biāo)示符等于標(biāo)示符位右移3位與上0x3ffff
}
if((CAN->sFIFOMailBox[0].RIR&CAN_RTR_REMOTE)==0) //如果消息為數(shù)據(jù)幀
{
msg->type=DATA_FRAME;
}
else //數(shù)據(jù)位遠程幀
{
msg->type=REMOTE_FRAME;
}
msg->len = (unsigned char)0x0000000F & CAN->sFIFOMailBox[0].RDTR; //讀取數(shù)據(jù)長度

msg->data[0] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR); //讀取數(shù)據(jù)低4字節(jié)
msg->data[1] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 8);
msg->data[2] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 16);
msg->data[3] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 24);

msg->data[4] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR); //讀取數(shù)據(jù)高4字節(jié)
msg->data[5] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 8);
msg->data[6] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 16);
msg->data[7] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 24);

本文引用地址:http://m.butianyuan.cn/article/201611/320933.htm

CAN->RF0R |= 1<<5; //釋放接收郵箱0 407
}
////////////////////////設(shè)置標(biāo)示符過濾器組/////////////////////////////////////////////////////////////////////////////

void CAN_wrFilter (unsigned int id, unsigned char format)
{
static unsigned short CAN_filterIdx = 0; //標(biāo)示符設(shè)置數(shù)量索引
unsigned int CAN_msgId = 0; //變量用于存儲需要設(shè)定的標(biāo)示符

if (CAN_filterIdx > 13) //檢查CAN過濾器是否已滿,最高到13
{
return; //如果已滿-返回
}
if (format == STANDARD_FORMAT) //如果是標(biāo)準(zhǔn)幀,標(biāo)準(zhǔn)幀是11位ID(報文識別碼)
{ // Standard ID
CAN_msgId |= (unsigned int)(id << 21) | CAN_ID_STD;//標(biāo)示符左移21位并添加幀識別碼,得到32位的標(biāo)示符字
}
else //如果是擴展幀,擴展幀是29位ID(報文識別碼)
{ // Extended ID
CAN_msgId |= (unsigned int)(id << 3) | CAN_ID_EXT;//標(biāo)示符左移3位并添加幀識別碼,得到32位的標(biāo)示符字
}
// set Initialisation mode for filter banks
//CAN過濾器組工作在初始化模式
CAN->FMR |= 1<<0;
// deactivate filter
CAN->FA1R &= ~(unsigned int)(1 << CAN_filterIdx);

// initialize filter
// set 32-bit scale configuration
//初始化過濾器
//過濾器位寬為單個32位
CAN->FS1R |= (unsigned int)(1 << CAN_filterIdx);
// set 2 32-bit identifier list mode
//過濾器組x的2個32位寄存器工作在標(biāo)識符列表模式
CAN->FM1R |= (unsigned int)(1 << CAN_filterIdx);
// 32-bit identifier
//32位標(biāo)識符
CAN->sFilterRegister[CAN_filterIdx].FR1 = CAN_msgId;
// 32-bit identifier
//32位標(biāo)識符
CAN->sFilterRegister[CAN_filterIdx].FR2 = CAN_msgId;
// assign filter to FIFO 0
//過濾器被關(guān)聯(lián)到FIFO0
CAN->FFA1R &= ~(unsigned int)(1 << CAN_filterIdx);
// activate filter
//過濾器被激活
CAN->FA1R |= (unsigned int)(1 << CAN_filterIdx);
// reset Initialisation mode for filter banks
//CAN過濾器組工作在正常模式
CAN->FMR &= ~(1<<0); // 該位置0為正常模式 415
// increase filter index
//設(shè)置的過濾器數(shù)量增加
CAN_filterIdx += 1;
}


上一頁 1 2 下一頁

關(guān)鍵詞: STM32CAN總線通信程

評論


技術(shù)專區(qū)

關(guān)閉