基于MSP430单片机实现的CAN通信系统
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include
#include "MCP2510.h"
void Init_SPI (void);
void Init_Port(void);
void Init_CLK(void);
void CS_Enable(void);
void CS_Disable(void);
void RessetMcp2510(void);
int GetStatusMcp2510(void);
void RtsMcp2510(char RTSn);
void BitModiMcp2510(char addr,char mask,char data);
void ReadMcp2510(int addr,int n,char outBuf[]);
void WriteMcp2510(int addr,int n,char inBuf[]);
void SetNormal(void);
void IsSendComplete(int addr);
void InitMcp2510(void);
void SendMsg(int nDLC,char inBuf[]);
int ReceiveMsg(char outBuf[]);
int nTX0_Len;
char nTX0_Flag;
int nSend_TX0;
char UART0_TX_BUF[26];
int nRX0_Len_temp;
int nRX0_Len;
char nRX0_Flag;
int nRev_UART0;
char UART0_RX_BUF[26];
char nRecID_Hi;
char nRecID_Lo;
void main(void)
{
char inBuf[8];
char outBuf[8];
int i;
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗
_DINT(); // 关闭中断
/////////////////////////////////
// 初始化
Init_CLK();
Init_Port();
Init_SPI();
nSend_TX0 = 0;
nRecID_Hi = 0;
nRecID_Lo = 0;
for(i = 0;i < 8;i++)
{
inBuf[i] = i;
outBuf[i] = 0;
}
_EINT();
for(;;)
{
ReceiveMsg(outBuf);
SendMsg(8,inBuf);
}
}
void Init_CLK(void)
{
unsigned int i;
BCSCTL1 = 0X00; //将寄存器的内容清零
//XT2震荡器开启
//LFTX1工作在低频模式
//ACLK的分频因子为1
do
{
IFG1 &= ~OFIFG; // 清除OSCFault标志
for (i = 0x20; i > 0; i--);
}
while ((IFG1 & OFIFG) == OFIFG); // 如果OSCFault =1
BCSCTL2 = 0X00; //将寄存器的内容清零
BCSCTL2 += SELM1; //MCLK的时钟源为TX2CLK,分频因子为1
BCSCTL2 += SELS; //SMCLK的时钟源为TX2CLK,分频因子为1
}
void Init_SPI (void)
{
//SPI0模块允许
ME1 |= USPIE0;
//将寄存器的内容清零
U0CTL = 0X00;
//数据为8比特,选择SPI模式,单片机为主机模式
U0CTL |= CHAR + SYNC + MM;
//将寄存器的内容清零
U0TCTL = 0X00;
// 时钟源为SMCLK,选择3线模式
U0TCTL = CKPH + SSEL1 + SSEL0 + STC;
//传输时钟为SMCLK / 4
UBR0_0 = 0X02;
UBR1_0 = 0X00;
//调整寄存器,没有调整
UMCTL_0 = 0X00;
//发送接收中断允许
IE1 |= UTXIE0;
IE1 |= URXIE0;
}
void Init_Port(void)
{
//将P3口所有的管脚在初始化的时候设置为输入方式
P3DIR = 0;
//将P3口所有的管脚设置为一般I/O口
P3SEL = 0;
//P3.1 P3.2 P3.3被分配为SPI口
P3SEL = BIT3 + BIT2 + BIT1;
//P1.0作为输出管脚
P1DIR |= BIT0;
//P3.3作为输出管脚
P3DIR |= BIT3;
//P3.1作为输出管脚
P3DIR |= BIT1;
//P1.0 输出高电平,MCP2510不被选通
P1OUT |= BIT0;
return;
}
void CS_Enable(void)
{
//P1.0输出低电平
P1OUT &=~(BIT0);
return ;
}
void CS_Disable(void)
{
//P1.0输出高电平
P1OUT|=BIT0;
return ;
}
interrup
t [UART0TX_VECTOR] void UART0_TX_ISR(void)
{
if(nTX0_Len != 0)
{
// 表示缓冲区里的数据没有发送完
nTX0_Flag = 0;
TXBUF0 = UART0_TX_BUF[nSend_TX0];
nSend_TX0 += 1;
if(nSend_TX0 >= nTX0_Len)
{
nSend_TX0 = 0;
nTX0_Len = 0;
nTX0_Flag = 1;
}
}
}
interrupt [UART0RX_VECTOR] void UART0_RX_ISR(void)
{
//接收来自的数据
UART0_RX_BUF[nRX0_Len_temp] = RXBUF0;
nRX0_Len_temp += 1;
if(nRX0_Len_temp >= nRX0_Len)
{
nRev_UART0 = 1;
nRX0_Len_temp = 0;
nRX0_Len = 0;
}
}
void RessetMcp2510(void)
{
int i;
CS_Enable();
for(i = 10;i > 0;i--) ;
//复位命令
UART0_TX_BUF[0] = (char)(0xC0);
nTX0_Len = 1;
// 设置中断标志,进入发送中断程序
IFG1 |= UTXIFG0;
for(i = 100;i > 0;i--) ;
CS_Disable();
return;
}
int GetStatusMcp2510(void)
{
int i;
int nStatus = 0;
CS_Enable();
for(i = 10;i > 0;i--) ;
//读状态命令
UART0_TX_BUF[0] = 0xA0;
nTX0_Len = 1;
// 设置中断标志,进入发送中断程序
IFG1 |= UTXIFG0;
nRX0_Len = 1;
while(1)
{
if(nRev_UART0 == 1)
{
nRev_UART0 = 0;
nStatus = (int)(UART0_RX_BUF[0]);
break;
}
}
for(i = 100;i > 0;i--) ;
CS_Disable();
return nStatus;
}
void RtsMcp2510(char RTSn)
{
int i;
CS_Enable();
for(i = 10;i > 0;i--) ;
//请求发送命令
UART0_TX_BUF[0] = (char)(0x80 | RTSn);
nTX0_Len = 1;
// 设置中断标志,进入发送中断程序
IFG1 |= UTXIFG0;
for(i = 100;i > 0;i--) ;
CS_Disable();
return;
}
void BitModiMcp2510(char addr,char mask,char data)
{
int i;
CS_Enable();
for(i = 10;i > 0;i--) ;
//位修改送命令
UART0_TX_BUF[0] = 0x05;
UART0_TX_BUF[0] = addr;
UART0_TX_BUF[0] = mask;
UART0_TX_BUF[0] = data;
nTX0_Len = 4;
// 设置中断标志,进入发送中断程序
IFG1 |= UTXIFG0;
for(i = 100;i > 0;i--) ;
CS_Disable();
return;
}
void ReadMcp2510(int addr,int n,char outBuf[])
{
int i;
CS_Enable();
for(i = 10;i > 0;i--) ;
//读命令
UART0_TX_BUF[0] = 0x03;
UART0_TX_BUF[0] = addr;
for(i = 0;i < n;i++)
{
UART0_TX_BUF[i + 2] = 0;
}
nTX0_Len = 2 + n;
// 设置中断标志,进入发送中断程序
IFG1 |= UTXIFG0;
//接收数据
nRX0_Len = n;
while(1)
{
if(nRev_UART0 == 1)
{
nRev_UART0 = 0;
for(i = 0;i < n;i++)
{
outBuf[i] = UART0_RX_BUF[i];
}
break;
}
}
for(i = 100;i > 0;i--) ;
CS_Disable();
return;
}
void WriteMcp2510(int addr,int n,char inBuf[])
{
int i;
CS_Enable();
for(i = 10;i > 0;i--) ;
//写命令
UART0_TX_BUF[0] = 0x02;
UART0_TX_BUF[0] = addr;
for(i = 0;i < n;i++)
{
UART0_TX_BUF[i + 2] = inBuf[i];
}
nTX0_Len = 2 + n;
// 设置中断标志,进入发送中断程序
IFG1 |= UTXIFG0;
for(i = 100;i > 0;i--) ;
CS_Disable();
return;
}
void SetNormal(void)
{
int nFlag = 1;
int i;
char outBuf[10];
for(i = 0;i < 10;i++)
{
outBuf[i] = 0;
}
//设置成正常模式
BitModiMcp2510(CANSTAT,0xe0,0x00);
do
{
ReadMcp2510(CANSTAT,1,outBuf);
nFlag = outBuf[0] & 0xe0;
}while(nFlag);
return;
}
void IsSendComplete(int addr)
{
int i;
int nFlag = 1;
char outBuf[10];
for(i = 0;i < 10;i++)
{
outBuf[i] = 0;
}
do
{
ReadMcp2510(addr,1,outBuf);
nFlag = outBuf[0] & 0x08;
}while(nFlag);
return;
}
void InitMcp2510(void)
{
char inBuf[10];
//复位
RessetMcp2510();
//设置拨特率
inBuf[0] = 0x02;
inBuf[1] = 0x90;
inBuf[2] = 0x07;
WriteMcp2510(CNF3,3,inBuf);
//RX0接收,屏蔽位为0,过滤器为0
inBuf[0] = 0x00;
inBuf[1] = 0x00;
WriteMcp2510(RXM0SIDH,2,inBuf);
inBuf[0] = 0x00;
inBuf[1] = 0x00;
WriteMcp2510(RXF0SIDH,2,inBuf);
//CAN中断不使能
inBuf[0] = 0x00;
WriteMcp2510(CANINTE,1,inBuf);
//设置成正常模式
SetNormal();
}
void SendMsg(int nDLC,char inBuf[])
{
int i;
char sndBuf[16];
for(i = 0;i < nDLC;i++)
{
sndBuf[i] = inBuf[i];
}
WriteMcp2510(TXB0D0,nDLC,sndBuf);
sndBuf[0] = nDLC;
WriteMcp2510(TXB0DLC,1,sndBuf);
sndBuf[0] = 0x03;
sndBuf[1] = nRecID_Hi;
sndBuf[2] = nRecID_Lo;
WriteMcp2510(TXB0CTRL,3,sndBuf);
RtsMcp2510(0x01);
IsSendComplete(TXB0CTRL);
return;
}
int ReceiveMsg(char outBuf[])
{
int i;
int nFlag;
int nDLC;
char revBuf[16];
for(i = 0;i < 16;i++)
{
revBuf[i] = 0;
}
ReadMcp2510(CANINTF,1,revBuf);
nFlag = revBuf[0] & 0x01;
if(nFlag == 0)
{
return 0;
}
BitModiMcp2510(CANINTF,0x01,0x00);
ReadMcp2510(TXB0SIDH,2,revBuf);
nRecID_Hi = revBuf[0];
nRecID_Lo = revBuf[1] & 0xe0;
ReadMcp2510(RXB0DLC,1,revBuf);
nDLC = revBuf[0] & 0x0f;
ReadMcp2510(RXB0D0,nDLC,outBuf);
return 1;
}