mascan.h
#ifndef MASCAN_H_
#define MASCAN_H_
#include "derivative.h"
#include "typedefs.h"
#include "SWLIBS_Typedefs.h" //定义mascan.h和其包含的头文件
#endif /* MASCAN_H_ */
struct can_msg //can信号结构体定义
{
unsigned int id; //标准帧id
unsigned char RTR; //RTR:1位远程帧,0为数据帧
unsigned char data[8]; //帧数据
unsigned char len; //数据长度
unsigned char prty; //优先级
};
extern struct can_msg msg;
extern struct can_msg RecvMsg; //头文件声明
void InitCAN(void);
int MSCAN0_Send(struct can_msg msg);
int MSCAN0_Receive(struct can_msg *msg);
void Can0_Send_TX23A_data(void);
void Can0_Send_TX23B_data(void);
void Can0_Send_TX23C_data(void);
void Can0_Send_TX23D_data(void);
void Can0_Send_TX23E_data(void);
void Can0_Receive_RX361_data(struct can_msg *msg);
void Can0_Receive_RX362_data(struct can_msg *msg);
void Can0_Receive_RX363_data(struct can_msg *msg);
void Can0_Receive_RX364_data(struct can_msg *msg);
void Can0_Receive_RX365_data(struct can_msg *msg);
extern int Testdata; //变量的定义
extern unsigned char Useer_LED1;
extern unsigned char Useer_LED2;
extern unsigned char Motor_Run;
extern tFrac16 RequiredSpeed;
extern volatile uint8_t RotDir;
/*
* mascan.c
#include <hidef.h>
#include "derivative.h" //mascan.c包含的头文件
#include "typedefs.h"
#include "SWLIBS_Typedefs.h"
#include "mascan.h" //该文件运行的头文件
struct can_msg msg; //can信号发送接收定义
struct can_msg RecvMsg;
int Testdata = 60;
unsigned char Useer_LED1 = 0;
unsigned char Useer_LED2 = 0; //所需要使用的变量定义
unsigned char Motor_Run;
tFrac16 RequiredSpeed;
volatile uint8_t RotDir;
can功能模块初始化;
CANCTL0寄存器:查询是否进入初始化状态;离开初始化状态,返回正常运行模式
当初始化模式处于有效的时候(INITRQ = 1 和 INITAK = 1)时,除WUPE,INITRQ和SLPRQ外的所有CANCTL0寄存器位都处于复位状态。只要退出初始化模式(INITRQ = 0,INITAK = 0),该寄存器可以再次写入。
CANBTR0,CANBTR1寄存器:设置波特率
CANBTR0,CANBTR1:配置MSCAN模块的各种CAN总线计时参数
CANIDMR寄存器:设置相应CAN口滤波器
这个是标识符掩码寄存器,指定标识符寄存器中的哪些相应位与接收过滤比较。我们选择关闭滤波器,全接收。
CANCTL1寄存器:使能MSCAN模块,设置MSCAN时钟源
这个模块提供了MSCAN模块的各种控制位和握手状态报文。
CANRIER寄存器:设置接收中断使能
该寄存器包含用于CANRELG寄存器中描述的中断标志的中断使能位。
128板子外部时钟源8Mhz,配置为内部时钟源为25Mhz(CAN0BTR1 = 0x16)
Bti Time = ×(1 + Time Segment1 + TimeSegment2)
Tsg1 为2个时间量子,Tsg2为7个时间量子,CAN总线时钟为25MHZ
CAN0BTR0_BRP = 4;//预分频因子为5
Bit Time = 2
则MSCAN波特率为500kHz
void InitCAN(void)
{
CAN0CTL1_CANE = 1; //mscan使能
if(CAN0CTL0_INITRQ==0) //查询是否进入初始化
CAN0CTL0_INITRQ =1; //进入初始化状态
while (CAN0CTL1_INITAK==0); //等待进入初始化状态
CAN0BTR0_SJW = 1; //设置同步
CAN0BTR0_BRP = 4; //设置波特率,预分频因子为5
CAN0BTR1 = 0x16; // Tsg1 为2个时间量子,Tsg2为7个时间量子,CAN总线时钟为25MHZ,MSCAN波特率为500kHz
//关闭滤波器
CAN0IDMR0 = 0xFF;
CAN0IDMR1 = 0xFF;
CAN0IDMR2 = 0xFF;
CAN0IDMR3 = 0xFF;
CAN0IDMR4 = 0xFF;
CAN0IDMR5 = 0xFF;
CAN0IDMR6 = 0xFF;
CAN0IDMR7 = 0xFF;
CAN0CTL1 = 0xC0; //MSCAN模块使能,定义MSCAN时钟源为总线时钟
CAN0CTL0 = 0x00; //返回到正常运行模式
while(CAN0CTL1_INITAK); //等到回到一般运行模式
while(CAN0CTL0_SYNCH==0); //等待总线时钟同步
CAN0RIER_RXFIE = 0; //使能接收中断
}
//发送函数
检查数据长度,检查时钟,寻找空闲缓冲器,写入标识符(CANIDR寄存器),判断帧类型(CANIDR寄存器),写入数据(CANDSR寄存器),写入数据长度(CANDLR寄存器),写入优先级(CANTBPR寄存器),清除发送标志位(CANTFLG寄存器)
标准帧发送
int MSCAN0_Send(struct can_msg msg)
{
unsigned char send_buf, sp;
if(msg.len > 8)
return(FALSE);
if(CAN0CTL0_SYNCH==0)
return(FALSE); //如果发送字节的长度和MSCAN时钟未同步到总线时钟,返回错误值。
send_buf = 0;
CAN0TBSEL=CAN0TFLG; //寻找空闲的缓冲器
send_buf=CAN0TBSEL;
CAN0TXIDR0 = (unsigned char)(msg.id>>3); //写入标识符
CAN0TXIDR1 = (unsigned char)(msg.id<<5);
if(msg.RTR) //RTR:1为远程帧,0为数据帧
CAN0TXIDR1 |= 0x10;
for(sp = 0; sp < msg.len; sp++) //开始写入数据
*((&CAN0TXDSR0)+sp) = msg.data[sp];
CAN0TXDLR = msg.len; //写入数据长度
CAN0TXTBPR = msg.prty; //写入优先级
CAN0TFLG = send_buf; //清除TXx标志(缓冲器准备发送)
return(TRUE);
}
CAN接收函数:
MSCAN接收的过程
检查接收标志:CANRFLG寄存器
检查帧模式(标准帧,扩展帧):CANIDR寄存器
读标识符:CANIDR寄存器
判断帧格式(远程帧,数据帧):CANIDR寄存器
读取数据长度:CANDLR寄存器
读取数据:CANDSR寄存器
清楚接收标志位:CANTFLG寄存器
CANIDR寄存器有两种型式:标准帧型式和扩展帧型式
CANDLR寄存器(数据长度寄存器):保存CAN帧的数据长度字段
CANDSR寄存器(数据段寄存器0-7):8个数据段寄存器(每个都带有位DB[7:0])包含将要发送或接收的数据。将要发送或接收的字节数有相应DLR寄存器中的数据长度代码决定。
CANTFLG寄存器(MSACAN发送器标志寄存器):每发送缓冲器空标志在CANTIRER寄存器中都有相应的中断使能位。
int MSCAN0_Receive(struct can_msg *msg)
{
unsigned char sp2;
if(!(CAN0RFLG_RXF)) //检测接收标志
return(FALSE);
if(CAN0RXIDR1_IDE) //检测CAN协议报文模式(一般,扩展)标识符号;0为标准格式,1为扩展格式
return(FALSE);
//读标识符号
msg->id = (unsigned int)(CAN0RXIDR0<<3)|(unsigned char)(CAN0RXIDR1>>5);
if(CAN0RXIDR1&0x10)
msg->RTR = TRUE;
else
msg->RTR = FALSE;
msg->len = CAN0RXDLR; //读取数据长度
for(sp2 = 0; sp2 < msg->len; sp2++) //读取数据
msg->data[sp2] = *((&CAN0RXDSR0)+sp2);
CAN0RFLG = 0x01; //清除RXF标志位(缓冲器准备接收)
return(TRUE);
}
//发送处理函数
//增加发送id
/*******************************ID:0x23A*************************************/
void Can0_Send_TX23A_data(void)
{
unsigned char data[8]={0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55};
msg.id = 0x23A; //id名称
msg.RTR = 0; //为数据帧
msg.len = 8; //数据长度为8
//给对应的数据赋值
msg.data[0] = (unsigned char) data[0];
msg.data[1] = (unsigned char) data[1];
msg.data[2] = (unsigned char) data[2];
msg.data[3] = (unsigned char) data[3];
msg.data[4] = (unsigned char) data[4];
msg.data[5] = (unsigned char) data[5];
msg.data[6] = (unsigned char) data[6];
msg.data[7] = (unsigned char) data[7];
msg.prty=0; //设置优先级
MSCAN0_Send(msg); //将以上设置的数据发送出去
}
//CAN接收处理函数:
//增加接收id
/*******************************ID:0x361*************************************/
void Can0_Receive_RX361_data(struct can_msg *msg)
{
if(msg->id == 0x361) //对361这个id的数据进行处理
{
Motor_Run=msg->data[0]; //对应第0位控制Motor Run
RequiredSpeed=msg->data[1]*256 + msg->data[2]; //第2,3位控制RequiredSpeed
RotDir = msg->data[3];
}
}
因为是做项目的时候的一个总结,在这个开发的过程中也遇到了很多的问题,一开始选用的是一块256的开发板,看网上也没有太多s12z系列芯片的开发内容,查资料花了很多的时间,希望这篇文章对你们有用,有想起来了的会几十更改的。新手,有错请见谅,告诉我及时改错。