LPC1768/1769之CAN控制器概述(附库函数下载地址)

发布者:科技飞翔最新更新时间:2016-12-26 来源: eefocus关键字:LPC1768  CAN控制器 手机看文章 扫描二维码
随时随地手机看文章
一、背景:
        使用LPC1769来做CAN的收发,在此对使用LPC1769的CAN控制器进行收发做个总结和记录,以备下
    次开发快速上手使用。
        附:LPC1768/1769除了支持最高频率不同以外,其它基本上一致。

二、正文:
        先贴一张LPC1769 CAN控制器的方框图:


  .


        由上图可见,整个CAN控制器一头是CPU,另一头是CAN收发器:
     CAN收发器负责CAN数据与CAN网络的通信。CAN内核模块解析和封装要发送到CAN收发器以及从CAN
   收发器发过来的数据,此处CAN内核工作由硬件自行完成。
     CPU通过APB总线即可设置CAN控制器状态,以及读取中断信息和中断状态。
     一共有3个发送缓冲器(邮箱),这样就可以保证,最少可以发送3组并发的CAN数据;2个接收缓冲
   器(邮箱),这样就可以在CPU处理1个邮箱的接收数据的同时,还能用另一个邮箱接收网络上的数据。
     LPC1769 CAN的验收滤波器比较特殊,它是一个独立于CAN控制器的器件,也属于一种外设,不过
   比较特殊的是,它是服务于CAN控制器的外设,这么做的意义就在于,验收滤波这方面,不再需要软件来
   来做任何事情,直接由硬件来实现查表算法,节省宝贵的CPU资源,由于它也算是一个独立的外设,运用
   起来也比较复杂,而本篇篇幅有限,暂不详述,下次再另开篇博客来说。
     至此,LPC1769 CAN的结构就介绍完毕,接下说明,做哪些事情可让其开始正确收发CAN数据。
        CAN1/2 使用以下寄存器进行设置:
        a)电源使能:在PCONP 寄存器中,设置PCAN1/2。
        注:复位时,CAN1/2 会被使能(PCAN1/2=0)。
        b)时钟使能:在PCLK_SEL0 寄存器中选择PCLK_CAN1/2 和验收滤波器的PCLK_ACF。
        注:如果所需使用的 CAN 波特率必须高于100kbit/s(参见表16.12),那么就不能选择IRC
     作为时钟源。
        c)唤醒:CAN 控制器能够将微控制器从掉电模式唤醒。
        d)引脚:通过PINSEL 寄存器选择CAN1/2 引脚,并通过PINMODE 寄存器选择引脚模式。
        e)中断:CAN 中断是通过CAN1/2IER 寄存器来使能的。中断的使能是通过在NIVC 中使
        用相应的中断设置使能寄存器(Interrupt Set Enable register)来实现的。
        f)CAN 控制器初始化:在CANNOD 寄存器中设置。

        以上为数据手册介绍的CAN控制器初始化过程,白话点说:        "a)"CAN是LPC1769的外设器件,要让其工作,首先要设置PCONP,该寄存器的各个位来决定外设
            的时钟是否打开或关闭,若某个外设不被使用,则关闭它,以达到节省功耗的目的;此处要需
       要使用CAN,所以先打开CAN的外设时钟。        "b)"其次,外设若要正常工作,则均需要一个合适的时钟频率,通PCLK_SEL0l来决定CAN的外设
            时钟来源,以及大小。        "c)"为了进一步减少MCU的功耗,当CAN网络上没有数据传输时,也没有CAN中断在处理,并且对应
       的睡眠位被置“1”,CAN外设会进入睡眠状态,若CAN总线上出现了显性位,则CAN外设从睡眠
       状态被唤醒。同时,若已配置了相关位,且此时整个MCU都进入掉电或者深度睡眠模式,则CAN
       也可将MCU唤醒         "d)"配置CAN的收发引脚,无需多言,告诉CAN控制器,从哪个引脚收发CAN数据。        "e)"配置CAN的各种中断使能条件,此处使能了发送/接收中断,错误中断;以及配置NVIC内
            CAN外设中断。        "f)"配置CAN相关的参数,譬如波特率等等。
        至此,CAN控制器初始化部分完成,还需要做接收和发送函数,以及中断函数,来实现CAN的收发
    ,和错误管理。
        当然,在CAN控制器初始化部分,波特率的参数设置还有许多要说,本篇篇幅有限,暂不详述,下次
    再开篇博客进行介绍。
        CAN中断函数:        /*----------------- INTERRUPT SERVICE ROUTINES --------------------------*/
        /*********************************************************************//**
         * @brief        CAN_IRQ Handler, control receive message operation
         * param[in]    none
         * @return         none
         **********************************************************************/
        void CAN_IRQHandler()
        {
            uint8_t IntStatus;
            uint32_t data1;            /* get interrupt status
             * Note that: Interrupt register CANICR will be reset after read.
             * So function "CAN_IntGetStatus" should be call only one time             */
            // 以下函数获取的是CAN1ICR/CAN2ICR的寄存器数据,该寄存器指明了中断来源
            IntStatus = CAN_IntGetStatus(LPC_CAN1);if((IntStatus>>0)&0x01) {// 接收中断            }
            ...            // 省略的内容为,根据寄存器的各位的中断来源数据来解析中断信息。
       // IntStatus = CAN_IntGetStatus(LPC_CAN2);
       // if(...) ...        }
        
        CAN接收函数:
        此函数为NXP提供的库函数,库函数下载链接在本文第三部分,该函数做的内容无非就是,在中
    断内,检查两个接收邮箱内是否有信息,若有,则将信息提取。    /********************************************************************//**
     * @brief        Receive message data
     * @param[in]    CANx pointer to LPC_CAN_TypeDef, should be:
     *                 - LPC_CAN1: CAN1 peripheral
     *                 - LPC_CAN2: CAN2 peripheral
     * @param[in]    CAN_Msg point to the CAN_MSG_Type Struct, it will contain received
     *              message information such as: ID, DLC, RTR, ID Format
     * @return         Status:
     *                 - SUCCESS: receive message successfully
     *                 - ERROR: receive message unsuccessfully
     *********************************************************************/
    Status CAN_ReceiveMsg (LPC_CAN_TypeDef *CANx, CAN_MSG_Type *CAN_Msg)
    {
        uint32_t data;
    
        CHECK_PARAM(PARAM_CANx(CANx));    
        //check status of Receive Buffer
        if((CANx->SR &0x00000001))
        {            /* Receive message is available */
            /* Read frame informations */
            CAN_Msg->format   = (uint8_t)(((CANx->RFS) & 0x80000000)>>31);
            CAN_Msg->type     = (uint8_t)(((CANx->RFS) & 0x40000000)>>30);
            CAN_Msg->len      = (uint8_t)(((CANx->RFS) & 0x000F0000)>>16);    
    
            /* Read CAN message identifier */
            CAN_Msg->id = CANx->RID;    
            /* Read the data if received message was DATA FRAME */
            if (CAN_Msg->type == DATA_FRAME)
            {                /* Read first 4 data bytes */
                data = CANx->RDA;                *((uint8_t *) &CAN_Msg->dataA[0])= data & 0x000000FF;                *((uint8_t *) &CAN_Msg->dataA[1])= (data & 0x0000FF00)>>8;;                *((uint8_t *) &CAN_Msg->dataA[2])= (data & 0x00FF0000)>>16;                *((uint8_t *) &CAN_Msg->dataA[3])= (data & 0xFF000000)>>24;    
                /* Read second 4 data bytes */
                data = CANx->RDB;                *((uint8_t *) &CAN_Msg->dataB[0])= data & 0x000000FF;                *((uint8_t *) &CAN_Msg->dataB[1])= (data & 0x0000FF00)>>8;                *((uint8_t *) &CAN_Msg->dataB[2])= (data & 0x00FF0000)>>16;                *((uint8_t *) &CAN_Msg->dataB[3])= (data & 0xFF000000)>>24;    
            /*release receive buffer*/
            CANx->CMR = 0x04;
            }            else
            {                /* Received Frame is a Remote Frame, not have data, we just receive
                 * message information only */
                CANx->CMR = 0x04; /*release receive buffer*/
                return SUCCESS;
            }
        }        else
        {            // no receive message available
            return ERROR;
        }        return SUCCESS;
    }
        
        CAN发送函数:
        该函数还是库函数,即依次查询3个发送邮箱的状态,若邮箱状态为空,则将数据填充到该邮箱
    并置位发送标志,然后由CAN内核模块硬件自动发送。发送的优先级在寄存器内均可配置,不详述。
    篇幅不想过长,因此查询邮箱2/3代码部分省略。    /********************************************************************//**
     * @brief        Send message data
     * @param[in]    CANx pointer to LPC_CAN_TypeDef, should be:
     *                 - LPC_CAN1: CAN1 peripheral
     *                 - LPC_CAN2: CAN2 peripheral
     * @param[in]    CAN_Msg point to the CAN_MSG_Type Structure, it contains message
     *                 information such as: ID, DLC, RTR, ID Format
     * @return         Status:
     *                 - SUCCESS: send message successfully
     *                 - ERROR: send message unsuccessfully
     *********************************************************************/
    Status CAN_SendMsg (LPC_CAN_TypeDef *CANx, CAN_MSG_Type *CAN_Msg)
    {
        uint32_t data;
        CHECK_PARAM(PARAM_CANx(CANx));
        CHECK_PARAM(PARAM_ID_FORMAT(CAN_Msg->format));        if(CAN_Msg->format==STD_ID_FORMAT)
        {
            CHECK_PARAM(PARAM_ID_11(CAN_Msg->id));
        }        else
        {
            CHECK_PARAM(PARAM_ID_29(CAN_Msg->id));
        }
        CHECK_PARAM(PARAM_DLC(CAN_Msg->len));
        CHECK_PARAM(PARAM_FRAME_TYPE(CAN_Msg->type));    
        //Check status of Transmit Buffer 1
        if (CANx->SR & (1<<2))
        {            /* Transmit Channel 1 is available */
            /* Write frame informations and frame data into its CANxTFI1,
             * CANxTID1, CANxTDA1, CANxTDB1 register */
            CANx->TFI1 &= ~0x000F0000;
            CANx->TFI1 |= (CAN_Msg->len)<<16;            if(CAN_Msg->type == REMOTE_FRAME)
            {
                CANx->TFI1 |= (1<<30); //set bit RTR            }            else
            {
                CANx->TFI1 &= ~(1<<30);
            }            if(CAN_Msg->format == EXT_ID_FORMAT)
            {
                CANx->TFI1 |= (0x80000000); //set bit FF            }            else
            {
                CANx->TFI1 &= ~(0x80000000);
            }    
            /* Write CAN ID*/
            CANx->TID1 = CAN_Msg->id;    
            /*Write first 4 data bytes*/
            data = (CAN_Msg->dataA[0])|(((CAN_Msg->dataA[1]))<<8)|
             ((CAN_Msg->dataA[2])<<16)|((CAN_Msg->dataA[3])<<24);
            CANx->TDA1 = data;    
            /*Write second 4 data bytes*/
            data = (CAN_Msg->dataB[0])|(((CAN_Msg->dataB[1]))<<8)|
            ((CAN_Msg->dataB[2])<<16)|((CAN_Msg->dataB[3])<<24);
            CANx->TDB1 = data;    
             /*Write transmission request*/
             // 注意该值,置位发送邮箱1,告知硬件,邮箱1的信息已经填充完毕可发送。
             CANx->CMR = 0x21;             return SUCCESS;
        }        //check status of Transmit Buffer 2
        else if(CANx->SR & (1<<10))
        {            /* Transmit Channel 2 is available */
            /* Write frame informations and frame data into its CANxTFI2,
             * CANxTID2, CANxTDA2, CANxTDB2 register */
             ...             /*Write transmission request*/
             // 注意该值,置位发送邮箱2,告知硬件,邮箱2的信息已经填充完毕可发送。
            CANx->CMR = 0x41;            return SUCCESS;
        }        //check status of Transmit Buffer 3
        else if (CANx->SR & (1<<18))
        {            /* Transmit Channel 3 is available */
            /* Write frame informations and frame data into its CANxTFI3,
             * CANxTID3, CANxTDA3, CANxTDB3 register */
             ...            /*Write transmission request*/
             // 注意该值,置位发送邮箱3,告知硬件,邮箱3的信息已经填充完毕可发送。
            CANx->CMR = 0x81;            return SUCCESS;
        }        else
        {            // 所有邮箱都处于非空闲状态,无法发送
            return ERROR;
        }
    }

    至此,有了初始化部分,CAN中断函数,CAN发送、接收函数,也就实现了CAN数据的收发。
    滤波以波特率以及CAN总线错误处理,下次再开博客详述。

三、参考文档
    LPC175x_6x CMSIS-Compliant Standard Peripheral Firmware Driver Library (Keil, IAR, GNU)
      https://www.lpcware.com/content/nxpfile/lpc175x6x-cmsis-compliant-standard-peripheral-firmware-driver-library-keil-iar-gnu至此,记录完毕。


关键字:LPC1768  CAN控制器 引用地址:LPC1768/1769之CAN控制器概述(附库函数下载地址)

上一篇:LPC1769 CAN的自测试模式
下一篇:Cotex-M3内核LPC17xx系列时钟及其配置方法

推荐阅读最新更新时间:2024-03-16 15:27

LPC1768 -- RTC实时时钟
RTC是当下设备中比较普遍的一个部件,很多设备都需要查看时间。RTC实时时钟已经在很多的单片机中集成,以前还要专门的时钟芯片,现在Cortex-M3内核都包括了这个部件了。和以前NXP的ARM7内核不同的是,LPC1768的时钟源只有32K时钟源提供,这一点是要注意的,其他和ARM7一致。 RTC其实也就是一个定时,可以理解为秒定时器,RTC寄存器挺多的,不过寄存器结构相对简单,操作起来还是很方便的。 讲解几个重要的寄存器,中断位置寄存器ILR、时钟控制寄存器CCR、计数器增量中断寄存器CIIR、报警屏蔽寄存器AMR 第一个ILR中断位置寄存器 BIT0,当为1时计数器增量模块产生中断。 BIT1,当为1是报警寄存器产生中断
[单片机]
<font color='red'>LPC1768</font> -- RTC实时时钟
LPC1768 IAP写入bin格式程序不能启动的解决办法
在为LPC1768做一个CAN总线在线升级功能的时候,使用IAP功能,将KEIL转换生成的bin文件写入lpc1768内部flash的起始地址,然后跳转到这个位置启动。自动跳转时能够正常启动,但是一复位或者断电重启就不能启动了,查找原因并求助论坛网友得到了问题原因和解决办法。 程序写入内部flash时需要计算bin文件前28个字节的校验和(32位),然后将这个校验和替换bin文件第28到31字节的值,bin文件其他部分不变。 计算方法: /****************************************************************** * 名称 :LpcCodeChecksum() * 功能
[单片机]
LPC17XX 学习之 systick
LPC1768在代码里用到使用systick时,是以如下形式出现 if (SysTick_Config(SystemCoreClock /1000))/1ms进入一次中断/ { while (1); /* 错误情况下就停在这里 } 这个函数的原型是 __STATIC_INLINEuint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1) SysTick_LOAD_RELOAD_Msk) return(1); /* Reload value impossible */ SysTick- L
[单片机]
stm32f407之CAN控制器(操作寄存器)
首先简单介绍一下CAN总线,关于CAN总线是谁发明的,CAN总线的历史,CAN总线的发展,CAN总线的应用场合,这些,通通不说。这里只是以我个人理解,简单说说CAN通信。CAN总线的端点没有地址(除非自己在帧里定义地址),CAN总线通信不用地址,用标识符,不是单独的谁发给谁,而是,你总是发送给整个网络。然后每个节点都有过滤器,对网络上的传播的帧的标识符进行过滤,自己想要什么样的帧,可以设置自己的过滤器,接收相关的帧信息。如果两个节点同时发送怎么办?这个不用我们担心,CAN控制器会自己仲裁,让高优先级的帧先发。 然后我们可以了解一下stm32的CAN控制器。 如上图所示,stm32有两个can控制器,can1(主),和can
[单片机]
stm32f407之<font color='red'>CAN</font><font color='red'>控制器</font>(操作寄存器)
LPC1768的IIS通讯
IIS是飞利浦公司定义的一种用于音频传输的数字总线,LPC1768支持该总线, I2S接口为一条3线串行总线,含有1根数据线、1根时钟线和1根字选择信号线。基本的I2S连接具有一个主机(其总是为主机)和一个从机。LPC1700系列Cortex—M3微控制器的I2S提供了彼此独立的发送和接收通道,每个通道都可作为主机或从机. 使用代码如下 void IISInit(void) { //打开IIS时钟 LPC_SC- PCONP |= 1 27; LPC_SC- PCLKSEL1 &= ~(0X03 22); //时钟选择25M //0.4 IIS RX CLK LPC_PINCON- PINSEL0 &= ~(
[单片机]
恩智浦推出集成CAN收发器的微控制器解决方案
中国上海,2011年1月18日讯 —— 恩智浦半导体NXP Semiconductors N.V.(Nasdaq:NXPI)近日宣布推出业界首款内嵌易用型片上CANopen驱动,集成高速CAN物理层收发器的微控制器LPC11C22和LPC11C24。作为一种独特的系统级封装解决方案,LPC11C22和LPC11C24集成了TJF1051 CAN收发器,在低成本LQFP48封装中实现了完整的CAN功能。 CAN被认为是一种适用于恶劣环境的坚固而可靠的通信信道。随着面向工厂、建筑物及家庭的工业及自动化应用日益普及,凭借LPC11C22和LPC11C24集成CAN收发器的微控制器解决方案,恩智浦为低成本CAN的广泛应
[单片机]
恩智浦推出集成<font color='red'>CAN</font>收发器的微<font color='red'>控制器</font>解决方案
基于CAN控制器和传感器实现车窗智能控制系统的设计
1、引言 目前.以微控制器为代表的汽车电子在整车电子系统中应用广泛,汽车控制正由机电控制系统转向以分布式网络为基础的智能化系统。CAN总线是一种支持分布式和实时控制的串行通信网络,以其高性能和高可靠性在自动控制领域广泛应用。作为目前最具应用潜力的现场总线之一,CAN总线技术为我国汽车产业升级、降低成本,扩大市场占用率提供支持。 现在各中高档轿车都安装有电动车窗,按钮控制车窗玻璃的升降。如果车窗无智能,司机在没有注意到乘客的手或物体伸出窗口的情况下按下按钮,乘客容易被车窗夹伤。为了安全,很多乘车都采用电动防夹车窗。在充分研究有关CAN总线在汽车电子系统中的应用和电动车窗防夹方案的基础上,提出一种基于CAN总线的轿车车窗智能控制系
[嵌入式]
基于<font color='red'>CAN</font><font color='red'>控制器</font>和传感器实现车窗智能控制系统的设计
P87C591内嵌CAN控制器的应用设计
摘要:独立的CAN控制器芯片需要外接一个微处理器,接受外部CPU的控制才能运行。如果微处理器内部带有CAN控制器,无疑会大大简化应用系统的硬件设计,系统的可靠性也有很大提高 ,同时还可以大幅度降低生成成本。Philips的新产品P87C591内部集成了CAN控制器。本文主要介绍如何利用P87C591进行CAN节点的设计和应用。 关键词:P87C591 CAN 节点 PeliCAN 应用设计 引言 CAN属于总线式串行通信网络。由于其独特的设计,与一般的通信总线相比,CAN总线的数据通信具有突出的可靠性、实时性和灵活性。CAN总线早已成为国际标准,其应用范围也从最初的汽车电控逐步扩展到工业控制的各个领域,成为最有前途的现场总线
[传感技术]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved