LPC1768/1769之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 Bufferif((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 availablereturn 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 1if (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 2else 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 3else 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 至此,记录完毕。记录时间:2016-11-28 记录地点:深圳WZ
转载于:https://www.cnblogs.com/ChYQ/p/6110713.html
LPC1768/1769之CAN控制器概述(附库函数下载地址)相关推荐
- 收藏!程序员必备的软件开发工具大全!(附高速下载地址)
对于每一位开发者而言,软件开发工具的重要性显然不言而喻.事实上,除了个人能力之外,它们也在团队的效率及实际生产力层面扮演着关键性角色. 今天阿晨就把自己的私货全部掏出来整理在下面! 内附高速下载地址! ...
- 【教程转载】 火狐浏览器 实用插件一览(附插件下载地址)
[教程转载] 火狐浏览器 实用插件一览(附插件下载地址)简单介绍一下: 火狐浏览器(firefox)最大的优点就是安全.快速.稳定. 有些人抱怨火狐的功能太少,有些网页不能正常浏览. 没关系,这些都不 ...
- 技术经典图书(附电子版下载地址)
本人大学期间专业是数学与应用数学, 2011年毕业, 做过C开发, 系统运维和测试, 这3年我读了很多书, 电子书和纸质的, 这些书中有很多很经典的图书和资料, 平时也喜欢和同事,朋友分享一些对他们有 ...
- python编程入门与案例详解pdf-这些年我读过的技术经典图书(附电子版下载地址)...
C技术资料 1.<> 作者: 谭浩强 这是我推荐的第一本书, 也是我接触的第一本书, 为什么把它放在第一位, 因为我觉得这本书对我的影响很大, 感觉这本书的最大特点是: 内容很全面, 内容 ...
- Python经典面试题100道(附PDF下载地址)
最近肝了一个月,整理了下经典的 Python 经典习题 100 道,有基础的,也有进阶的,用习题来巩固知识点,不枯燥,为了方便大家查阅,我把这 100 道题整理成了 PDF 文档,大家可以下载到电脑或 ...
- Microsoft Edge浏览器最新版已经换成开源Chromium引擎了,附官方下载地址
基于 Chromium 的新版 Microsoft Edge 已于 2020 年 1 月 15 日发布.它与 Windows 和 macOS 的所有受支持版本兼容.下载新版浏览器将替换 Window ...
- php做一个网页的源代码,用HTML5做一个个人网站此文仅展示个人主页界面。内附源代码下载地址...
下载说明: 1.再好的作品都不如将来要做的作品.在每一次的设计当中都能有所收获,才是设计师在web开发中最得益的. 2.本站所有作品均是杨青个人设计.如果发现模板有错,请尽情谅解. 3.如果遇到什么问 ...
- 【华为大咖分享】12.从Change、merge到New Challenge--华为内源平台到研发云平台的发展历程(后附PPT下载地址)
文:华为云DevCloud 表伟 完整版PPT下载请访问原文地址:https://bbs.huaweicloud.com/forum/thread-12724-1-1.html 华为云DevCloud ...
- 【华为大咖分享】11.五星级软件工程师的高效秘诀(后附PPT下载地址)
文:华为云DevCloud 徐毅 完整版PPT下载请访问原文地址:https://bbs.huaweicloud.com/forum/thread-12639-1-1.html 华为云DevCloud ...
最新文章
- EJS 什么是EJS后缀文件 EJS怎么用
- SQL JOIN\SQL INNER JOIN 关键字\SQL LEFT JOIN 关键字\SQL RIGHT JOIN 关键字\SQL FULL JOIN 关键字...
- PHP IE中下载附件问题
- python提高文件读取速度_Python提高了HDF5文件的读取速度
- 九问国产操作系统,九大掌门人万字回应!
- 服务器TIME_WAIT和CLOSE_WAIT分析和解决办法
- C#获取IP和整数IP方法
- (原創) 开启Notebook时,建议从天版中间开启 (日記)
- Mac Big sur如何设置触控板滚动不带惯性?
- 数据清洗与数据预处理浅析
- .net 4.5 新特性 async await 一般处理程序实例
- 学习HTML 笔记A3 :HTML标题、段落、文本格式化
- Python 正则表达式(RegEx)
- 伪元素写竖线_[CSS] 用伪元素:after实现分割线和气泡
- java连接jpi方式_Java数据库连接(Java Database Connectivity)
- 常用逻辑电平标准总结
- Object不能直接转成int
- UDP打洞、P2P组网方式研究
- JS一百只鸡卖一百块钱,公鸡5元,母鸡3元,三只小鸡一元
- 生成10位随机数(PHP)