TI中文支持网
TI专业的中文技术问题搜集分享网站

清华大学TM4C123微处理器原理与实践例程-CAN实验程序解析

// CAN实验程序解析
//头文件
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "driverlib/can.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "utils/uartstdio.h"
#include "driverlib/rom.h"
#include "driverlib/fpu.h"
	
// 变量定义部分
// 一个计数器,用于记录所发送的数据包数
volatile ui32 g_ulMsgCount_TX = 0;
// 一个计数器,用于记录所接收的数据包数
volatile ui32 g_ulMsgCount_RX = 0; 
// 用于指示在传输过程中是否出现错误以及错误类型
volatile ui32 g_bErrFlag = 0; 
//用于指示是否接收到数据包
volatile ui32 g_bRXFlag = 0; 

// 函数定义部分
// UART0的配置及初始化部分。*
// UART0模块用于通过计算机虚拟串口显示过程信息,主要包括InitConsole
//函数和一些UARTprintf语句。
void InitConsole(void)
{// 由于UART0使用PA0,PA1两个引脚,因此需要使能GPIOA模块SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

	// 将PA0和PA1两个引脚的功能选择为执行UART0模块的功能GPIOPinConfigure(GPIO_PA0_U0RX);GPIOPinConfigure(GPIO_PA1_U0TX);// 对PA0和PA1两个引脚配置为UART功能GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);// UART的标准初始化UARTStdioConfig(0,115200,50000000);
}

// 延时1s的函数
Void SimpleDelay(void)
{
	//由于ROM_SysCtlDelay函数延时3个时钟周期,而ROM_SysCtlClockGet
//函数返回系统时钟的频率,因此最终的结果就是延时1sROM_SysCtlDelay(ROM_SysCtlClockGet()/3);
}

// CAN的中断函数 
// 该函数寻找产生中断的原因,并且计算已发送/接收的数据包数目。
//由于要使用CAN0模块的中断函数,所以需要在startup_ccs.c文件的
//vector table(中断函数列表)中声明CANIntHandler。
void CANIntHandler(void)
{ui32 ulStatus;// 通过CANIntStatus函数读取中断的状态ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);// 如果是控制器状态中断,则说明出现了某种错误if(ulStatus == CAN_INT_INTID_STATUS){
		//读取CAN模块所处的状态,并自动清除中断。ulStatus = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);//将g_bErrFlag这个状态指示变量置1,以指示有错误发生g_bErrFlag = 1;}// 检查是否是由message object 1引起的发送中断else if(ulStatus == 1){// 数据包发送已经完成,清除中断CANIntClear(CAN0_BASE, 1);//发送完一个数据包,计数器g_ulMsgCount_TX增加g_ulMsgCount_TX++;// 发送已经完成,清除所有的错误信息.g_bErrFlag = 0;}// 检查是否是由于message object 2引起的接收中断else if(ulStatus==2){// 数据包接收已经完成,清除中断CANIntClear(CAN0_BASE, 2);
		// 接收完一个数据包,计数器g_ulMsgCount_RX增加
		g_ulMsgCount_RX++;

		// 设置Flag说明接收到的数据包正在等待处理g_bRXFlag = 1;// 发送已经完成,清除所有的错误信息.
		g_bErrFlag = 0;}
}

