Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2006439
  • 博文数量: 356
  • 博客积分: 8284
  • 博客等级: 中将
  • 技术积分: 4580
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-15 20:25
个人简介

天行健,君子以自强不息

文章分类

全部博文(356)

文章存档

2018年(1)

2016年(4)

2015年(13)

2014年(14)

2013年(2)

2012年(25)

2011年(43)

2010年(65)

2009年(189)

分类: C/C++

2011-11-24 18:50:46

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) |
0

上一篇:stm32之RTC

下一篇:LPC1766之DMA

给主人留下些什么吧!~~