📄 lib_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 + -