// main 函数
// 配置CAN模块,循环发送CAN格式数据包并通过LOOPBACK模式接收。
// 运行过程中的信息通过UART向计算机机传输。
int main(void)
{
	//使能FPUFPUEnable();FPULazyStackingEnable();// 定义CAN的发送和接收对象tCANMsgObject sCANMessage;tCANMsgObject srCANMessage;// 定义发送数据存储区和接收数据存储区unsigned int uIdx;//一个循环语句使用的变量ui8 ucMsgData[4];ui8 ucrMsgData[8];// 禁用中断。在进行中断配置时要保证中断没被使用。IntMasterDisable();// 设置系统时钟为50MHzSysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);// 由于CAN0使用PN0、PN1两个引脚,需要使能GPION对应的时钟
//信号SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);// 使能CAN0模块的时钟信号SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);//将PN0和PN1两个引脚的功能选择为执行CAN0模块的功能GPIOPinConfigure(GPIO_PN0_CAN0RX);GPIOPinConfigure(GPIO_PN1_CAN0TX);// 对PN0和PN1两个引脚做有关CAN功能的配置GPIOPinTypeCAN(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1);// CAN控制器的初始化CANInit(CAN0_BASE);// 利用CANBitRateSet函数将CAN的传输速率设置为1MHzCANBitRateSet(CAN0_BASE, SysCtlClockGet(), 1000000);// 寄存器操作,将CAN0模块配置为运行于LOOPBACK模式HWREG(CAN0_BASE + CAN_O_CTL) = HWREG(CAN0_BASE + CAN_O_CTL) | CAN_CTL_TEST;HWREG(CAN0_BASE + CAN_O_TST) = HWREG(CAN0_BASE + CAN_O_TST) | CAN_TST_LBACK;// 使能CAN0模块CANEnable(CAN0_BASE);// 使能CAN0模块的中断IntEnable(INT_CAN0);//设置可以引起CAN中断的中断源CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);//初始化配置message object,即待发送的报文对象
//配置好报文对象后调用CANMessageSet函数进行设置,
//这样报文就可以自动被发送出去

// 待发送的数据为0*(ui32 *)ucMsgData = 0;// CAN message ID:使用1作为报文的IDsCANMessage.ui32MsgID = 1;
// 没有MASK屏蔽
sCANMessage.ui32MsgIDMask = 0;
//使能发送中断
sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE; 
//发送数据包大小为4个字节
sCANMessage.ui32MsgLen = sizeof(ucMsgData);
// 指向发送数据的指针
sCANMessage.pucMsgData = ucMsgData;// 初始化配置用于接收的报文对象
// 同样也是用CANMessageSet函数可以将某个message object(报文对象)
//设置为如下的配置// 可以接收任何ID的报文对象srCANMessage.ui32MsgID = 0;
// 没有屏蔽
srCANMessage.ui32MsgIDMask = 0;
// 使能接收中断和ID过滤srCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE|MSG_OBJ_USE_ID_FILTER;
// 允许最多8个字节的数据
srCANMessage.ui32MsgLen = 8;//将message object 2设置为接收报文对象
ROM_CANMessageSet(CAN0_BASE,2,&srCANMessage,MSG_OBJ_TYPE_RX);// 使能UART模块InitConsole();//使能中断IntMasterEnable();// 开始进入发送数据包的循环, 每秒将发送一个数据包。while(1){// 将待发送的数据包内容通过UART传输并显示出来UARTprintf("Sending msg: 0x%02X %02X %02X %02X",ucMsgData[0], ucMsgData[1], ucMsgData[2], ucMsgData[3]);// 将待发送的报文配置到message object 1中。CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);// 等待1sSimpleDelay();// 通过g_bErrFlag变量查看是否出错if(g_bErrFlag){UARTprintf(" error - cable connected?\n");}else{// 如果没有出错,则显示已经发送的报文数目UARTprintf(" total count Transmit = %u\n", g_ulMsgCount_TX);}// 每次发送完毕,都将报文中的数据内容+1(*(ui32 *)ucMsgData)++;// 接收报文程序// 通过g_bRXFlag判断是否有已经接收到是数据包if(g_bRXFlag){	// 建立指向报文数据的缓存区	srCANMessage.pucMsgData = ucrMsgData;	// 读取接收到的报文对象。	// 将message object中的信息读取到srCANMessage接收对象中	CANMessageGet(CAN0_BASE,2,&srCANMessage,0);	// 将g_bRXFlag置为0。//等到下个报文到来时,中断函数会再次将它置1的	g_bRXFlag=0;	// 如果出现数据丢失等错误,则输出提示信息	if(srCANMessage.ui32Flags & MSG_OBJ_DATA_LOST)	{		UARTprintf("CAN message loss detected\n");	}	// 通过UART输出接收到的报文信息	UARTprintf("Receive Msg ID=0x%08X len=%u data=0x",srCANMessage.ui32MsgID,srCANMessage.ui32MsgLen);	// 输出报文中的数据内容	for(uIdx=0;uIdx<srCANMessage.ui32MsgLen;uIdx++)	{		UARTprintf("%02X",ucrMsgData[uIdx]);	}	// 输出所有已收到的报文数目	UARTprintf(" total count Received = %u\n", g_ulMsgCount_RX);}}return(0);
}
xyz549040622:

回复 jiang chenglong:

楼主的问题解决了没有,有关我的回复,在另一个帖子中有说明,如果您已经解决了问题,希望您能够分享经验。

赞(0)
未经允许不得转载:TI中文支持网 » 清华大学TM4C123微处理器原理与实践例程-CAN实验程序解析
分享到: 更多 (0)