📄 can.c
字号:
#include "..\CAN\can.h"
/* 全局接收缓冲数据区,除开揭示信息,依下面的数据信息说明可知:
一共有8×18=144帧,每帧12个字节,故缓冲区大小为144×12字节 */
static stcCANRxData Global_CAN_RxDBuf[144];
/* 18个接收缓冲区,对应18种数据 */
static CAN_RxBuf Drv_CAN_RxBuf[18];
/* 各缓冲区帧数,每种数据皆为8帧 */
static uint32 Drv_CAN_RxDBufSize[18] = {8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8};
/* 数据信息说明:
测速测距单元1 8帧×12字节 CAN优先级0x04 0
测速测距单元2 8帧×12字节 CAN优先级0x05 1
机车信号1 8帧×12字节 CAN优先级0x08 2
机车信号2 8帧×12字节 CAN优先级0x09 3
1端显示器按键 8帧×12字节 CAN优先级0x48 4
2端显示器按键 8帧×12字节 CAN优先级0x49 5
显示器设定1 8帧×12字节 CAN优先级0x4C/0x4D 6
显示器设定2 8帧×12字节 CAN优先级0x50/0x51 7
显示器设定3 8帧×12字节 CAN优先级0x54/0x55 8
1端显示器自检 8帧×12字节 CAN优先级0xC8 9
2端显示器自检 8帧×12字节 CAN优先级0xC9 10
显示器转储请求 8帧×12字节 CAN优先级0xCC/0xCD 11
记录单元自检 8帧×12字节 CAN优先级0xE0 12
记录单元发送文件目录 8帧×12字节 CAN优先级0xE1 13
记录单元发送文件数据 8帧×12字节 CAN优先级0xE2 14
通信板发送信息 8帧×12字节 保留 15
CAN3 8帧×12字节 保留 16
CAN4 8帧×12字节 保留 17
*/
static stcCANTxData Global_CAN_TxDBuf[80]; /* 4个通用发送缓冲数据区 */
static CAN_TxBuf Drv_CAN_TxBuf[4]; /* 4个通用发送缓冲区 */
static uint32 Drv_CAN_TxDBufSize[4] = {32, 32, 8, 8}; /* 各缓冲数据区帧数 */
eSend_CMD SendCMD[CAN_MAX_NUM]; /* 定义发送命令(CAN_MAX_NUM = 4)*/
/************************************************************************************
功能:创建验收滤波LUT表格
参数:nCell[5] -- 指定每个表格Cell的个数,每个Cell为32bits;
返回值:enum LUT_BUILD_ERR -- LUT状态枚举
*************************************************************************************/
uint32 CAN_AFBuildLUT(uint32 nCell[5])
{
uint32 i;
uint32 * pU32;
uint32 tmpREGSFF_sa, tmpREGSFF_GRP_sa, tmpREGEFF_sa;
uint32 tmpREGEFF_GRP_sa, tmpREGENDofTable;
/* 接收过滤用RAM区大小为2048(0x800)个字节 */
if (4 * (nCell[0] + nCell[1] + nCell[2] + nCell[3] + nCell[4]) > 0x800)
{
return TOTAL_SIZE_TOO_LARGE;
}
/* 扩展标志符范围表格必须以偶数个cell出现 */
if ((nCell[4] & 0x01) != 0) /* 或用条件(nCell[4] % 2) != 0 */
{
return EFF_GRP_SIZE_INVALID;
}
tmpREGSFF_sa = (nCell[0] << 2);
tmpREGSFF_GRP_sa = tmpREGSFF_sa + (nCell[1] << 2);
tmpREGEFF_sa = tmpREGSFF_GRP_sa + (nCell[2] << 2);
tmpREGEFF_GRP_sa = tmpREGEFF_sa + (nCell[3] << 2);
tmpREGENDofTable = tmpREGEFF_GRP_sa + (nCell[4] << 2);
/* FullCAN模式下必须满足:EndOfTable <= 0x800 - 6 * SFF_sa(解释详见《LPC2000系列32位ARM微控制器的CAN接收过滤设置》P8)*/
if ((0x800 - tmpREGSFF_sa * 6) < tmpREGENDofTable)
{
return FCAN_STORE_SIZE_INVALID;
}
regCANAFMR = 0x02; /* 要修改接收过滤相关的寄存器和LUT内容时,必须先将AFMR中的AccBP置位 */
pU32 = (uint32 *)(CANAFRAM_GADR); /* 指向接收过滤用RAM(AF RAM)的首地址 */
/* 禁能所有的AF cell,即往cell中写入-1(0xFFFFFFFF) */
for (i = 0; i < (tmpREGENDofTable >> 2); i++)
{
*(pU32 + i) = 0xFFFFFFFF;
}
/* 清空FullCAN自动接收存储区 */
for (i = (tmpREGENDofTable >> 2); i < 0x200; i++)
{
*(pU32 + i) = 0;
}
/* 初始化各接收过滤寄存器 */
regCANSFF_sa = tmpREGSFF_sa;
regCANSFF_GRP_sa = tmpREGSFF_GRP_sa;
regCANEFF_sa = tmpREGEFF_sa;
regCANEFF_GRP_sa = tmpREGEFF_GRP_sa;
regCANENDofTable = tmpREGENDofTable;
return LUT_SETTING_OK;
}
/************************************************************************************
功能:初始化FullCAN表格
参数:pTab -- 指向待设定FullCAN表格的数组;
nCell -- 待设定cell数目
返回值:enum LUT_BUILD_ERR -- LUT状态枚举
*************************************************************************************/
uint32 CAN_AFInitFCANTab(_AF_SFF_CELL * pTab, uint32 nCell)
{
uint32 i;
_AF_SFF_CELL *pU32 = (_AF_SFF_CELL *)(CANAFRAM_GADR); /* FullCAN表格首地址 */
/*将cell写入-1(即0xFFFFFFFF),也可以用 _AF_SFF_CELL mask = {-1, -1, -1, -1, -1, -1, -1, -1};替代该语句*/
_AF_SFF_CELL mask = {0x7FF, 1, 1, 0x07, 0x7FF, 1, 1, 0x07};
/* 判断FullCAN表格是否超出范围 */
if (nCell > (regCANSFF_sa >> 2))
{
return TABLE_CELL_TOO_LARGE;
}
/* 判断cell的内容是否有效 */
for (i = 0; i < nCell; i++)
{
/* 每个cell的控制器编号必须相同,高位标志符小于低位标志符 */
if ((pTab[i].LoCh != pTab[i].UpCh) || (pTab[i].LoId >= pTab[i].UpId))
{
return CELL_CONTENT_INVALID;
}
}
regCANAFMR = 0x02; /* 要修改接收过滤相关的寄存器和LUT内容时,必须将AFMR中的AccBP置位 */
/* 格式化FullCAN表格,即cell全部置位 */
for (i = 0; i < (regCANSFF_sa >> 2); i++)
{
*(pU32 + i) = mask;
}
/* 创建FullCAN cell */
for (i = 0; i < nCell; i++)
{
*(pU32 + i) = *(pTab + i);
}
regCANAFMR = 0x00; /* 通知FullCAN表格已初始化,恢复正常模式 */
return LUT_SETTING_OK;
}
/************************************************************************************
功能:初始化独立标准帧标识符表格
参数:pTab -- 指向待设定独立标准帧标识符表格的数组;
nCell -- 待设定cell数目
返回值:enum LUT_BUILD_ERR -- LUT状态枚举
*************************************************************************************/
uint32 CAN_AFInitSFFIndvTab(_AF_SFF_CELL * pTab, uint32 nCell)
{
uint32 i;
_AF_SFF_CELL *pU32 = (_AF_SFF_CELL *)((CANAFRAM_GADR) + (regCANSFF_sa)); /* 独立标准标识符表格首地址 */
/* 或用语句_AF_SFF_CELL mask = {-1, -1, -1, -1, -1, -1, -1, -1};替代 */
_AF_SFF_CELL mask = {0x7FF, 1, 1, 0x07, 0x7FF, 1, 1, 0x07};
/* 判断独立标准标识符表格是否超出范围 */
if (nCell > ((regCANSFF_GRP_sa - regCANSFF_sa) >> 2))
{
return TABLE_CELL_TOO_LARGE;
}
/* 判断cell的内容是否有效 */
for (i = 0; i < nCell; i++)
{
/* 每个cell的控制器编号必须相同,高位标志符小于低位标志符 */
if ((pTab[i].LoCh != pTab[i].UpCh) || (pTab[i].LoId >= pTab[i].UpId))
{
return CELL_CONTENT_INVALID;
}
}
regCANAFMR = 0x02; /* 将AFMR中的AccBP置位,允许修改LUT内容和CAN接收过滤相关的寄存器 */
/* 格式化独立标准标志符表格,即将cell全部置位 */
for (i = 0; i < ((regCANSFF_GRP_sa - regCANSFF_sa) >> 2); i++)
{
*(pU32 + i) = mask;
}
/* 创建独立标准标志符表格 */
for (i = 0; i < nCell; i++)
{
*(pU32 + i) = *(pTab + i);
}
regCANAFMR = 0x00; /* 通知独立标准标志符表格已初始化,恢复正常模式 */
return LUT_SETTING_OK;
}
/************************************************************************************
功能:初始化标准帧标识符范围表格
参数:pTab -- 指向待设定标准帧标识符范围表格的数组;
nCell -- 待设定cell数目
返回值:enum LUT_BUILD_ERR -- LUT状态枚举
*************************************************************************************/
uint32 CAN_AFInitSFFGrpTab(_AF_SFF_CELL * pTab, uint32 nCell)
{
uint32 i;
_AF_SFF_CELL *pU32 = (_AF_SFF_CELL *)((CANAFRAM_GADR) + (regCANSFF_GRP_sa)); /* 标准帧标识范围表格首地址 */
/* 或用语句_AF_SFF_CELL mask = {-1, -1, -1, -1, -1, -1, -1, -1}; */
_AF_SFF_CELL mask = {0x7FF, 1, 1, 0x07, 0x7FF, 1, 1, 0x07};
/* 判断标准帧标识范围表格是否太大 */
if (nCell > ((regCANEFF_sa - regCANSFF_GRP_sa) >> 2))
{
return TABLE_CELL_TOO_LARGE;
}
regCANAFMR = 0x02; /* 允许修改LUT内容 */
/* 格式化标准帧标识范围表格 */
for (i = 0; i < ((regCANEFF_sa - regCANSFF_GRP_sa) >> 2); i++)
{
*(pU32 + i) = mask;
}
/* 创建标准帧标识范围表格 */
for (i = 0; i < nCell; i++)
{
*(pU32 + i) = *(pTab + i);
}
regCANAFMR = 0x00; /* 通知标准帧标识范围表格已初始化,恢复正常模式 */
return LUT_SETTING_OK;
}
/************************************************************************************
功能:初始化独立扩展帧标识符表格
参数:pTab -- 指向待设定独立扩展帧标识符表格的数组;
nCell -- 待设定cell数目
返回值:enum LUT_BUILD_ERR -- LUT状态枚举
*************************************************************************************/
uint32 CAN_AFInitEFFIndvTab(_AF_EFF_CELL * pTab, uint32 nCell)
{
uint32 i;
/* 扩展帧标识符表格首地址 */
_AF_EFF_CELL *pU32 = (_AF_EFF_CELL *)((CANAFRAM_GADR) + (regCANEFF_sa));
/* 或用_AF_EFF_CELL mask = {-1, -1}; */
_AF_EFF_CELL mask = {0x1FFFFFFF, 0x07};
/* 判断独立扩展帧标识符表格是否超出范围 */
if (nCell > ((regCANEFF_GRP_sa - regCANEFF_sa) >> 2))
{
return TABLE_CELL_TOO_LARGE;
}
regCANAFMR = 0x02; /* 允许修改LUT内容 */
/* 格式化独立扩展帧标识符表格 */
for (i = 0; i < ((regCANEFF_GRP_sa - regCANEFF_sa)>> 2); i++)
{
*(pU32 + i) = mask;
}
/* 创建独立扩展帧标识符表格 */
for (i = 0; i < nCell; i++)
{
*(pU32 + i) = *(pTab + i);
}
regCANAFMR = 0x00; /* 通知独立扩展帧标识符表格已初始化,恢复正常模式 */
return LUT_SETTING_OK;
}
/************************************************************************************
功能:初始化扩展帧标识范围表格
参数:pTab -- 指向待设定扩展帧标识范围表格的数组;
nCell -- 待设定cell数目
返回值:enum LUT_BUILD_ERR -- LUT状态枚举
*************************************************************************************/
uint32 CAN_AFInitEFFGrpTab(_AF_EFF_CELL * pTab, uint32 nCell)
{
uint32 i;
/* 扩展帧标识范围表格首地址 */
_AF_EFF_CELL *pU32 = (_AF_EFF_CELL *)((CANAFRAM_GADR) + (regCANEFF_GRP_sa));
/* 或用_AF_EFF_CELL mask = {-1, -1}; */
_AF_EFF_CELL mask = {0x1FFFFFFF, 0x07};
/* 扩展标志符范围表格必须以偶数个cell出现
判断条件也可改为"(nCell[4] & 0x01) != 0" */
if ((nCell % 2) != 0)
{
return CELL_NUM_INVALID;
}
/* 判断扩展标志符范围表格cell数是否越限 */
if (nCell > ((regCANENDofTable - regCANEFF_GRP_sa) >> 2))
{
return TABLE_CELL_TOO_LARGE;
}
regCANAFMR = 0x02; /* 允许修改LUT内容 */
/* 格式化扩展标志符范围表格 */
for (i = 0; i < ((regCANENDofTable - regCANEFF_GRP_sa)>> 2); i++)
{
*(pU32 + i) = mask;
}
/* 创建独立扩展帧标识符范围表格 */
for (i = 0; i < nCell; i++)
{
*(pU32 + i) = *(pTab + i);
}
regCANAFMR = 0x00; /* 通知独立扩展帧标识符范围表格已初始化,恢复正常模式 */
return LUT_SETTING_OK;
}
/************************************************************************************
功能:指定接收过滤器的工作模式,启动或关闭全局滤波器
参数:mode -- 接收过滤寄存器AFMR的各种模式枚举(AF_NORMAL、AF_IGNORE、AF_BYPASS、
AF_FULLCAN)
返回值:无
*************************************************************************************/
void CAN_AFSetMode(eAF_MODE mode)
{
regCANAFMR = 0x02; /* 允许修改接收过滤寄存器AFMR */
switch(mode)
{
case AF_NORMAL:
regCANAFMR = 0x00; /* 正常模式,执行全局过滤操作 */
break;
case AF_IGNORE:
regCANAFMR = 0x01; /* 忽略模式,接收器忽略总线上出现的数据 */
break;
case AF_BYPASS:
regCANAFMR = 0x02; /* 旁路模式,允许所有接收通过,以及用于修改与CAN接收过滤相关的寄存器和LUT内容 */
break;
case AF_FULLCAN:
regCANAFMR = 0x04; /* FullCAN模式,允许在全局接收过滤的基础上添加自动接收和存储功能 */
break;
default:
regCANAFMR = 0x00; /* 默认为正常模式 */
break;
}
}
/************************************************************************************
功能:获取接收过滤表格的结束偏移地址
参数:无
返回值:表格结束偏移地址,即ENDofTable寄存器中的值
*************************************************************************************/
uint32 CAN_AFGetEndOfTabOffset(void)
{
return regCANENDofTable;
}
/****************************************************************************************
功能:初始化接收和发送数据缓冲区:缓冲区帧数大小、有效帧数为0、缓冲区指针、
发送缓冲区下一读出位置为0
参数:无
返回值:无
*****************************************************************************************/
void CAN_InitBuf(void)
{
uint32 i;
uint8 * pTT;
/* 接收缓冲区设置 */
Drv_CAN_RxBuf[0].RxDBufSize = Drv_CAN_RxDBufSize[0]; /* 缓冲区帧数大小 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -