LPC17XX-CAN总线学习

CAN外设初始化(库函数),IO口设置为非开漏上拉模式

/************************************************************************************************
函数名:void CAN_config(void)
函数功能:CAN初始化
参数:无
返回值:无
*************************************************************************************************/
void CAN_config(void)
{
	PINSEL_CFG_Type PinCfg;
	/*-------------------------------------
	 * CAN1: select P0.0 as RD1. P0.1 as TD1
	 * 波特率125000
	---------------------------------------*/
	PinCfg.Portnum = 0;//GPIO0端口
	PinCfg.Pinnum = 0;//GPIO0_0
	PinCfg.Funcnum = 1;//设置GPIO管脚功能为CAN功能
	PinCfg.OpenDrain = 0;//非开漏模式
	PinCfg.Pinmode = 0;	//上拉
	PINSEL_ConfigPin(&PinCfg);
	PinCfg.Pinnum = 1;//GPIO0_1
	PINSEL_ConfigPin(&PinCfg);//初始化管脚配置结构体
	CAN_Init(LPC_CAN1, 125000);//初始化CAN1  波特率125K
	CAN_IRQCmd(LPC_CAN1, CANINT_RIE, ENABLE);//接收中断使能
	NVIC_EnableIRQ(CAN_IRQn);//使能中断
	CAN_SetAFMode(LPC_CANAF,CAN_AccBP);//验收文件旁路模式
	CAN_InitMessage();//初始化发送和接收缓冲区
	CAN_SendMsg(LPC_CAN1, &TXMsg);//发送数据
}

其中

CAN_InitMessage();//初始化发送和接收缓冲区
/************************************************************************************************
函数名:void CAN_InitMessage
函数功能:接收和发送缓冲区初始化
参数:无
返回值:无
*************************************************************************************************/
void CAN_InitMessage(void) 
{	
	TXMsg.format = EXT_ID_FORMAT;//扩展帧数据
	TXMsg.id = 0x00001234;//id号
	TXMsg.len = 8;//数据长度
	TXMsg.type = DATA_FRAME;//数据帧
	TXMsg.dataA[0] = TXMsg.dataA[1] = TXMsg.dataA[2] = TXMsg.dataA[3] = 0x00000011;
	TXMsg.dataB[0] = TXMsg.dataB[1] = TXMsg.dataB[2] = TXMsg.dataB[3] = 0x00000000;

	RXMsg.format = 0x00;
	RXMsg.id = 0x00;
	RXMsg.len = 0x00;
	RXMsg.type = 0x00;
	RXMsg.dataA[0] = RXMsg.dataA[1] = RXMsg.dataA[2] = RXMsg.dataA[3] = 0x00000000;
	RXMsg.dataB[0] = RXMsg.dataB[1] = RXMsg.dataB[2] = RXMsg.dataB[3] = 0x00000000;
}

数据帧是扩展帧还是正常帧是由发送数据结构体定义来决定的
扩展帧的帧ID长度是29位,帧ID的范围是0000 0000-1FFF FFFF。CANopen帧ID最多是11位的,因此是标准帧;可以简单认为CAN标准帧和扩展帧只是在ID的长度上不一样,以能扩展更多的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
	 */
	IntStatus = CAN_IntGetStatus(LPC_CAN1);
	//check receive interrupt
	if((IntStatus>>0)&0x01)
	{
		CAN_ReceiveMsg(LPC_CAN1,&RXMsg);
		CANRcvMsgParse(&RXMsg);
	}
}
CAN_ReceiveMsg(LPC_CAN1,&RXMsg);

其中这个语句是库函数中将接受寄存器的数据放入,用户自定义的缓存中。

CANRcvMsgParse(&RXMsg);
/*******************************************************************************************************************************
* 函数介绍:CANRcvMsgParse
* 参数:无
* 返回值:无
* 备注:解析CAN接收数据
*******************************************************************************************************************************/
void CANRcvMsgParse(CAN_MSG_Type *CAN_Msg)
{
	uint8 Index = 0;
	uint8 i = 0;
//	uint8  Buf[16] = {0};
  uint8 Buf[8] = {0};  //两个字节
	if(CAN_Msg->format != STD_ID_FORMAT)
	{
		return;
	}
	
	if(CAN_Msg->id == SWO_STA_ID+BrdAddr)		// 指示灯状态控制
	{
		for(i = 0;i < 4;i++)
		{
			Buf[Index++] = CAN_Msg->dataA[i];
		}
   
		for(i = 0;i < 4;i++)
		{
			Buf[Index++] = CAN_Msg->dataB[i];
		}
		if(BrdAddr==7)
		{
				targetDistance=(uint16_t)Buf[1]<<8|Buf[2];//数码管显示
				BrdValues.Out =Buf[0];	
		}
		else
		{
				BrdValues.Out =Buf[0];
		}
		printf("\r\n%#08X",BrdValues.Out);
		CANCommTimer.Cnt = 0;
		CanStatus = 1;
	}
}

自定义的一个can解析函数,将接收缓存的数据放入变量中。至此一个can的接收处理流程完成。
发送

void TaskExBoradsAd2(void)
{
	uint8 TxMsg[8] = {0};
	if(BrdAddr!=7)
	{
		TxMsg[0] = BrdValues.ADValue[4] / 256;
		TxMsg[1] = BrdValues.ADValue[4] % 256;
		TxMsg[2] = BrdValues.ADValue[5] / 256;
		TxMsg[3] = BrdValues.ADValue[5] % 256;
		CANSendMsg(ADI2_STA_ID+BrdAddr,TxMsg);
	}
}
/*******************************************************************************************************************************
* 函数介绍:CANRcvMsgParse
* 参数:uint16 Id:帧ID  
*      uint8 *Buf:数据变量的地址
* 返回值:无
* 备注:解析CAN接收数据
*******************************************************************************************************************************/
void CANSendMsg(uint16 Id,uint8 *Buf)
{
	CAN_MSG_Type Msg;

	Msg.format = STD_ID_FORMAT;//TXMsg.format = EXT_ID_FORMAT;
	Msg.id = Id;
	Msg.len = 8;
	Msg.type = DATA_FRAME;
	
	Msg.dataA[0] = Buf[0];
	Msg.dataA[1] = Buf[1];
	Msg.dataA[2] = Buf[2];
	Msg.dataA[3] = Buf[3];

	Msg.dataB[0] = Buf[4];
	Msg.dataB[1] = Buf[5];
	Msg.dataB[2] = Buf[6];
	Msg.dataB[3] = Buf[7];
	
	if(CAN_SendMsg(LPC_CAN1, &Msg) != SUCCESS)
	{
		CAN_SendMsg(LPC_CAN1, &Msg);
	}
}

目前没有用到以下

  1. CAN过滤器
void CAN_setup (uint32_t ctrl)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;

  if (ctrl == 1) {
    LPC_SC->PCONP       |=  (1 << 13);           /* Enable power to CAN1 block */
    LPC_PINCON->PINSEL0 |=  (1 <<  0);           /* Pin P0.0 used as RD1 (CAN1) */
    LPC_PINCON->PINSEL0 |=  (1 <<  2);           /* Pin P0.1 used as TD1 (CAN1) */
    
    NVIC_EnableIRQ(CAN_IRQn);                    /* Enable CAN interrupt */
  } else {
    LPC_SC->PCONP       |=  (1 << 14);           /* Enable power to CAN2 block */
    LPC_PINCON->PINSEL0 |=  (1 <<  9);           /* Pin P0.4 used as RD2 (CAN2) */
    LPC_PINCON->PINSEL0 |=  (1 << 11);           /* Pin P0.5 used as TD2 (CAN2) */
    
    NVIC_EnableIRQ(CAN_IRQn);                    /* Enable CAN interrupt */
  }

  LPC_CANAF->AFMR = 2;                           /* By default filter is not used 默认不使用过滤器*/
  pCAN->MOD   = 1;                               /* Enter reset mode 进入复位模式,禁能 CAN 操作,可写的寄存器可以写入,终止当前报文的发送/接收*/
  pCAN->IER   = 0;                               /* Disable all interrupts */
  pCAN->GSR   = 0;                               /* Clear status register ,*/
  CAN_cfgBaudrate(ctrl, 500000);                 /* Set bit timing 波特率设定/
  pCAN->IER   = 0x0003;                          /* Enable Tx and Rx interrupt */
}

LPC_SC->PCONP |= (1 << 13); 这句语句的作用是单片机外设使能,直接控制电源供给,类似stm32的RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
在这里插入图片描述

void CAN_start (uint32_t ctrl)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;

  pCAN->MOD = 0;                                 /* Enter normal operating mode */
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值