📄 lpc2300can.c
字号:
/****************************************Copyright (c)**************************************************
***文件名称:CAN验收滤波测试程序
***作者:张利刚
***单位:中科院微系统所嘉兴分中心网络组
***时间:2008年7月17日
********************************************************************************************************/
#include "LPC2300CAN.h"
extern MessageDetail MessageDetailT;
extern MessageDetail MessageCAN0; // 引用CAN0通道帧变量
extern MessageDetail MessageCAN1; // 引用CAN1通道帧变量
/*********************************************************************************************************
** 函数名称: void enable_IRQ(void)
** 功能描述: 使能IRQ中断
** 输 入: 无
** 输 出: 无
** 说明:系统必须处于特权模式
********************************************************************************************************/
static __inline void Enable_IRQ(void)
{
int tmp;
__asm
{
MRS tmp,CPSR
BIC tmp,tmp,#0x80
MSR CPSR_c,tmp
}
}
/*
*********************************************************************************************************
**函数原型 : void INI_LED(void);
**参数说明 : 无
**返回值 : 无
**说 明 : 初始化LED
*********************************************************************************************************/
void INI_LED(void)
{
uint32 LED1 = 1 << 25; // P1.25控制LED1
uint32 LED2 = 1 << 26; //P1.26控制LED2
uint32 LED3 = 1 << 27; // P1.25控制LED3
uint32 LED4 = 1 << 28; //P1.26控制LED4
//LED
PINSEL1 = 0x00000000; // 所有管脚连接GPIO
IO1DIR = LED1+LED2+LED3+LED4;
}
/*
*********************************************************************************************************
**函数原型 : void OPEN_CLOSE_LED(unsigned int num);
**参数说明 : LED灯编号
**返回值 : 无
**说 明 : LED灯的闪烁
*********************************************************************************************************/
void OPEN_CLOSE_LED(unsigned int num)
{
uint32 LED1 = 1 << 25; // P1.25控制LED1
uint32 LED2 = 1 << 26; //P1.26控制LED2
uint32 LED3 = 1 << 27; // P1.25控制LED3
uint32 LED4 = 1 << 28; //P1.26控制LED4
unsigned int loop;
switch(num)
{
case 1:
IO1SET |=LED1;
for(loop=0;loop<100000;loop++)
;
IO1CLR |=LED1;
break;
case 2:
//开和关LED2
IO1SET |=LED2;
for(loop=0;loop<100000;loop++)
;
IO1CLR |=LED2;
break;
case 3:
//开和关LED3
IO1SET |=LED3;
for(loop=0;loop<100000;loop++)
;
IO1CLR |=LED3;
break;
case 4:
//开和关LED4
IO1SET |=LED4;
for(loop=0;loop<100000;loop++)
;
IO1CLR |=LED4;
break;
default:
break;
}
}
/*
*********************************************************************************************************
**函数原型 : unsigned char Enter_SWRst(unsigned char Ch);
**参数说明 : Ch:CAN控制器号,0表示第一路CAN
**返回值 : 0:失败
** : 1: 成功
**说 明 : CAN控制器进入软件复位模式
*********************************************************************************************************/
unsigned char Enter_SWRst(unsigned char Ch)
{
unsigned long regaddr;
REG_CANMOD regmod;
regaddr = (unsigned long)(&CAN1MOD)+Ch*CANOFFSET;
regmod.DWord = RGE(regaddr); //读取CAN1MOD寄存器
regmod.Bits.RM = 1; //RM位置“1”
RGE(regaddr) = regmod.DWord; //回写CAN1MOD寄存器
regmod.DWord = RGE(regaddr); //验证写入值
return (0 != regmod.Bits.RM)? 1:0;
}
/*
*********************************************************************************************************
**函数原型 : unsigned char Quit_SWRst(unsigned char Ch);
**参数说明 : Ch:CAN控制器号,0表示第一路CAN
**返回值 : 0:失败
** : 1: 成功
**说 明 : CAN控制器退出软件复位模式
*********************************************************************************************************/
unsigned char Quit_SWRst(unsigned char Ch)
{
unsigned long regaddr;
REG_CANMOD regmod;
regaddr = (unsigned long)(&CAN1MOD)+Ch*CANOFFSET;
regmod.DWord = RGE(regaddr); //读取CAN1MOD寄存器
regmod.Bits.RM = 0; //RM位置“0”
RGE(regaddr) = regmod.DWord; //回写CAN1MOD寄存器
regmod.DWord = RGE(regaddr); //验证写入值
return (0 != regmod.Bits.RM)? 0:1;
}
/*
*********************************************************************************************************
**函数原型 : unsigned char CAN_Init(unsigned char Ch, unsigned long Baud);
**参数说明 : Ch:CAN控制器号,0表示第一路CAN
** : Baud:CAN波特率值
**返回值 : 无
**说 明 : CAN控制器退出软件复位模式
*********************************************************************************************************/
unsigned char CAN_Init(unsigned char Ch, unsigned long Baud)
{
unsigned long regaddr;
switch(Ch) //配置CAN控制器引脚
{
case 0:
PCONP |= 0x01L<<13; //打开CAN1控制器电源
PINSEL0 &= ~(0x03L<<0);/*RD1*/
PINSEL0 |= (0x01L<<0);
PINSEL0 &= ~(0x03L<<2);/*TD1*/
PINSEL0 |= (0x01L<<2);
break;
case 1:
PCONP |= 0x01L<<14; //打开CAN1控制器电源
PINSEL0 &= ~(0x03L<<8);/*RD2*/
PINSEL0 |= (0x02L<<8);
PINSEL0 &= ~(0x03L<<10);/*TD2*/
PINSEL0 |= (0x02L<<10);
break;
default:
break;
}
Enter_SWRst(Ch);
regaddr = (unsigned long)(&CAN1BTR)+Ch*CANOFFSET;
RGE(regaddr) = Baud;
if(Ch == 0)
{
CAN1CMR |= (0x01<<2); //释放接收缓冲区
CAN1ICR &= ~(0x01);
CAN1IER |= ((1<<0)|(1<<2)); //使能CAN0接收与错误报警中断
}
else
{
CAN2CMR |= (0x01<<2);
CAN2ICR &= ~(0x01);
CAN2IER |= ((1<<0)|(1<<2)); //使能CAN1接收与错误报警中断
}
Quit_SWRst(Ch);
/*初始化中断*/
VICIntSelect &= (~(1<<23)); //设置通道为IRQ中断
*(volatile uint32 *)((&VICVectAddr0) + 23) =(uint32)CANIntPrg; //设置中断入口地址
*(volatile uint32 *)((&VICVectPri0) + 23) = 9; //设置第23通道的中断优先级为9
VICIntEnable |=(1<<23); //使能CAN1/CAN2的中断向量
//CAN_AFMR &= ~0x07; //验收过滤设置为旁路模式
//CAN_AFMR|=(1<<1);
CAN_AFMR &= ~0x07; //验收过滤设置为正常模式
CAN_AFMR|=0x00;
if((CAN_AFMR & 0x07) == 0x00)
return 1;
else
return 0;
}
/*
*********************************************************************************************************
**函数原型 : unsigned char CANRCV(unsigned char Ch, MessageDetail MessageCAN)
**参数说明 :
**输入变量 : Ch:CAN控制器号,0表示第一路CAN
** : *MessageCAN: 存放CAN帧信息的结构体
**输出变量 : *MessageCAN: 存放CAN帧信息的结构体
**返回值 : 无
**说 明 : 接受CAN帧放在指定的结构体中
*********************************************************************************************************/
unsigned char CANRCV(unsigned char Ch, MessageDetail *MessageCAN)
{
unsigned long mes;
unsigned long regaddr;
regaddr = (unsigned long)(&CAN1RFS)+Ch*CANOFFSET; //处理DLC、RTR、FF
mes = RGE(regaddr);
MessageCAN->LEN = (mes >>16) & 0x0F; //获取帧长度
MessageCAN->FF = (mes >>31); //获取FF
regaddr = (unsigned long)(&CAN1RID)+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)(&CAN1RDA)+Ch*CANOFFSET; //处理 数据A
mes = RGE(regaddr);
MessageCAN->DATAA = mes;
regaddr = (unsigned long)(&CAN1RDB)+Ch*CANOFFSET; //处理 数据B
mes = RGE(regaddr);
MessageCAN->DATAB = mes;
return(1);
}
/*
*********************************************************************************************************
**函数原型 : unsigned char writedetail(unsigned char LEN,unsigned char FF, unsigned int ID,unsigned char *data);
**参数说明 : LEN:数据长度
** : *data 发送数据所在的数组
:
**返回值 : 操作成功返回 1 失败返回 0
**说 明 : 用户填写发送 帧信息
*********************************************************************************************************/
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<LEN;i++)
{
if(i<4)
{
MessageDetailT.DATAA |= (*(data+i)<<(i*8));
}
else
{
MessageDetailT.DATAB |= (*(data+i)<<((i-4)*8));
}
}
//MessageDetailT.DATAB = ID;
return(1);
}
}
/*
*********************************************************************************************************
**函数原型 : unsigned char CANSend(unsigned char Ch, unsigned char BUFNum);
**参数说明 : Ch:CAN控制器号,0表示第一路CAN
** : BUFNum 选择缓冲区
: MessageDetailT 报文的特征信息及数据
**返回值 : 无
**说 明 : CAN发送帧
*********************************************************************************************************/
unsigned char CANSend(unsigned char Ch, unsigned char BUFNum)
{
unsigned long CAN32reg;
unsigned long regaddr;
unsigned char FFflag;
BUFNum-=1; // 计算地址方便。
regaddr = (unsigned long)(&CAN1TFI1)+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)(&CAN1TID1)+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)(&CAN1TDA1)+Ch*CANOFFSET+BUFNum*0X10; // 写帧数据A
RGE(regaddr) = MessageDetailT.DATAA;
regaddr = (unsigned long)(&CAN1TDB1)+Ch*CANOFFSET+BUFNum*0X10; // 写帧数据B
RGE(regaddr) = MessageDetailT.DATAB;
regaddr = (unsigned long)(&CAN1CMR)+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;
OPEN_CLOSE_LED(2);
regaddr = (unsigned long)(&CAN1GSR)+Ch*CANOFFSET; //查询发送状态
CAN32reg = RGE(regaddr);
if(CAN32reg&(1<<3)) //所有的请求已成功完成
{
return(1); //发送成功返回 1
}
else { return (0);} //发送失败返回 0
}
/*
********************************************************************************************
**函数原型 : void CANIntPrg(void)
**参数说明 : 无
**返回值 : 无
**说 明 : CAN控制器中断处理函数
******************************************************************************************/
void __irq CANIntPrg(void)
{
unsigned char j;
unsigned int CAN32reg,mes;
unsigned int regaddr;
for(j=0;j<2;j++) //最大CAN通道数为2,分别检测两个通道的中断
{
regaddr = (unsigned long)(&CAN1ICR)+j*CANOFFSET;
CAN32reg=RGE(regaddr);
if((CAN32reg&(1<<0))!= 0) //RI 接收中断
{
CAN32reg &= ~(0x01);
RGE(regaddr) = CAN32reg;
if(j==0)
{
OPEN_CLOSE_LED(1);
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)(&CAN1CMR)+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)(&CAN1CMR)+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)(&CAN1GSR)+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); //释放接收缓冲区
}
}
VICVectAddr = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -