IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> CAN通信程序代码阅读总结 -> 正文阅读

[嵌入式]CAN通信程序代码阅读总结


1. eCAN模块GPIO初始化

void InitECanbGpio(void)
{
 EALLOW;//配置GPIO引脚工作在eCAN功能
   GpioCtrlRegs.GPAPUD.bit.GPIO16 = 1;   // Disable pull-up for GPIO16 (CANTXB)
   GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;   // Enable pull-up for GPIO17 (CANRXB)
   GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3; // Asynch qual for GPIO17 (CANRXB)
   GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 2;  // Configure GPIO16 for CANTXB operation
   GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 2;  // Configure GPIO17 for CANRXB operation
  EDIS;
}

????使用到的寄存器如下所示:
在这里插入图片描述
????上拉输入的好处是减小了电流,输入的电平不会上下浮动而导致输入信号不稳定,在没有信号输入的情况下可以稳定在高电平。
在这里插入图片描述
在这里插入图片描述
总结:

  1. 使能接收引脚上拉,禁用发送引脚上拉;
  2. 设置接收引脚为异步模式;
  3. 设置GPIO引脚为CAN接收、输出引脚。

2. 初始化eCanb模块:InitEcanb

	EALLOW;       //配置eCAN的RX和TX分别为eCAN的接收和发送引脚
    ECanbShadow.CANTIOC.all = ECanbRegs.CANTIOC.all;
    ECanbShadow.CANTIOC.bit.TXFUNC = 1;
    ECanbRegs.CANTIOC.all = ECanbShadow.CANTIOC.all;

    ECanbShadow.CANRIOC.all = ECanbRegs.CANRIOC.all;
    ECanbShadow.CANRIOC.bit.RXFUNC = 1;
    ECanbRegs.CANRIOC.all = ECanbShadow.CANRIOC.all;
	EDIS;

????涉及的寄存器如下:
在这里插入图片描述
在这里插入图片描述

EALLOW;
    ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
    ECanbShadow.CANMC.bit.STM = 0;//非自测模式
    ECanbShadow.CANMC.bit.SCB = 1;//eCAN模式
    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    EDIS;

在这里插入图片描述
在这里插入图片描述

//初始化所有主设备控制区域为0,MCF所有的位都初始化为0 
    ECanbMboxes.MBOX0.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX1.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX2.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX3.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX4.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX5.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX6.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX7.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX8.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX9.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX10.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX11.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX12.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX13.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX14.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX15.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX16.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX17.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX18.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX19.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX20.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX21.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX22.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX23.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX24.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX25.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX26.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX27.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX28.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX29.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX30.MSGCTRL.all = 0x00000000;
    ECanbMboxes.MBOX31.MSGCTRL.all = 0x00000000;

????接下来进行的是相关寄存器的置位工作,包括邮箱发送和接收相关、中断标志位置位,并请求对SCC模式下的CANBTC寄存器进行设置。

EALLOW;
    ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
    ECanbShadow.CANTA.all = 0xFFFFFFFF;
    ECanbRegs.CANTA.all = ECanbShadow.CANTA.all;

    ECanbShadow.CANRMP.all = ECanbRegs.CANRMP.all;
    ECanbShadow.CANRMP.all = 0xFFFFFFFF;
    ECanbRegs.CANRMP.all = ECanbShadow.CANRMP.all;


//添加

    ECanbShadow.CANGIF0.all = ECanbRegs.CANGIF0.all;
    ECanbShadow.CANGIF0.all = 0xFFFFFFFF;
    ECanbRegs.CANGIF0.all = ECanbShadow.CANGIF0.all;

//添加
    ECanbShadow.CANGIF1.all = ECanbRegs.CANGIF1.all;
    ECanbShadow.CANGIF1.all = 0xFFFFFFFF;
    ECanbRegs.CANGIF1.all = ECanbShadow.CANGIF1.all;


/* Configure bit timing parameters for eCANB*/

    ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
    ECanbShadow.CANMC.bit.CCR = 1 ;            // Set CCR = 1
    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;   

????CANME寄存器的CCE为被置位后,可以进行波特率的设置了。

do 
    {ECanbShadow.CANES.all=ECanbRegs.CANES.all;}
    while(ECanbShadow.CANES.bit.CCE != 1 ) ;    // Wait for CCE bit to be set..


    ECanbShadow.CANBTC.all = ECanbRegs.CANBTC.all;  //添加
    ECanbShadow.CANBTC.all = 0;
    ECanbShadow.CANBTC.bit.BRPREG = 9;
    /*  TQ=1/(SYSCLKOUT/4)×(BRPREG+1) */
    ECanbShadow.CANBTC.bit.TSEG2REG = 2;
    ECanbShadow.CANBTC.bit.TSEG1REG = 10;  
	ECanbShadow.CANBTC.bit.SAM = 1;
    ECanbRegs.CANBTC.all = ECanbShadow.CANBTC.all;

    ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
    ECanbShadow.CANMC.bit.CCR = 0 ;            // Set CCR = 0
    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;


    do
    {
      ECanbShadow.CANES.all = ECanbRegs.CANES.all;
    } while(ECanbShadow.CANES.bit.CCE != 0 );       // Wait for CCE bit to be  cleared..

????对邮箱的相应配置进行设置。

ECanbRegs.CANME.all = 0;//屏蔽所有邮箱,在写MSGID之前必须要做

	EDIS;
	ECanbMboxes.MBOX0.MSGID.bit.IDE = 0;//标准帧格式
	...
	ECanbMboxes.MBOX31.MSGID.bit.IDE = 0;

	ECanbMboxes.MBOX0.MSGCTRL.bit.DLC = 8;//数据长度8个字节
	...
	ECanbMboxes.MBOX31.MSGCTRL.bit.DLC = 8;//数据长度8个字节

	ECanbMboxes.MBOX0.MSGCTRL.bit.TPL = 0;//设置优先级
	...
	ECanbMboxes.MBOX31.MSGCTRL.bit.TPL = 31;//设置优先级

	ECanbMboxes.MBOX0.MSGCTRL.bit.RTR = 0;//没有远程帧请求
	...
	ECanbMboxes.MBOX31.MSGCTRL.bit.RTR = 0;//没有远程帧请求

	EALLOW;
	EALLOW;
	ECanbRegs.CANMIM.all = 0xFFFFFFFE;
	//邮箱中断将产生在ECAN0INT
	ECanbRegs.CANMIL.all = 0;
	ECanbRegs.CANGIF0.all = 0xFFFFFFFF;
	ECanbRegs.CANGIF1.all = 0xFFFFFFFF;
	//ECAN0INT中断请求线被使能
	ECanbRegs.CANGIM.bit.I0EN = 1;

    EDIS;

总结:

  1. 配置接收和发送引脚;
  2. 配置eCAN模块在eCAN模式;
  3. 邮箱控制寄存器全部置位,邮箱接收和发送相关标志位置位,请求设置波特率等数据;
  4. 设置波特率等数据;
  5. 对邮箱进行配置,如格式、数据长度、优先级等;
  6. 设置eCAN模块的中断。

3. 主程序

????先要对中断向量进行配置,这里要查看中断向量表,查看ECAN0INTB中断是在哪一条中断线上,又是这条中断线上的第几个中断向量。

EALLOW;
	PieVectTable.TINT0 = &ISRTimer0;//计时器中断向量
	PieVectTable.ECAN0INTB = &ISRCanb;//eCAN模块中断向量
	EDIS;

	PieCtrlRegs.PIECTRL.bit.ENPIE = 1;//所有向量取自PIE向量表
	PieCtrlRegs.PIEIER1.bit.INTx5 = 1;//XINT2
	PieCtrlRegs.PIEIER1.bit.INTx7 = 1;//TINT0
	PieCtrlRegs.PIEIER9.bit.INTx7 = 1;//ECAN0INTB

	IER |= M_INT9;//中断9使能
	IER |= M_INT1;//中断1使能
	IER |= M_INT14;//中断14使能

	EINT;//使能全局中断
	ERTM;//使能实时中断

????接下来要设置接收邮箱和发送邮箱。

    MSGb_Init(0,0,0x0601);		//cana mail 0 send  电机1
	MSGb_Init(1,1,0x0581);		//cana mail 1 resive

	MSGb_Init(2,0,0x0602);		//cana mail 2 send  电机2
	MSGb_Init(3,1,0x0582);		//cana mail 3 resive  电机2

	MSGb_Init(4,0,0x0080);      //cana mail 4 send  发送同步帧

	MSGb_Init(5,0,0x0203);		//cana mail 5 send  发送数字量邮箱
	MSGb_Init(6,0,0x0303);		//cana mail 6 send  发送模拟量邮箱

	MSGb_Init(7,0,0x0403);		//cana mail 7 send  发送模拟量邮箱

	MSGb_Init(8,1,0x0183);      //cana mail 8 resive
	MSGb_Init(9,1,0x0283);		//cana mail 9 resive
	MSGb_Init(10,1,0x0383);		//cana mail 10 resive
	MSGb_Init(11,1,0x0483);		//cana mail 11 resive

	MSGb_Init(12,0,0x0000);     //启动所有节点
	MSGb_Init(13,0,0x0603);     //配置周期发送

????我们需要看一下MSGb_Init函数是怎么配置邮箱的。

void MSGb_Init(Uint16 msgnum,Uint16 dir,Uint32 id)
{
    struct ECAN_REGS ECanbShadow;
    switch (msgnum)
	{
	  case 0:
			    ECanbShadow.CANMD.all = ECanbRegs.CANMD.all;
				ECanbShadow.CANMD.bit.MD0 = dir;  //邮箱0设置为发送
				ECanbRegs.CANMD.all = ECanbShadow.CANMD.all;
				if(dir==1)
				{
					ECanbMboxes.MBOX0.MSGID.bit.AME=1;//接收屏蔽
			   	}
	  			ECanbMboxes.MBOX0.MSGID.all = (id << 18);
	        	ECanbShadow.CANME.all = ECanbRegs.CANME.all;
	        	ECanbShadow.CANME.bit.ME0 = 1;//使能
	        	ECanbRegs.CANME.all = ECanbShadow.CANME.all;
	            break;
	            ......

在这里插入图片描述
????当我们定义的接收邮箱收到信息后,就会触发邮箱中断,转而去执行中断子程序,中断路线如下。
在这里插入图片描述
????根据之前的初始化工作,我们知道当邮箱1或邮箱3收到信息后,就会将其RMP为置1,即触发中断邮箱接收中断,同时若CANMIM和CANMIL寄存器对应位都被使能,则会通过CANGIM寄存器将所有中断映射到ECAN0INT中断线上。

4. 中断服务子程序

interrupt void ISRCanb(void)
{
    switch(ECanbRegs.CANRMP.all)//如果收到消息,CANRMP将有位被置1
   	{
   		......
		case 0x00000002://1
		ECanbRegs.CANRMP.all=0xffffffff;//清除接收完成标志
		L[1] = ECanbMboxes.MBOX1.MDL.all;
		H[1] = ECanbMboxes.MBOX1.MDH.all;
		if(L[1] == 0x436C6000)
		{
			HisBuffer_v1[0] = 0x05;
			HisBuffer_v1[1] = 0x81;
			HisBuffer_v1[2] = (L[1] >> 24) & 0xff;
			HisBuffer_v1[3] = (L[1] >> 16) & 0xff;
			HisBuffer_v1[4] = (L[1] >> 8) & 0xff;
			HisBuffer_v1[5] = L[1] & 0xff;
			HisBuffer_v1[6] = H[1] & 0xff;
			HisBuffer_v1[7] = (H[1] >> 8) & 0xff;
			HisBuffer_v1[8] = (H[1] >> 16) & 0xff;
			HisBuffer_v1[9] = (H[1] >> 24) & 0xff;
			flag_send_v1 = 1;
		}
		break;

		case 0x00000004:    //2
		ECanbRegs.CANRMP.all=0xffffffff;
		L[2] = ECanbMboxes.MBOX2.MDL.all;
		H[2]= ECanbMboxes.MBOX2.MDH.all;
		break;

		case 0x00000008:   //3                     电机2
		ECanbRegs.CANRMP.all=0xffffffff;//清除接收完成标志
		L[3] = ECanbMboxes.MBOX3.MDL.all;
		H[3] = ECanbMboxes.MBOX3.MDH.all;
		if(L[3] == 0x436C6000)
		{
			HisBuffer_v2[0] = 0x05;
			HisBuffer_v2[1] = 0x82;
			HisBuffer_v2[2] = (L[3] >> 24) & 0xff;
			HisBuffer_v2[3] = (L[3] >> 16) & 0xff;
			HisBuffer_v2[4] = (L[3] >> 8) & 0xff;
			HisBuffer_v2[5] = L[3] & 0xff;
			HisBuffer_v2[6] = H[3] & 0xff;
			HisBuffer_v2[7] = (H[3] >> 8) & 0xff;
			HisBuffer_v2[8] = (H[3] >> 16) & 0xff;
			HisBuffer_v2[9] = (H[3] >> 24) & 0xff;
			flag_send_v2 = 1;
		}
		break;
		......

????由程序可以发现,当任意RMP位被置位后,就会进入中断,而我们使能的接收邮箱是邮箱1和邮箱3,那么其对应RMP位被置位,就会进入对应的程序段。我们所要做的是将接收到的数据重新进行处理,写入数组HisBuffer中,然后将以太网发送标志置1,再通过以太网发送出去。以太网通信是后续我们需要讨论的了。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 22:53:39  更:2022-04-07 22:54:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:49:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码