您的位置 首页 软件

根据STM32的CAN总线通讯程序

includeincludesyshincludedelayhincludeCANhCAN_msgCAN_TxMsg;发送邮箱CAN_msgCAN_RxMsg;接收邮箱u8CAN

#include

#include “sys.h”
#include “delay.h”
#include “CAN.h”
CAN_msg CAN_TxMsg; //发送邮箱
CAN_msg CAN_RxMsg; //接纳邮箱
u8 CAN_TxRdy=0; //发送安排妥当标志
u8 CAN_RxRdy=0; //接纳安排妥当标志
u8CAN_TDTxR_DLC; //数据长度,最高为1111
/////////////////CAN设置/////////////////////////////////////
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;//铲除复用重映射装备寄存器13,14位,
AFIO->MAPR|=0X00004000;//装备为10;IO口重映射至PB8.PB9
RCC->APB2ENR|=1<<3; //RCC_APB2ENR_IOPBEN;//敞开IO口B时钟
GPIOB->CRH&=~(0X0F<<0);//铲除PB8状况寄存器~(1111<<0)
GPIOB->CRH|=(0X08<<0);//设定pb8上下拉输入1000
GPIOB->CRH&=~(0XF<<4);//清空pb9状况寄存器
GPIOB->CRH|=(0X0B<<4);//设定PB9推挽输出
MY_NVIC_Init(1,1,USB_HP_CAN_TX_IRQChannel,2);//发送中止使能
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;//发送邮箱空中止答应 409
CAN->IER|=1<<1; //FIFO0音讯挂号中止答应 409 (CAN_IER_FMPIE0|CAN_IER_TMEIE);
//brp=(brp/18)/500000;//波特率设置500Kb/s,核算波特率分频器值
CAN->BTR&=~(((0X03)<<24)|((0x07)<<20)|((0x0f)<<16)|(0x1ff)); //清空BTR寄存器相关位 410 400
CAN->BTR|=(((1&0X03)<<24)|((7&0X07)<<20)|((8&0X0F)<<16)|(brp-1));//设置BTR寄存器 410 400

}
//////////////从初始化形式进入正常作业形式/////////////////////////////////////////////
void CAN_start(void)
{
CAN->MCR&=0xfffffffe;
while(CAN->MSR&(0x01));
CAN->MCR&=0xfffffffd; //清零INRQ位,进入正常形式
//while(~(CAN->MSR&0x01)); //等候硬件对INAK位清零,承认退出初始化
}
//////////////设置作业形式///////////////////////////////////////////
void CAN_testmode(void)
{
CAN->BTR&=0x3fffffff;//清空BTR 的SILM LBKM位410
CAN->BTR|=0XC0000000;//设置BTR 的LBKM位为高,环回形式 410

}
///////////////检测发送邮箱为空////////////////////////////////////////////////
void CAN_waitReady(void)
{
while((CAN->TSR&(1<<26))==0); //检测发送邮箱0标志位,为1则为空,为0不为空
CAN_TxRdy=1; //置发送安排妥当标志位为1
}
///////////////发送数据//////////////////////////////////////
void CAN_wrMsg(CAN_msg *msg)
{
CAN->sTxMailBox[0].TIR=(u8)0; //发送邮箱标明符寄存器复位 清零
if(msg->format ==STANDARD_FORMAT)//假如是规范11位标明符帧
{msg->id=33 ;
CAN->sTxMailBox[0].TIR|=0x4200000;//(msg->id<<21)|CAN_ID_STD; //则标明符左移21位,高11位为规范标明符,标明符挑选方位0 411
}
else //假如是29位扩展标明符帧
{
CAN->sTxMailBox[0].TIR|=(u8)(msg->id<<3)|CAN_ID_EXT; //标明符左移3位,高29位为标明符(扩展标明符)标明符挑选方位1 411
}
if(msg->type==DATA_FRAME) //假如音讯为数据帧
{
CAN->sTxMailBox[0].TIR|=CAN_RTR_DATA;//标明符寄存器RTR方位0,数据帧
}
else //假如为长途帧
{
CAN->sTxMailBox[0].TIR|=CAN_RTR_REMOTE;//标明符寄存器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])); //数据位低4字节写入发送邮箱0



CAN->sTxMailBox[0].TDHR=(((u8)msg->data[7]<<24)|((u8)msg->data[6]<<16)|((u8)msg->data[5]<<8)|((u8)msg->data[4])); //数据位高4字节写入发送邮箱0



CAN->sTxMailBox[0].TDTR&=0xfffffff0;//设置音讯长度DLC清0
CAN->sTxMailBox[0].TDTR|=0x00000004;//设置音讯长度为4个字节
CAN->IER|=1<<0; //发送邮箱空中止使能 409
CAN->sTxMailBox[0].TIR|=1<<0; //发送音讯411

}
///////////////读取邮箱数据并开释//////////////////////////////////////////////////////////////
void CAN_rdMsg(CAN_msg *msg)
{
if((CAN->sFIFOMailBox[0].RIR&CAN_ID_EXT)==0) //假如是11位规范标识符
{
msg->format=STANDARD_FORMAT; //音讯为规范格局
msg->id=(u32)0x000007ff&(CAN->sFIFOMailBox[0].RIR>>21); //标明符等于标明符位右移21位与0x7ff
}
else //假如是29位扩展标识符
{
msg->format=EXTENDED_FORMAT; //音讯格局为扩展标明符格局
msg->id=(u32)0x0003ffff&(CAN->sFIFOMailBox[0].RIR>>3);//标明符等于标明符位右移3位与上0x3ffff
}
if((CAN->sFIFOMailBox[0].RIR&CAN_RTR_REMOTE)==0) //假如音讯为数据帧
{
msg->type=DATA_FRAME;
}
else //数据位长途帧
{
msg->type=REMOTE_FRAME;
}
msg->len = (unsigned char)0x0000000F & CAN->sFIFOMailBox[0].RDTR; //读取数据长度

msg->data[0] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR); //读取数据低4字节
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); //读取数据高4字节
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);

CAN->RF0R |= 1<<5; //开释接纳邮箱0 407
}
////////////////////////设置标明符过滤器组/////////////////////////////////////////////////////////////////////////////

void CAN_wrFilter (unsigned int id, unsigned char format)
{
static unsigned short CAN_filterIdx = 0; //标明符设置数量索引
unsigned int CAN_msgId = 0; //变量用于存储需求设定的标明符

if (CAN_filterIdx > 13) //查看CAN过滤器是否已满,最高到13
{
return; //假如已满-回来
}
if (format == STANDARD_FORMAT) //假如是规范帧,规范帧是11位ID(报文识别码)
{ // Standard ID
CAN_msgId |= (unsigned int)(id << 21) | CAN_ID_STD;//标明符左移21位并添加帧识别码,得到32位的标明符字
}
else //假如是扩展帧,扩展帧是29位ID(报文识别码)
{ // Extended ID
CAN_msgId |= (unsigned int)(id << 3) | CAN_ID_EXT;//标明符左移3位并添加帧识别码,得到32位的标明符字
}
// 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位寄存器作业在标识符列表形式
CAN->FM1R |= (unsigned int)(1 << CAN_filterIdx);
// 32-bit identifier
//32位标识符
CAN->sFilterRegister[CAN_filterIdx].FR1 = CAN_msgId;
// 32-bit identifier
//32位标识符
CAN->sFilterRegister[CAN_filterIdx].FR2 = CAN_msgId;
// assign filter to FIFO 0
//过滤器被相关到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
//设置的过滤器数量添加
CAN_filterIdx += 1;
}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/ruanjian/260495.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部