⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.c

📁 瑞萨的DOME板LIN主从节点程序调试通过可以使用
💻 C
字号:
/****************************************************************/
/* 项目名称     : R8C/23 CAN/LIN Demo Board		                */
/*              : 样例程序2                                     */
/*              : CAN收发										*/
/* 硬件环境		: R0K521237C000BB								*/
/* MCU型号      : R5F21237JFP                                   */
/* C编译器		: NC30WA,版本5.30.r02及以上					*/
/* 文件名	    : CAN.c											*/
/* 版本			: 1.0                                           */
/* 作者			: wangsy                                        */
/* 修订历史     :                                               */
/*			修订者		时间		版本	说明				*/
/*			wangsy		2006/9/11	1.0		初版发行			*/
/*																*/
/****************************************************************/
/*		Copyright, 2006 RENESAS TECHNOLOGY CORPORATION &        */
/*                      RENESAS SOLUTIONS CORPORATION			*/
/****************************************************************/

/*------------包含的头文件--------------*/
#include "..\inc\Comdef_r823.h"
#include "..\inc\CAN.h"

/*-------------变量定义-----------------*/
// CAN 接受帧
can_std_data_def ReceiveData = {0x00U, 0x08, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
// CAN 发送帧
can_std_data_def TransmitData = {SND_FRM_ID, 0x08, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};

uchar8 ucFlag_CAN0_RE = NO;		// CAN接收,事件触发标志

uchar8 re_slot = RCV_SLOT;		// 接收信箱
uchar8 tr_slot = SND_SLOT; 		// 发送信箱

/*-------------函数声明-----------------*/
void config_can0(void); 		// CAN0初始设置
void can0_receive(void);		// CAN0接收入口函数
void can0_transmit(void);		// CAN0发送入口函数
void set_bitrate_can0(void);	// CAN0波特率设置
// 移位(左移)函数 MISRA中不允许移位的位数为变量
uint16 left_shift(uint16 oprnd_obj, uchar8 left_bit);	
// 设置CAN0标准数据帧的发送
void set_trm_std_dataframe_can0(uchar8 in_slot, can_std_data_def * in_trm_data);
// 设置CAN0标准数据帧的接收
void set_rcv_std_dataframe_can0(uchar8 in_slot, uint16 in_sid);

/*-----------中断处理函数---------------*/
void int_can0_receive(void);

/*------------函数定义------------------*/
/*------------------------------------------------------
  名称		: config_can0
  功能		: CAN0初始设置
  入口		: 无
  出口		: 无
  调用		: 调用void set_bitrate_can0(void)
  寄存器	: c0ctlr, c0str,c0recic,c0gmr,c0lmar,c0lmbr
------------------------------------------------------*/
void config_can0(void)
{
	// canI/O 设置
	pd6_1 = 1;
	pd6_2 = 0;

	c0ctlr_addr.b.reset = 1; 				// 进入初始化模式
	c0ctlr_addr.b.sleep = 0; 				// 结束休眠模式	

	while(c0str_addr.b.state_reset == 0) 	// 等待处理器进入初始化模式
	{	
	}

	c0ctlr_addr.b.porten = 1;	   			// CAN端口使能
	c0ctlr_addr.b.loopback = 0;    			// 不采用自环模式 
	c0ctlr_addr.b.msgorder = 1;    			// 消息顺序:字节访问
	c0ctlr_addr.b.basiccan = 0;    			// 不采用Basic CAN模式
	c0ctlr_addr.b.buserren = 0;    			// 禁止总线错误中断 
	c0ctlr_addr.b.tsprescale = 0;  			// 时间戳预分频器:"period of 1bit time"

	set_bitrate_can0();  					// 调用比特率设置函数

	c0ctlr_addr.b.reset = 0;  				// 跳出初始化模式 

	while(c0str_addr.b.state_reset != 0)	// 确认跳出初始化模式
	{	
	}

	c0recic_addr.byte = CAN0_RCV_PRIORITY;	// CAN0接收中断优先级5

	//设置屏蔽寄存器为可以接收所有的ID
	c0gmr.ba.sidh = 0x0;		 
	c0gmr.ba.sidl = 0x0;		
	
	c0lmar.ba.sidh = 0x0;		
	c0lmar.ba.sidl= 0x0;

	c0lmbr.ba.sidh = 0x0;		
	c0lmbr.ba.sidl= 0x0;
}

/*------------------------------------------------------
  名称		: set_bitrate_can0
  功能		: CAN0波特率设置
  入口		: 无
  出口		: 无
  调用		: 无
  寄存器	: prc0,cclkr,c0conr
------------------------------------------------------*/
void set_bitrate_can0(void)
{
	// clock = 20MHz 
	prc0 = 1; 							// 打开保护寄存器
	cclkr &= ~(uchar8)0x00;				// 清零 CAN0 时钟寄存器
	prc0 = 0;							// 关闭保护寄存器
	c0conr_addr.b.brp = CAN0_BRP - 1U; 	// CAN 时钟预分频器 = 10  125kbps
	
	// 设置位时序
	c0conr_addr.b.sam = BT_SAM - 1U; 	// SS = 1 Tq 	
	c0conr_addr.b.pts = BT_PTS - 1U; 	// PTS = 1 Tq 
	c0conr_addr.b.pbs1 = BT_PBS1 - 1U;	// PBS1 = 3 Tq 
	c0conr_addr.b.pbs2 = BT_PBS2 - 1U;	// PBS2 = 3 Tq 
	c0conr_addr.b.sjw = BT_SJW - 1U; 	// SJW = 1 Tq 
}

/*------------------------------------------------------
  名称		: left_shift
  功能		: 移位(左移)函数
  入口		: 要求左移的位数
  出口		: 被移位的变量
  调用		: 无
  寄存器	: 无
------------------------------------------------------*/
uint16 left_shift(uint16 oprnd_obj, uchar8 left_bit)
{
	switch(left_bit)
	{
		case 0:
			break;
		case 1:
			oprnd_obj = oprnd_obj << 1;
			break;
		case 2:
			oprnd_obj = oprnd_obj << 2;
			break;
		case 3:
			oprnd_obj = oprnd_obj << 3;
			break;
		case 4:
			oprnd_obj = oprnd_obj << 4;
			break;
		case 5:
			oprnd_obj = oprnd_obj << 5;
			break;
		case 6:
			oprnd_obj = oprnd_obj << 6;
			break;
		case 7:
			oprnd_obj = oprnd_obj << 7;
			break;
		case 8:
			oprnd_obj = oprnd_obj << 8;
			break;
		case 9:
			oprnd_obj = oprnd_obj << 9;
			break;
		case 0x0a:
			oprnd_obj = oprnd_obj << 0x0a;
			break;
		case 0x0b:
			oprnd_obj = oprnd_obj << 0x0b;
			break;
		case 0x0c:
			oprnd_obj = oprnd_obj << 0x0c;
			break;
		case 0x0d:
			oprnd_obj = oprnd_obj << 0x0d;
			break;
		case 0x0e:
			oprnd_obj = oprnd_obj << 0x0e;
			break;
		case 0x0f:
			oprnd_obj = oprnd_obj << 0x0f;
			break;
		default:
			break;
	}
	
	// 将移位完的操作数返回
	return(oprnd_obj);
}

/*------------------------------------------------------
  名称		: set_trm_std_dataframe_can0
  功能		: 设置CAN0标准数据帧的发送
  入口		: in_slot:		信箱号
  			  *in_trm_data:发送数据帧的地址
  出口		: 无
  调用		: uint16 left_shift(uint16 oprnd_obj, uchar8 left_bit)
  寄存器	: c0mctl,c0icr,c0idr,c0slot
------------------------------------------------------*/
void set_trm_std_dataframe_can0(uchar8 in_slot, can_std_data_def *in_trm_data)
{
	uchar8 LoopCounter; 
	uint16 temp;

	// 确认可以发送
	while(c0mctl[in_slot].transmit.trmactive == 1)	
	{
	}

	// 清零CAN0消息控制寄存器
	while(c0mctl[in_slot].byte != 0x00)		
	{
		c0mctl[in_slot].byte = 0x00;		
	}

	// 对应信箱,CAN0中断控制寄存器禁止	
	temp = c0icr_addr.word + 0U;
	temp &= (~(left_shift((uint16)0x0001, in_slot)));
	c0icr_addr.word = (int16)temp;
	
	// 对应信箱,CAN0采用标准ID
	temp = c0idr_addr.word + 0U;
	temp &=  ~(left_shift((uint16)0x0001, in_slot));
	c0idr_addr.word = (int16)temp;
	
	c0slot[in_slot].ba.sidh = (uchar8)(((in_trm_data->id)>> 6U) & 0x1FU); 	// 设置SID10-6 	
	c0slot[in_slot].ba.sidl = (uchar8)((in_trm_data->id) & 0x3FU); 			// 设置SID5-0
	c0slot[in_slot].ba.dlc = in_trm_data->dlc;	 							// 设置DLC

	// 将发送数据放入CAN0发送信箱
	for(LoopCounter=0; (LoopCounter<(in_trm_data->dlc))&&(LoopCounter<8); ++LoopCounter)
    {	
        c0slot[in_slot].ba.data[LoopCounter] = in_trm_data->data[LoopCounter];
	}

	// 启动标准数据帧的发送
	c0mctl[in_slot].byte = 0x80; 	
}

/*------------------------------------------------------
  名称		: can0_receive
  功能		: CAN0接收
  入口		: 无
  出口		: 无
  调用		: void set_rcv_std_dataframe_can0(uchar8 in_slot, uint16 in_sid)
  寄存器	: 无
------------------------------------------------------*/
void can0_receive(void)
{
	// 调用CAN0标准数据帧的接收设置
	set_rcv_std_dataframe_can0(re_slot, ReceiveData.id);
}

/*------------------------------------------------------
  名称		: set_rcv_std_dataframe_can0
  功能		: 设置CAN0标准数据帧的接收
  入口		: in_slot:	信箱号
  			  in_sid:	接收SID
  出口		: 无
  调用		: uint16 left_shift(uint16 oprnd_obj, uchar8 left_bit)
  寄存器	: c0mctl,c0icr,c0idr,c0slot
------------------------------------------------------*/
void set_rcv_std_dataframe_can0(uchar8 in_slot, uint16 in_sid)
{
	uint16 temp;

	// 清零CAN0消息控制寄存器
	while(c0mctl[in_slot].byte != 0x00)		
	{	
		c0mctl[in_slot].byte = 0x00;		 
	}
	
	// 对应信箱,CAN0中断控制寄存器允许
	temp = c0icr_addr.word + 0U;
	temp |= left_shift((uint16)0x0001, in_slot);	
	c0icr_addr.word = (int16)temp;
	
	// 对应信箱,CAN0采用标准ID
	temp = c0idr_addr.word + 0U;
	temp &= ~(left_shift((uint16)0x0001, in_slot));	
	c0idr_addr.word = (int16)temp;
			
	c0slot[in_slot].ba.sidh = (uchar8)((in_sid>> 6U) & 0x1FU); 	// 设置 SID10-6 
	c0slot[in_slot].ba.sidl = (uchar8)(in_sid & 0x3FU); 		// 设置 SID5-0
	
	// 启动CAN0标准数据帧的接收 
	c0mctl[in_slot].byte = 0x40; 
}

/*------------------------------------------------------
  名称		: can0_transmit
  功能		: CAN0发送
  入口		: 无
  出口		: 无
  调用		: void set_trm_std_dataframe_can0(uchar8 in_slot, can_std_data_def * in_trm_data)
  寄存器	: 无
------------------------------------------------------*/
void can0_transmit(void)
{
    set_trm_std_dataframe_can0(tr_slot, &TransmitData);
}

/*------------------------------------------------------
  名称		: int_can0_receive
  功能		: 中断处理函数:CAN0接收
  入口		: 无
  出口		: 无
  调用		: 无
  寄存器	: c0mctl,c0slot
------------------------------------------------------*/
#pragma INTERRUPT int_can0_receive
void int_can0_receive(void)
{
	uchar8 lp_dlc;

	// 当发生中断时,将CAN0接收事件触发标志置为YES
	ucFlag_CAN0_RE = YES;

	// 确认新的数据来到
	while(c0mctl [re_slot].receive.newdata != 1)
	{
	}
	
	// 等待直到消息有效
	while(c0mctl[re_slot].receive.invaldata == 1)
	{
	}
	
	// 清零
	c0mctl[re_slot].receive.newdata = 0;
	
	// 检查过载错误
	if(c0mctl[re_slot].receive.msglost == 1) 
	{
		c0mctl[re_slot].receive.msglost = 0;

		// 当发生过载错误时的用户处理程序(略)
	}
	else
	{
	}

	// 读出消息
	ReceiveData.id = ((uint16)c0slot[re_slot].ba.sidh << 6) + c0slot[re_slot].ba.sidl;
	
	ReceiveData.dlc = c0slot[re_slot].ba.dlc;
	
	for(lp_dlc=0; lp_dlc<c0slot[re_slot].ba.dlc; ++lp_dlc)
	{
		ReceiveData.data[lp_dlc] = c0slot[re_slot].ba.data[lp_dlc];
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -