1、main.c文件
#include "LPC17xx.h" /* LPC17xx外设寄存器 */
#include "LPC1700CAN.h"
extern MessageDetail MessageDetailT; /* 定义发送帧 */
extern MessageDetail MessageCAN0; /* 定义CAN0通道帧接收帧 */
extern MessageDetail MessageCAN1; /* 定义CAN1通道帧接收帧 */
/*********************************************************************************************************
*********************************************************************************************************/
//unsigned char writedetail(unsigned char LEN,unsigned char FF, unsigned int ID,unsigned char *data)
//unsigned char CANSend(unsigned char Ch, unsigned char BUFNum)
void delay(unsigned int x)
{
while(x--);
}
int main (void)
{
unsigned char buff[4]={0x11,0x22,0x33,0x44};
SystemInit(); /* 系统初始化 */
CAN_Init(0, BPS_500K); //开发板上面的接插件can接口是该芯片的第一个can的接口
//CAN_Init(1, BPS_1000K); /* 初始化第2路CAN,波特率1000K */
NVIC_SetPriority(CAN_IRQn, 1); /* 设置CAN中断优先级 */
NVIC_EnableIRQ(CAN_IRQn); /* 使CAN中断 */
writedetail(4,1, 0x01,buff);//第二个参数为0,标准帧;为1,扩展帧。
while (1)
{
CANSend(0, 1);
delay(1000000);
}
}
2、can.c文件
#include "LPC1700CAN.h"
MessageDetail MessageDetailT;
MessageDetail MessageCAN0; /* 引用CAN0通道帧变量 */
MessageDetail MessageCAN1; /* 引用CAN1通道帧变量 */
/*********************************************************************************************************
** Function name: Enter_SWRst
** Descriptions: 向PC机发送显示字符。
** input parameters: Ch:CAN控制器号,0表示第一路CAN
** Output parameters: 无
** Returned value: 0: 失败
** 1: 成功
*********************************************************************************************************/
unsigned char Enter_SWRst(unsigned char Ch)
{
unsigned long regaddr;
REG_CANMOD regmod;
regaddr = (unsigned long)(&LPC_CAN1->MOD)+Ch*CANOFFSET;
regmod.DWord = RGE(regaddr); /* 读取LPC_CAN1->MOD寄存器 */
regmod.Bits.RM = 1; /* RM位置"1" */
RGE(regaddr) = regmod.DWord; /* 回写LPC_CAN1->MOD寄存器 */
regmod.DWord = RGE(regaddr); /* 验证写入值 */
return (0 != regmod.Bits.RM)? 1:0;
}
/*********************************************************************************************************
** Functoin name: Quit_SWRst
** Descriptions: CAN控制器退出软件复位模式
** input paraments: Ch: CAN控制器号,0表示第一路CAN
** output paraments: 无
** Returned values: 0: 失败
** 1: 成功
*********************************************************************************************************/
unsigned char Quit_SWRst(unsigned char Ch)
{
unsigned long regaddr;
REG_CANMOD regmod;
regaddr = (unsigned long)(&LPC_CAN1->MOD)+Ch*CANOFFSET;
regmod.DWord = RGE(regaddr); /* 读取LPC_CAN1->MOD寄存器 */
regmod.Bits.RM = 0; /* RM位置"0" */
RGE(regaddr) = regmod.DWord; /* 回写LPC_CAN1->MOD寄存器 */
regmod.DWord = RGE(regaddr); /* 验证写入值 */
return (0 != regmod.Bits.RM)? 0:1;
}
/*********************************************************************************************************
** Functoin name: CAN_Init
** Descriptions: CAN控制器退出软件复位模式
** input paraments: Ch: CAN控制器号,0表示第一路CAN,为1表示第二路can
** Baud: CAN波特率值
** output paraments: 无
** Returned values: 无
*********************************************************************************************************/
void CAN_Init(unsigned char Ch, unsigned long Baud)
{
unsigned long regaddr;
switch(Ch){ /* 配置CAN控制器引脚 */
case 0:
LPC_SC->PCONP |= 0x01L<<13; /* 打开CAN控制器电源 */
LPC_PINCON->PINSEL0 = (LPC_PINCON->PINSEL0 & ~(0x03L<<0)) | (0x01L<<0);
/* 选择RD1 */
LPC_PINCON->PINSEL0 = (LPC_PINCON->PINSEL0 & ~(0x03L<<2)) | (0x01L<<2);
/* 选择TD1 */
break;
case 1:
LPC_SC->PCONP |= 0x01L<<14; /* 打开CAN控制器电源 */
LPC_PINCON->PINSEL0 = (LPC_PINCON->PINSEL0 & ~(0x03L<<8)) | (0x02L<<8);
/* 选择TD1 */
LPC_PINCON->PINSEL0 = (LPC_PINCON->PINSEL0 & ~(0x03L<<10)) | (0x02L<<10);
/* 选择TD1 */
break;
default:
break;
}
Enter_SWRst(Ch);
regaddr = (unsigned long)(&LPC_CAN1->BTR)+Ch*CANOFFSET;
RGE(regaddr) = Baud;
LPC_CANAF->AFMR = (LPC_CANAF->AFMR & (~0x07)) | (1 << 1); /* 设置为旁路模式 */
if(Ch == 0){
LPC_CAN1->CMR |= (0x01<<2); /* 释放接收缓冲区 */
LPC_CAN1->IER |= ((1<<0)|(1<<2)); /* 使能CAN0接收与错误报警中断 */
} else{
LPC_CAN2->CMR |= (0x01<<2);
LPC_CAN2->IER |= ((1<<0)|(1<<2)); /* 使能CAN1接收与错误报警中断 */
}
Quit_SWRst(Ch);
}
/*********************************************************************************************************
** Functoin name: CANRCV
** Descriptions: 接受CAN帧放在指定的结构体中
** input paraments: Ch: CAN控制器号,0表示第一路CAN
** *MessageCAN: 存放CAN帧信息的结构体
** output paraments: 无
** Returned values: 无
*********************************************************************************************************/
unsigned char CANRCV(unsigned char Ch, MessageDetail *MessageCAN)
{
unsigned long mes;
unsigned long regaddr;
regaddr = (unsigned long)(&LPC_CAN1->RFS)+Ch*CANOFFSET; /* 处理DLC、RTR、FF */
mes = RGE(regaddr);
MessageCAN->LEN = (mes >>16) & 0x0F; /* 获取帧长度 */
MessageCAN->FF = (mes >>31); /* 获取FF */
regaddr = (unsigned long)(&LPC_CAN1->RID)+Ch*CANOFFSET; /* 处理ID */
mes = RGE(regaddr);
if(MessageCAN->FF) { /* FF为1,ID为29位 */
MessageCAN->CANID = mes & 0x1fffffff;
} else { /* FF为0 ,ID为11位 */
MessageCAN->CANID = mes & 0x000007ff;
}
regaddr = (unsigned long)(&LPC_CAN1->RDA)+Ch*CANOFFSET; /* 处理 数据A */
mes = RGE(regaddr);
MessageCAN->DATAA = mes;
regaddr = (unsigned long)(&LPC_CAN1->RDB)+Ch*CANOFFSET; /* 处理 数据B */
mes = RGE(regaddr);
MessageCAN->DATAB = mes;
return(1);
}
/*********************************************************************************************************
** Functoin name: Writedetail
** Descriptions: 用户填写发送 帧信息
** input paraments: LEN: 数据长度
** *data: 发送数据所在的数组
** FF:值为0表示标准帧,值为1表示扩展帧
** ID:
** output paraments: 无
** Returned values: 0: 失败
** 1: 成功
*********************************************************************************************************/
//在正式发送can报文前,将需要发送的数据通过此函数封装起来
unsigned char writedetail(unsigned char LEN,unsigned char FF, unsigned int ID,unsigned char *data)
{
unsigned char i;
if(LEN>8){
return(0);
} else {
MessageDetailT.LEN=LEN;
MessageDetailT.FF=FF;
MessageDetailT.CANID=ID;
MessageDetailT.DATAA=0; /* 先清零 */
MessageDetailT.DATAB=0;
for(i=0;i if(i<4){
MessageDetailT.DATAA |= (*(data+i)<<(i*8));
} else {
MessageDetailT.DATAB |= (*(data+i)<<((i-4)*8));
}
}
return(1);
}
}
/*********************************************************************************************************
** Functoin name: CANSend
** Descriptions: CAN控制器退出软件复位模式
** input paraments: Ch: CAN控制器号,0表示第一路CAN
** BUFNum: 选择缓冲区
** output paraments: MessageDetailT: 报文的特征信息及数据
** Returned values: 0: 失败
** 1: 成功
*********************************************************************************************************/
//FF为1则是扩展帧,为0则是标准帧
//ch为0表示第一路can,即开发板上面的接插件接口
//BUFNum的值为1到3,这个变量的取值在示波器上面测试过
//此函数为发送can报文的最底层函数
unsigned char CANSend(unsigned char Ch, unsigned char BUFNum)
{
unsigned long CAN32reg;
unsigned long regaddr;
unsigned char FFflag;
BUFNum-=1; /* 计算地址方便 */
regaddr = (unsigned long)(&LPC_CAN1->TFI1)+Ch*CANOFFSET+BUFNum*0X10;/* 3缓冲区间地址差 0x10 */
CAN32reg = RGE(regaddr);
CAN32reg &= ~((0x0fL<<16) | (0x01L<<30) | (0x80000000)); /* 清 DLC,RTR.FF位 */
CAN32reg |= ((unsigned long)MessageDetailT.LEN<<16) | ((unsigned long)MessageDetailT.FF<<31);
RGE(regaddr)=CAN32reg;
FFflag = MessageDetailT.FF;
regaddr = (unsigned long)(&LPC_CAN1->TID1)+Ch*CANOFFSET+BUFNum*0X10;/* 写帧ID */
CAN32reg = RGE(regaddr);
if(FFflag){ /* FF为1,ID为29位 */
CAN32reg &=0x70000000;
CAN32reg |= (MessageDetailT.CANID & 0x1fffffff);
} else{
CAN32reg &= 0xfffff800; /* FF为0 ,ID为11位 */
CAN32reg |= (MessageDetailT.CANID & 0x000007ff);
}
RGE(regaddr)=CAN32reg;
regaddr = (unsigned long)(&LPC_CAN1->TDA1)+Ch*CANOFFSET+BUFNum*0X10;/* 写帧数据A */
RGE(regaddr) = MessageDetailT.DATAA;
regaddr = (unsigned long)(&LPC_CAN1->TDB1)+Ch*CANOFFSET+BUFNum*0X10;/* 写帧数据B */
RGE(regaddr) = MessageDetailT.DATAB;
regaddr = (unsigned long)(&LPC_CAN1->CMR)+Ch*CANOFFSET; /* 写控制寄存器,发送 */
CAN32reg = RGE(regaddr);
CAN32reg &= ~0x03;
CAN32reg |= 0x03;
CAN32reg &= ~((1<<5)|(1<<6)|(1<<7));
switch(BUFNum){
case 0: CAN32reg |= 01<<5;break;
case 1: CAN32reg |= 01<<6;break;
case 2: CAN32reg |= 01<<7;break;
default: break;
}
RGE(regaddr)=CAN32reg;
regaddr = (unsigned long)(&LPC_CAN1->GSR)+Ch*CANOFFSET; /* 查询发送状态 */
CAN32reg = RGE(regaddr);
if(CAN32reg&(1<<3)) { /* 所有的请求已成功完成 */
return(1); /* 发送成功返回 1 */
} else {
return (0); /* 发送失败返回 0 */
}
}
/*********************************************************************************************************
** Functoin name: CAN_IRQHandler
** Descriptions: CAN控制器中断处理函数
** input paraments: 无
** output paraments: 无
** Returned values: 无
*********************************************************************************************************/
void CAN_IRQHandler (void)
{
unsigned char j;
unsigned int CAN32reg,mes;
unsigned int regaddr;
/*
* 最大CAN通道数为2,分别检测两个通道的中断
*/
for(j=0;j<2;j++){
regaddr = (unsigned long)(&LPC_CAN1->ICR)+j*CANOFFSET;
CAN32reg=RGE(regaddr);
if((CAN32reg&(1<<0))!= 0) /* RI 接收中断 */
{
CAN32reg &= ~(0x01);
RGE(regaddr) = CAN32reg;
if(j==0)
{
CANRCV(j, &MessageCAN0); /* 收到CAN0中断,接收帧 */
/* 填写发送帧*/
MessageDetailT.LEN=MessageCAN0.LEN;
MessageDetailT.FF=MessageCAN0.FF;
MessageDetailT.CANID=MessageCAN0.CANID;
MessageDetailT.DATAA=MessageCAN0.DATAA;
MessageDetailT.DATAB=MessageCAN0.DATAB;
/* CAN0发送,以第一个缓冲区 */
CANSend(j, 1);
regaddr = (unsigned long)(&LPC_CAN1->CMR)+j*CANOFFSET;
mes=RGE(regaddr);
mes |= (1<<2); /* 释放接收缓冲区 */
RGE(regaddr)=mes;
}
if(j==1)
{
CANRCV(j, &MessageCAN1); /* 收到CAN1中断,接收帧 */
/* 填写发送帧*/
MessageDetailT.LEN=MessageCAN1.LEN;
MessageDetailT.FF=MessageCAN1.FF;
MessageDetailT.CANID=MessageCAN1.CANID;
MessageDetailT.DATAA=MessageCAN1.DATAA;
MessageDetailT.DATAB=MessageCAN1.DATAB;
/* CAN1发送,以第二个缓冲区*/
CANSend(j, 2);
regaddr = (unsigned long)(&LPC_CAN1->CMR)+j*CANOFFSET;
mes=RGE(regaddr);
mes |= (1<<2); /* 释放接收缓冲区 */
RGE(regaddr)=mes;
}
}
/* 根据需要添加
if((CAN32reg&(1<<1))!= 0) // TI1 第一发送缓冲区发送完成中断
{
;
}
if((CAN32reg&(1<<9))!= 0) // TI2 第二发送缓冲区发送完成中断
{
;
}
if((CAN32reg&(1<<10))!= 0) // TI3 第三发送缓冲区发送完成中断
{
;
}
*/
if((CAN32reg&(1<<7))!= 0) /* BEI 总线错误中断 */
{
Enter_SWRst(j);
regaddr = (unsigned long)(&LPC_CAN1->GSR)+j*CANOFFSET;
mes=RGE(regaddr);
mes &=0x00ff;
RGE(regaddr)=mes; /*总线错误清除处理 */
Quit_SWRst(j);
}
if((CAN32reg&(1<<6))!= 0) /* ALI 仲裁丢失中断 */
{
//添加用户代码
}
if((CAN32reg&(1<<3))!= 0)
{
//添加用户代码
//ClrCanDataOver(j); /*释放接收缓冲区 */
}
}
}
/*********************************************************************************************************
End Of File
*********************************************************************************************************/
3、程序功能
通过can总线对外发送数据,波特率500k。
阅读(6627) | 评论(0) | 转发(0) |