S32K148_CAN驱动(裸机开发)
hello,大家好。今天我又来啦,今天记录一下S32K148-CAN裸机驱动编写,有错误地方欢迎大家指正。
CAN的发送接收在S32K148中主要有三种方式,一种是邮箱机制(mailbox),一种FIFO方式,还有一种DMA方式。邮箱方式较为简单,也比较好理解。我的想法是先搞懂一种实现方式,再去满满研究其他方法。
邮箱机制主要涉及到一下寄存器:
还有一个RAMn[n]寄存器。
具体每个寄存器的功能数据手册有详细介绍,我就不逐个叙述了。直接根据我的demo程序来作简要介绍。
CAN的初始化主要包括:
1)PCC时钟使能
2)CAN发送引脚和接收引脚的复用配置
3)CAN模块程序使能,同时进入冻结模式
4)配置时钟,波特率,MB清0,接收MB的掩码配置,接收MB的code配置
5)接收或发送报文中断使能
#define MSG_BUF_SIZE 4 /* Msg Buffer Size. (CAN 2.0AB: 2 hdr + 2 data= 4 words)1MB = 4words */
#define MB_FIFO_IDX_TX 16u /* MB for transmitting CAN message*/
#define MB_FIFO_IDX_RX 6u /* MB for transmitting CAN message*/
#define MB_FIFO_NUM 6u /* MB0~MB5 for FIFO engine*/
void can2_init(void)
{
PCC->PCCn[PCC_PORTB_INDEX] |= 1<<30;
/*PIN MUX
* PTB12 CAN2 RX
* PTB13 CAN2 TX*/
PORTB->PCR[12] |= 1<<10;
PORTB->PCR[13] |= 1<<10;
/*CAN2 init*/
/*PCC FOR CAN2*/
PCC->PCCn[PCC_FlexCAN2_INDEX] |= 1<<30;
/*CAN2 cfg*/
CAN2->MCR |= 1<<31; //mdis=1,disable module
CAN2->CTRL1 &=~(1<<13); //CLKSRC=0,Clock Source = SOSCDIV2
CAN2->MCR &=~(1<<31); //mdis=0,ENable module //等待进入冻结模式
while( (CAN2->MCR & (1<<24))>>24 == 0 ); CAN2->CTRL1 = 0x01DB0006; //250k,rjw=11,psg1=011,psg2=011,propsg=110,clk=0,presdiv=1,配置时钟and波特率
for(uint8_t i=24; i<128; i++ )
{ /* CAN2: clear 32 msg bufs x 4 words/msg buf = 128 words */
CAN2->RAMn[i] = 0; /* Clear msg buf word */
}
for(uint8_t i=0; i<32; i++ )
{ /* In FRZ mode, init CAN2 16 msg buf filters */
CAN2->RXIMR[i] = 0xFFFFFFFF; /* Check all ID bits for incoming messages */
} CAN2->RXMGMASK = 0x00000000; /* Global acceptance mask: all ID bits DON'T CARE receive all ID message*/ CAN2->RAMn[ 0*MSG_BUF_SIZE + 0] = 0x04000000; /* Msg Buf 4, word 0: Enable for reception */
/* EDL,BRS,ESI=0: CANFD not used */
/* CODE=4: MB set to RX inactive */
/* IDE=0: Standard ID */
/* SRR, RTR, TIME STAMP = 0: not applicable */
//CAN2->RAMn[ 0*MSG_BUF_SIZE + 0] = 0x04200000; /* Msg Buf 4, word 0: Enable for reception */
/* EDL,BRS,ESI=0: CANFD not used */
/* CODE=4: MB set to RX inactive */
/* IDE=1: extend ID */
/* SRR, RTR, TIME STAMP = 0: not applicable */ CAN2->MCR = (0x0000001f) | (1<<17); /*SRXDIS=1,MAXMB=32*/ CAN2->MCR &= ~CAN_MCR_HALT_MASK; /* Negate HALT bit */
/*发送和接收message中断使能*/
CAN2->IMASK1 |= (1<<16)|(1<<0);
/*bus off中断使能*/
CAN2->CTRL1 |= (1<<15);
while ((CAN2->MCR && CAN_MCR_FRZACK_MASK) >> CAN_MCR_FRZACK_SHIFT);/* Good practice: wait for FRZACK to clear (not in freeze mode) */
while ((CAN2->MCR && CAN_MCR_NOTRDY_MASK) >> CAN_MCR_NOTRDY_SHIFT);/* Good practice: wait for NOTRDY to clear (module ready) */
//注册接收中断向量
S32_NVIC_EnableIRQ(CAN2_ORed_0_15_MB_IRQn);
S32_NVIC_EnableIRQ(CAN2_ORed_16_31_MB_IRQn);
//注册bus off中断向量
S32_NVIC_EnableIRQ(CAN2_ORed_IRQn);
}
CAN初始化过程中,需要注意地方在于接收掩码如何配置(原则:0表示不关心,1表示关心),其次配置好接收MB的选择同时使能相应MB的接收中断。这里面CAN发送很简单,主要针对CAN报文接收问题。
发送函数,注意标准帧和扩展帧的设置
void can2_send_8Byte(uint8_t data[], uint8_t datalength, uint32_t id, uint8_t id_mode)
{
uint8_t i;
uint8_t data_tem[datalength];
for(i=0;i<datalength;i++)
{
data_tem[i] = data[i];
}
//CAN2->IFLAG1 |= 0xFFFF0000; //clear all transmit flag
//wait bus idle
// while( (CAN2->ESR1 & (1<<7))>>7 == 0 );
//data input
CAN2->RAMn[MB_FIFO_IDX_TX*MSG_BUF_SIZE + 2] = data_tem[0]<<24 | data_tem[1]<<16 | data_tem[2]<<8 | data_tem[3];
CAN2->RAMn[MB_FIFO_IDX_TX*MSG_BUF_SIZE + 3] = data_tem[4]<<24 | data_tem[5]<<16 | data_tem[6]<<8 | data_tem[7];
//ID cfg
if(id_mode == StandardID)
{
CAN2->RAMn[MB_FIFO_IDX_TX*MSG_BUF_SIZE + 1] = id<<18;
CAN2->RAMn[MB_FIFO_IDX_TX*MSG_BUF_SIZE + 0] = 0x0C480000; //CODE=1100,SRR=1,IDE=0,RTR=0,DLC=1000
}else
{
CAN2->RAMn[MB_FIFO_IDX_TX*MSG_BUF_SIZE + 1] = id;
CAN2->RAMn[MB_FIFO_IDX_TX*MSG_BUF_SIZE + 0] = 0x0C680000; //CODE=1100,SRR=1,IDE=1,RTR=0,DLC=1000
}
}
接收函数
void can2_receive_8Byte(uint8_t id_mode)
{
can2_RecMessage.length = (CAN2->RAMn[0*MSG_BUF_SIZE + 0] >> 16) & 0xF;
if(id_mode == StandardID)
{
can2_RecMessage.id = (CAN2->RAMn[0*MSG_BUF_SIZE + 1] >> 18) & 0x7FF;
}else
{
can2_RecMessage.id = (CAN2->RAMn[0*MSG_BUF_SIZE + 1]) & 0x1FFFFFFF;
}
can2_RecMessage.data[0] = (CAN2->RAMn[0*MSG_BUF_SIZE + 2]) >> 24;
can2_RecMessage.data[1] = ((CAN2->RAMn[0*MSG_BUF_SIZE + 2]) >> 16) & 0xFF;
can2_RecMessage.data[2] = ((CAN2->RAMn[0*MSG_BUF_SIZE + 2]) >> 8) & 0xFF;
can2_RecMessage.data[3] = (CAN2->RAMn[0*MSG_BUF_SIZE + 2]) & 0xFF;
can2_RecMessage.data[4] = (CAN2->RAMn[0*MSG_BUF_SIZE + 3]) >> 24;
can2_RecMessage.data[5] = ((CAN2->RAMn[0*MSG_BUF_SIZE + 3]) >> 16) & 0xFF;
can2_RecMessage.data[6] = ((CAN2->RAMn[0*MSG_BUF_SIZE + 3]) >> 8) & 0xFF;
can2_RecMessage.data[7] = (CAN2->RAMn[0*MSG_BUF_SIZE + 3]) & 0xFF;
}
这个时候还不能接收,因为我需要把这个接收函数放到中断函数中,因为我配置的接收MB为0,所以接收中断函数是CAN2_ORed_0_15_MB_IRQHandler();
void CAN2_ORed_0_15_MB_IRQHandler(void)
{
gpio_reverse(PTe, 22);
can2_receive_8Byte(StandardID);
CAN2->IFLAG1 |= 0x0000FFFF;//清除标志位
}
每次接收到报文后,进入中断,在接收中断函数里读取报文ID和DATA。注意在中断函数里清除相应的MB标志位,即可进行下一次接收中断。
本次我设置的接收全局掩码设置都为0x0,且设置的标准帧。所以对于所有的标准帧ID报文,我都可以接收。
S32K148_CAN驱动(裸机开发)的更多相关文章
- S3C2416裸机开发系列十六_sd卡驱动实现
S3C2416裸机开发系列十六 sd卡驱动实现 象棋小子 1048272975 SD卡(Secure Digital Memory Card)具有体积小.容量大.传输数据快.可插拔.安全性好等长 ...
- 【转载】s3c2440裸机开发调试环境(MDK4.6,Jlink v8,mini2440)
用于arm裸机程序开发的IDE基本有 以下3个:MDK,IAR,还有ADS.具体它们的具体情况在这里我就不多说了,百度一下就明白了.由于之前开发c51,stm32时候都使用了MDK开发环境,而且MDK ...
- S3C2416裸机开发系列19_Fatfs播放录像wav音频文件
S3C2416裸机开发系列19 Fatfs播放录像wav音频文件 国际象棋男孩 1048272975 多媒体资源,一般都是以文件的形式存储在固化存储器中.Fatfs所支持的fat32为windo ...
- ok6410[000] 搭建裸机开发环境
1.安装交叉工具链arm-linux-gcc-4.3.2 先把这个工具复制到rhat系统中[rhel-server-6.3-i386-dvd.iso] 解压arm-linux-gcc-4.3.2到一个 ...
- S3C2440—3.用点亮LED来熟悉裸机开发的详细流程
文章目录 一.硬件知识 1.LED原理图 2.芯片手册 Ⅰ.找LED原理图 Ⅱ.找对应引脚 Ⅲ.在芯片手册中查找引脚信息 Ⅳ.查看寄存器说明 Ⅴ.配置寄存器 二.S3C2440框架与启动过程 三.要用 ...
- Cubieboard2裸机开发之(四)定时器操作
前言 在Cubieboard2裸机开发之(三)里用到了一个延时函数delay,它的延时时间是不精确的,因此为了能够精确延时,就需要定时器的配合.定时器可以精确延时的一个重要原因是它的计时时钟(或者说频 ...
- S3C2440触摸屏驱动实例开发讲解
出处:http://www.embeddedlinux.org.cn/html/yingjianqudong/ 一.开发环境 主 机:VMWare--Fedora 9 开发板:Mini2440--6 ...
- Vs2010 配置驱动的开发环境
我已被用来VS2010开发环境,之前曾经与vs2010驱动的开发环境.重装系统,一次又一次的配置,找了好几篇文章,配置没有成功,在配置阶段突然成功了,直接把原来的驱动程序的配置文件将能够接管使用. 当 ...
- ARM裸机开发中内存管理库RT_HEAP的使用
在使用arm芯片进行裸机开发的时候,很多时候都需要内存管理的功能,我们可以使用自己写的内存管理程序,也可以直接使用标准库,不过我一般比较喜欢标准库,速度快,今天就来说说在C语言环境下怎么样进行内存的动 ...
- 异常驱动的开发(Exception-Driven Development)
你的网站或应用程序存在哪些问题?如果你在等着用户来告诉你,那么你只能看到所有的问题中已经暴露的那极小的一部分.要知道,那只是"冰山一角"! 而且,如果你真的是在守株待兔,我不得不很 ...
随机推荐
- 编写引入svg
SVG是一种XML语言,类似XHTML,可以用来绘制矢量图形,例如右面展示的图形.SVG可以通过定义必要的线和形状来创建一个图形,也可以修改已有的位图,或者将这两种方式结合起来创建图形.图形和其组成部 ...
- 手脱NsPacK壳
1.查壳 使用PEiD未能检测到壳信息,这时,我们更换其他工具 从图中可以看到壳的信息为[NsPacK(3.x)[-]] 2.百度壳信息 北斗程序压缩(Nspack)是一款压缩壳.主要的选项是:压缩资 ...
- Tutorial 3_软件工作量估计和编码规范
软件过程与管理实验 实验3:编码规范 本次实验内容是个人软件过程部分,通过本次实验,学生将掌握以下内容: 1.建立自己的编码规范和代码审查表. 2.会用COCOMO II模型对软件工作量进行估计. [ ...
- 三大特性,多个场景,Serverless 应用引擎 SAE 全面升级
作者:营火 微服务能力大提升,更新增 Job.PHP 等场景,延展 Serverless 新边界 点击此处,获得阿里云 SAE 发布会直播 PPT! 企业的数字化随着互联网的普及发展越来越快,技术架构 ...
- 最新管家婆财贸ERP C9 V22.0的应用网页版的财务软件1000用户补丁免狗授权注册机网络版软件下载
管家婆财贸ERPC9应用价值: 1.多组织独立核算 多种组织形态核算,出具独立的三大财务报表及业务报表,发挥经营管理的积极性,便于专业化运营. 2.兼顾统筹与分权 满足多种集团统管与分权管控模式需求, ...
- unity---世界坐标和本地坐标的转换
会受到缩放的影响 用的比较多的是 本地坐标转换为世界坐标,比如在自己周围释放物体 当物体发生旋转,方向会发生变化
- 通过一次生产case深入理解tomcat线程池
最近生产上遇到一个case,终于想明白了原因,今天周末来整理一下 生产case 最近测试istio mesh的预热功能(调用端最小连接数原则) 来控制调用端进入k8s刚扩出来的容器的流量 因为刚启动的 ...
- 【抬杠C#】如何实现接口的base调用
背景 在三年前发布的C#8.0中有一项重要的改进叫做接口默认实现,从此以后,接口中定义的方法可以包含方法体了,即默认实现.不过对于接口的默认实现,其实现类或者子接口在重写这个方法的时候不能对其进行ba ...
- 多路分支、for循环
多路分支 多路分支也叫做switch语句,它的格式: switch (控制表达式){ case 条件: 输出....} switch 可以看成一种跳转,每当我们满足跳转就会跳转到响应的位置,接下我们写 ...
- VMware虚拟机基于contos 7 搭建lnmp环境全过程
这个环境也整了几次了,由于本人比较懒,没有记住.找资料很麻烦,就自己动手咯 1.下载VMware虚拟机 (有注册码) 地址:http://www.zdfans.com/5928.html ...