前段时间在做了一个使用CAN接收数据,然后通过KEY选择是另一个CAN或者COM发送处理的数据。
我会通过连载的方式发布整个过程。
部分文件著作权归所属个人!(在注释中有)
首先,我们准备环境:
MDK3.5 + AK100(ZLG的ARM牛X仿真器)
其次,我整理思绪... ...
最基本,需要三个主要模块:CAN、UART、KEY。
CAN code:
/****************************************Copyright (c)**************************************************
** 广州致远电子有限公司
** 工业通信网络事业部
** http://www.embedcontrol.com
**-------------------------------------文件信息--------------------------------------------------------
** 文 件 名: LPC2300CAN.c
** 当 前 版 本: v1.0
** 日 期: 2007年5月06日
** 描 述:
**-------------------------------------历史创建--------------------------------------------------------
** 文 件 名: LPC2300CAN.c
** 版 本: v1.0
** 日 期: 2007年4月27日
** 创 建 人: 滕欣欣
** 描 述: LPC2300开发板实验教程实例代码
**-------------------------------------历史修改--------------------------------------------------------
** 文 件 名:
** 版 本:
** 日 期:
** 修 改 人:
** 描 述:
********************************************************************************************************/
#include "../can/LPC2300CAN.h"
#include "LPC2300CANReg.h"
#include "lpc23xx.h"
#include "../common/type.h"
static struct _MessageDetail MessageDetailT,MessageDetailR;
unsigned char dataAB[8];
unsigned long dataRID;
extern CAN_FIFOMailBox_TypeDef sFIFOMailBox;
/*
*********************************************************************************************************
**函数原型 : unsigned char Enter_SWRst(unsigned char Ch);
**参数说明 : Ch:CAN控制器号,0表示第一路CAN
**返回值 : 0:失败
** : 1: 成功
**说 明 : CAN控制器进入软件复位模式
*********************************************************************************************************/
unsigned char Enter_SWRst(unsigned char Ch)
{
unsigned long regaddr;
REG_CANMOD regmod;
regaddr = (unsigned long)(&CAN1MOD)+Ch*CANOFFSET;
regmod.DWord = RGE(regaddr); //读取CAN1MOD寄存器
regmod.Bits.RM = 1; //RM位置“1”
RGE(regaddr) = regmod.DWord; //回写CAN1MOD寄存器
regmod.DWord = RGE(regaddr); //验证写入值
return (0 != regmod.Bits.RM)? 1:0;
}
/*
*********************************************************************************************************
**函数原型 : unsigned char Quit_SWRst(unsigned char Ch);
**参数说明 : Ch:CAN控制器号,0表示第一路CAN
**返回值 : 0:失败
** : 1: 成功
**说 明 : CAN控制器退出软件复位模式
*********************************************************************************************************/
unsigned char Quit_SWRst(unsigned char Ch)
{
unsigned long regaddr;
REG_CANMOD regmod;
regaddr = (unsigned long)(&CAN1MOD)+Ch*CANOFFSET;
regmod.DWord = RGE(regaddr); //读取CAN1MOD寄存器
regmod.Bits.RM = 0; //RM位置“0”
RGE(regaddr) = regmod.DWord; //回写CAN1MOD寄存器
regmod.DWord = RGE(regaddr); //验证写入值
return (0 != regmod.Bits.RM)? 0:1;
}
/*
*********************************************************************************************************
**函数原型 : unsigned char CAN_Init(unsigned char Ch, unsigned long Baud);
**参数说明 : Ch:CAN控制器号,0表示第一路CAN
** : Baud:CAN波特率值
**返回值 : 无
**说 明 : CAN控制器退出软件复位模式
*********************************************************************************************************/
void CAN_Init(unsigned char Ch, unsigned long Baud)
{
unsigned long regaddr;
PCONP |= 0x01L<<13; //打开CAN控制器电源
switch(Ch) //配置CAN控制器引脚
{
case 0:
PINSEL0 &= ~(0x03L<<0);/*RD1*/
PINSEL0 |= (0x01L<<0);
PINSEL0 &= ~(0x03L<<2);/*TD1*/
PINSEL0 |= (0x01L<<2);
break;
case 1:
PINSEL1 &= ~(0x03L<<10);/*RD1*/
PINSEL1 |= (0x03L<<10);
PINSEL1 &= ~(0x03L<<12);/*TD1*/
PINSEL1 |= (0x03L<<12);
break;
default:
break;
}
Enter_SWRst(Ch);
regaddr = (unsigned long)(&CAN1BTR)+Ch*CANOFFSET;
RGE(regaddr) = Baud;
CAN_AFMR &= ~0x07; //设置为旁路模式
CAN_AFMR|=(1<<1);
Quit_SWRst(Ch);
}
/*
*********************************************************************************************************
**函数原型 : unsigned char CANRCVANDSEND(unsigned char Ch, unsigned char BUFNum);
**参数说明 : Ch:CAN控制器号,0表示第一路CAN
** : BUFNum 选择缓冲区
**返回值 : 无
**说 明 : CAN将收到的信息再发送出去
*********************************************************************************************************/
unsigned char CANRCVANDSEND(unsigned char Ch, unsigned char BUFNum)
{
unsigned long mes, CAN32reg;
unsigned long regaddr;
unsigned char i=5;
unsigned char i2 = 0;
BUFNum-=1; // 计算地址方便。
regaddr = (unsigned long)(&CAN1RFS)+Ch*CANOFFSET; //处理DLC、RTR、FF
mes = RGE(regaddr);
mes &= 0Xffff0000;
regaddr = (unsigned long)(&CAN1TFI1)+Ch*CANOFFSET+0X10*BUFNum;
RGE(regaddr)=mes;
regaddr = (unsigned long)(&CAN1RID)+Ch*CANOFFSET; //处理ID
mes = RGE(regaddr);
regaddr = (unsigned long)(&CAN1TID1)+Ch*CANOFFSET+0X10*BUFNum;
RGE(regaddr)=mes;
dataRID = mes;
regaddr = (unsigned long)(&CAN1RDA)+Ch*CANOFFSET; //处理 数据A
mes = RGE(regaddr);
regaddr = (unsigned long)(&CAN1TDA1)+Ch*CANOFFSET+0X10*BUFNum;
RGE(regaddr)=mes;
// MessageDetailR.DATAA = mes;
for (i2 = 0; i2 < 4; i2++) {
dataAB[i2] = mes >> 8 * i2;
}
regaddr = (unsigned long)(&CAN1RDB)+Ch*CANOFFSET; //处理 数据B
mes = RGE(regaddr);
regaddr = (unsigned long)(&CAN1TDB1)+Ch*CANOFFSET+0X10*BUFNum;
RGE(regaddr)=mes;
// MessageDetailR.DATAB = mes;
for (i2 = 0; i2 < 4; i2++) {
dataAB[4 + i2] = mes >> 8 * i2;
}
regaddr = (unsigned long)(&CAN1GSR)+Ch*CANOFFSET; //查 接收缓冲区状态
mes = RGE(regaddr);
while(mes&(1<<0)) // RBS为1 接收缓冲区满
{
regaddr = (unsigned long)(&CAN1CMR)+Ch*CANOFFSET;
mes=RGE(regaddr);
mes |= (1<<2); //释放接收缓冲区
RGE(regaddr)=mes;
if(!(i--))
{
return(0);
}
}
// regaddr = (unsigned long)(&CAN1CMR)+Ch*CANOFFSET;
// mes=RGE(regaddr);
// mes &= (~(1<<2));
// RGE(regaddr)=mes;
return(1);
}
/*
*********************************************************************************************************
**函数原型 : unsigned char writedetail(unsigned char LEN,unsigned char FF, unsigned int ID,unsigned char *data);
**参数说明 : LEN:数据长度
** : *data 发送数据所在的数组
:
**返回值 : 操作成功返回 1 失败返回 0
**说 明 : 用户填写发送 帧信息
*********************************************************************************************************/
unsigned char writedetail(unsigned char LEN,unsigned char FF, unsigned int ID,unsigned char *data)
{
unsigned char i;
if(LEN>8)
{
return(0);
}
else
{
MessageDetailT.LEN=LEN;
MessageDetailT.FF=FF;
MessageDetailT.CANID=ID;
MessageDetailT.DATAA=0; //先清零
MessageDetailT.DATAB=0;
for(i=0;i<LEN;i++)
{
if(i<4)
{
MessageDetailT.DATAA |= (*(data+i)<<(i*8));
}
else
{
MessageDetailT.DATAB |= (*(data+i)<<((i-4)*8));
}
}
//MessageDetailT.DATAB = ID;
return(1);
}
}
/*
*********************************************************************************************************
**函数原型 : unsigned char CANSend(unsigned char Ch, unsigned char BUFNum);
**参数说明 : Ch:CAN控制器号,0表示第一路CAN
** : BUFNum 选择缓冲区
: MessageDetailT 报文的特征信息及数据
**返回值 : 无
**说 明 : CAN控制器退出软件复位模式
*********************************************************************************************************/
unsigned char CANSend(unsigned char Ch, unsigned char BUFNum)
{
unsigned long CAN32reg;
unsigned long regaddr;
unsigned char FFflag;
BUFNum-=1; // 计算地址方便。
regaddr = (unsigned long)(&CAN1TFI1)+Ch*CANOFFSET+0X10*BUFNum; // 3缓冲区间地址差 0x10
CAN32reg = RGE(regaddr);
CAN32reg &= ~((0x0fL<<16) | (0x01L<<30) | (0x80000000)); //清 DLC,RTR.FF位?
CAN32reg |= ((unsigned long)MessageDetailT.LEN<<16) | ((unsigned long)MessageDetailT.FF<<31);
RGE(regaddr)=CAN32reg;
FFflag = MessageDetailT.FF;
regaddr = (unsigned long)(&CAN1TID1)+Ch*CANOFFSET+0X10*BUFNum; //写帧ID
CAN32reg = RGE(regaddr);
if(FFflag) //FF为1,ID为29位
{
CAN32reg &=0x70000000;
CAN32reg |= (MessageDetailT.CANID & 0x1fffffff);
}
else
{
CAN32reg &= 0xfffff800; //FF为0 ,ID为11位
CAN32reg |= (MessageDetailT.CANID & 0x000007ff);
}
RGE(regaddr)=CAN32reg;
regaddr = (unsigned long)(&CAN1TDA1)+Ch*CANOFFSET+0X10*BUFNum; // 写帧数据A
RGE(regaddr) = MessageDetailT.DATAA;
regaddr = (unsigned long)(&CAN1TDB1)+Ch*CANOFFSET+0X10*BUFNum; // 写帧数据B
RGE(regaddr) = MessageDetailT.DATAB;
regaddr = (unsigned long)(&CAN1CMR)+Ch*CANOFFSET; //写控制寄存器,发送
CAN32reg = RGE(regaddr);
CAN32reg &= ~0x03;
CAN32reg |= 0x03;
CAN32reg &= ~((1<<5)|(1<<6)|(1<<7));
switch(BUFNum)
{
case 0: CAN32reg |= 01<<5;break;
case 1: CAN32reg |= 01<<6;break;
case 2: CAN32reg |= 01<<7;break;
default: break;
}
RGE(regaddr)=CAN32reg;
regaddr = (unsigned long)(&CAN1GSR)+Ch*CANOFFSET; //查询发送状态
CAN32reg = RGE(regaddr);
/*/if(CAN32reg&(1<<5)) //等待所有请求的发送已经完成
{
;
} */
if(CAN32reg&(1<<3)) //所有的请求已成功完成
{
return(1); //发送成功返回 1
}
else { return (0);} //发送失败返回 0
}
/*----------------------------------------------------------------------------
read a message from CAN peripheral and release it
*----------------------------------------------------------------------------*/
void CAN_rdMsg (CAN_msg *msg) {
// Read identifier information
if ((CAN1->sFIFOMailBox[0].RIR & CAN_ID_EXT) == 0) { // Standard ID
msg->format = STANDARD_FORMAT;
msg->id = (DWORD)0x000007FF & (CAN1->sFIFOMailBox[0].RIR >> 21);
} else { // Extended ID
msg->format = EXTENDED_FORMAT;
msg->id = (DWORD)0x0003FFFF & (CAN1->sFIFOMailBox[0].RIR >> 3);
}
// Read type information
if ((CAN1->sFIFOMailBox[0].RIR & CAN_RTR_REMOTE) == 0) {
msg->type = DATA_FRAME; // DATA FRAME
} else {
msg->type = REMOTE_FRAME; // REMOTE FRAME
}
// Read length (number of received bytes)
msg->len = (unsigned char)0x0000000F & CAN1->sFIFOMailBox[0].RDTR;
// Read data bytes
msg->data[0] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDLR);
msg->data[1] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDLR >> 8);
msg->data[2] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDLR >> 16);
msg->data[3] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDLR >> 24);
msg->data[4] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDHR);
msg->data[5] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDHR >> 8);
msg->data[6] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDHR >> 16);
msg->data[7] = (unsigned int)0x000000FF & (CAN1->sFIFOMailBox[0].RDHR >> 24);
CAN1->RF0R |= CAN_RF0R_RFOM0; // Release FIFO 0 output mailbox
}
此模块主要用到的函数为:CANRCVANDSEND()提供接收CAN总线的数据,在原例中为接收发送一体。我们需要稍微改造一下,
// MessageDetailR.DATAA = mes;
for (i2 = 0; i2 < 4; i2++) {
dataAB[i2] = mes >> 8 * i2;
}
我们知道CAN分数据A部分与数据B部分,每部分各为4个Byte数组。
上面即数据A部分的分离数组。
同理,我们只需要增加4,即可取到数据B部分的每个数组值。
// MessageDetailR.DATAB = mes;
for (i2 = 0; i2 < 4; i2++) {
dataAB[4 + i2] = mes >> 8 * i2;
}
至此,CAN模块处理完。