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

📄 lib_can.c

📁 基于sam7x256平台做的CAN与网口互转接口
💻 C
字号:
//*------------------------------------------------------------------------------------------------
//* 文件名				: lib_can.c
//* 功能描述			: can驱动函数
//*------------------------------------------------------------------------------------------------

//*------------------------------------------ 头文件 ----------------------------------------------
#include	"/uCOS_II/includes.h"
#include	"/at91sam7x256/include/AT91SAM7X256.h"
#include	"/at91sam7x256/include/lib_AT91SAM7X256.h"
#include	"/LwIP/include/lwip/opt.h"
#include	"/LwIP/include/lwip/err.h"
#include    "/at91sam7x256/periph/CAN/lib_can.h"
//*------------------------------------------------------------------------------------------------
volatile UBYTE testCAN = AT91C_TEST_NOK;
//*stcRcvCANCyBuf CANRcvCyBufApp;

//*HANDLER hCANRECV;
__irq void AT91F_CAN_Handler(void)
{
 volatile ULONG status;
 extern HANDLER hCANRECVD;
		
  status = AT91F_CAN_GetStatus(AT91C_BASE_CAN) & AT91F_CAN_GetInterruptMaskStatus(AT91C_BASE_CAN);
  AT91F_CAN_DisableIt(AT91C_BASE_CAN,status);
  //*取中断位,判断为何种类型的中断
  //*wakeup中断
  if(status & AT91C_CAN_WAKEUP) {
    testCAN = AT91C_TEST_OK;
  }

  //*接受中断,则发送信号量hCanInput给CAN接受任务
  if(status & AT91C_CAN_MB1) {
   OSAPISemSend(hCANRECVD);
  //*释放数据寄存器,允许接受下一帧
  AT91C_BASE_CAN->CAN_TCR=AT91C_CAN_MB1;
  
  }
   if(status & AT91C_CAN_MB2) {
   OSAPISemSend(hCANRECVD);
  //*释放数据寄存器,允许接受下一帧
  AT91C_BASE_CAN->CAN_TCR=AT91C_CAN_MB2;
  
  }
  //*发送中断
  if(status & AT91C_CAN_MB0) {
     
     //*添加用户代码
  }
  //*添加其他中断处理
}
//*------------------------------------------------------------------------------------------------
//*函数名称:CANInit
//*功能描述:CAN控制器的初始化
//*出口参数:
//*入口参数
//*------------------------------------------------------------------------------------------------
void CANInit(void)
{
  extern HANDLER hCANRECVD;//*注:此变量要在CAN入口进程中定义
  ULONG tick=0;
  //*使能 CAN PIOs
  AT91F_CAN_CfgPIO();
  //*使能 CAN Clock
  AT91F_CAN_CfgPMC();
 

  //*使能 CAN Transceiver
  AT91F_PIOA_CfgPMC();
  AT91F_PIO_CfgOutput(AT91C_BASE_PIOA,AT91B_CAN_TRANSCEIVER_RS) ;
  //* Clear PA23 <=> Enable Transceiver Normal Mode (versus Standby mode)使能传输引脚
  //*??????是PA23引脚还是PA2
  AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,AT91B_CAN_TRANSCEIVER_RS) ;

  // Init CAN Interrupt Source Level
  AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,                        	// CAN base address
                        AT91C_ID_CAN,                         	// CAN ID
                        AT91C_AIC_PRIOR_HIGHEST,               	// Max priority
                        AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, 	    // Level sensitive
                        AT91F_CAN_Handler);                     // C Handler

  AT91F_AIC_EnableIt(AT91C_BASE_AIC,AT91C_ID_CAN);
  //*初始化环形缓冲区
  CANRcvCyBufApp.FullFlag = 0;
  CANRcvCyBufApp.ReadPoint = 0;
  CANRcvCyBufApp.WritePoint = 0;

  // Cfg CAN Baudrate to 1Mbit/s => BRP = 5
  // We choose 8 Time Quanta (tCSC = 125ns): 8tCSC = tSYNC + tPRS + tPHS1 + tPHS2
  // Cfg PHASE1 PHASE2 PROPAG and SYNC segment
  // Delay of busdriver + delay of receiver circuit = 200ns
  // Delay of bus line considered negligible = 0ns
  // tPRS = 2*(200+0) = 400ns < 4tCSC => PROPAG = 3
  // tSYNC = 1tCSC =>  8tCSC = 1tCSC + 4tCSC + tPHS1 + tPHS2
  // tPHS1 + tPHS2 = 3tCSC => Phase Segment 2 = Max(IPT=2TQ,Phase Segment 1) = 2TQ => PHASE2 = 2-1 = 1 => PHASE1 = 0
  // tSJW = Min(4 TQ, Phase Segment 1) = 1TQ => SJW = 1-1 = 0
  AT91F_CAN_CfgBaudrateReg(AT91C_BASE_CAN,0x00050301);
  //*创建信号量 hCANRECV,控制等待发送任务!用于CAN发送任务与EMAC接受任务得通讯
    hCANRECVD= OSAPISemNew(2);
  // Enable CAN and Wait for WakeUp Interrupt
  AT91F_CAN_EnableIt(AT91C_BASE_CAN,AT91C_CAN_WAKEUP);//*WAKEUP中断
  AT91F_CAN_CfgModeReg(AT91C_BASE_CAN,AT91C_CAN_CANEN);//*使能CAN
  //*等待启动,若成功则返回AT91_TEST_OK,否则返回AT91_TEST_OK
  //*testCAN在AT91F_CAN_Handler中断函数中定义,测试启动是否成功
  while( (testCAN != AT91C_TEST_OK) && (++tick < AT91C_CAN_TIMEOUT) ) ;
  testCAN=AT91C_TEST_NOK;
  if (tick >= AT91C_CAN_TIMEOUT) {
  //*如果超时关闭总线
  AT91F_DisableCAN(AT91C_BASE_CAN); 
  } 
  
}
//*------------------------------------------------------------------------------------------------
//*函数名称:AT91F_InitMailbox(MailBoxNUM num)
//*功能描述:邮箱初始化
//*出口参数:
//*入口参数
//*------------------------------------------------------------------------------------------------
void AT91F_InitMailbox(void)
{

  //*init mailbox0
   AT91F_InitMailboxRegisters(AT91C_BASE_CAN_MB0,
                             AT91C_CAN_MOT_TX | AT91C_CAN_PRIOR,                    // Mailbox Mode Reg
                             0x00000000,                                            // Mailbox Acceptance Mask Reg
                             AT91C_CAN_MIDvA & (0x07<<18),	                        // Mailbox ID Reg
                             0x11223344,                                            // Mailbox Data Low Reg
                             0x01234567,                                            // Mailbox Data High Reg
                             (AT91C_CAN_MDLC & (0x8<<16)) );                        // Mailbox Control Reg

   AT91F_InitMailboxRegisters(AT91C_BASE_CAN_MB1,
                             AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR,                    // Mailbox Mode Reg
                             AT91C_CAN_MIDvA | AT91C_CAN_MIDvB | AT91C_CAN_MIDE,    // Mailbox Acceptance Mask Reg
                             AT91C_CAN_MIDvA & (0x07<<18),	                        // Mailbox ID Reg
                             0x00000000,                                            // Mailbox Data Low Reg
                             0x00000000,                                            // Mailbox Data High Reg
                             0x00000000);                                           // Mailbox Control Reg
   AT91F_InitMailboxRegisters(AT91C_BASE_CAN_MB2,
                             AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR,                    // Mailbox Mode Reg
                             AT91C_CAN_MIDvA | AT91C_CAN_MIDvB | AT91C_CAN_MIDE,    // Mailbox Acceptance Mask Reg
                             AT91C_CAN_MIDvA & (0x07<<18),	                        // Mailbox ID Reg
                             0x00000000,                                            // Mailbox Data Low Reg
                             0x00000000,                                            // Mailbox Data High Reg
                             0x00000000);                                           // Mailbox Control Reg

}
//*------------------------------------------------------------------------------------------------
//*函数名称:ReadCANRcv(MailBoxNUM num)
//*功能描述:读取MaiBox中得数据,将MailBox得数据读到环形缓冲区中
//*出口参数:
//*入口参数:
//*------------------------------------------------------------------------------------------------
ULONG	ReadCANRcv(AT91PS_CAN_MB *MailBoxNum,stcRcvCANCyBuf *RcvCyBuf)
{
    ULONG	PointTemp = 0;
	ULONG	Statue = 0;
	PointTemp = RcvCyBuf->WritePoint;
	if((0 == RcvCyBuf->FullFlag))
	{
		/*RcvCyBuf->RcvBuf[PointTemp].CANRcvFS = RxBUF(CanNum).CANRcvFS;
		RcvCyBuf->RcvBuf[PointTemp].RxCANID = RxBUF(CanNum).RxCANID;*/
		RcvCyBuf->RcvBuf[PointTemp].RDA =  AT91F_CAN_GetMessageDataLow (MailBoxNum);
		RcvCyBuf->RcvBuf[PointTemp].RDB = AT91F_CAN_GetMessageDataHigh (MailBoxNum);
		//*获取数据
		
		if(++RcvCyBuf->WritePoint >= USE_CAN_cycRCV_BUF_SIZE)
			RcvCyBuf->WritePoint=0;
		if(RcvCyBuf->WritePoint == RcvCyBuf->ReadPoint)
			RcvCyBuf->FullFlag =1;
	}
	else
		Statue = 1;
	//*RelCanRecBuf(CanNum)清空MailBox
	return Statue;
 
 
}
//*------------------------------------------------------------------------------------------------
//*函数名称:SendCANData()
//*功能描述:
//*出口参数:
//*入口参数
//*------------------------------------------------------------------------------------------------
void  CanSendData(ULONG LData,ULONG HData)
{
  ULONG status;
  ULONG tick=0;



   //*AT91F_CAN_EnableIt(AT91C_BASE_CAN0,AT91C_CAN_MB0); 在此CAN0—MB0不接收数据,不用开中断
   AT91F_CAN_EnableIt(AT91C_BASE_CAN,AT91C_CAN_MB0);        // can1 为接收数据的邮箱 ,采用中断接收
   AT91F_CAN_CfgMessageDataLow (AT91C_BASE_CAN_MB0,LData);  //写入要发送的数据低4位

   AT91F_CAN_CfgMessageDataHigh(AT91C_BASE_CAN_MB0,HData);  //写入要发送的数据高4位

   AT91F_CAN_InitTransferRequest(AT91C_BASE_CAN,AT91C_CAN_MB0);        //请求发送
  tick=0;
  do {
     status = AT91F_CAN_GetMessageStatus(&(AT91C_BASE_CAN->CAN_MB0)) ; //waitting for send completed
   } while( !(status & AT91C_CAN_MRDY) && (++tick<AT91C_CAN_TIMEOUT) );

}

⌨️ 快捷键说明

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