程序示例:#include "CAN.h"
#include "msp430_config.h"
#include "mcp2515.h"
#define uchar unsigned char
#define uint unsigned int
uchar flag;
INT16U NUM_COUNT = 0;
INT8U Time_Flag = 0;
#define CAN_RST_0 P1OUT &=~BIT1 //
#define CAN_RST_1 P1OUT |= BIT1 //
uchar Address; //地址
uchar RecvBuff[8]={0}; //接收缓存区
uchar SendBuff[8]={0}, SendIndex=0; //发送缓存区,接发送数据缓存区对应数
uchar can_isr_flag = 0; //P1.2有CAN中断标志:接收、发送、错误、溢出
uchar can_rcv_data_flag = 0; //CAN接收数据标志
uchar datapro_write_flag=0;//处理接收的数据正确,置位发送
uchar times; //计数次数
uchar SYSTime;
/////////////////////////////////////////////////////////////////////////////////////////////
void delay(uint x)
{
uchar i;
while(x--) for(i=120;i>0;i--);
}
///////////////////////////////////////////////////////////
void Init_Clk()
{
uchar i;
BCSCTL1&=~XT2OFF; //打开XT2振荡器 //基础时钟控制寄存器BCSCTL1的第7位置0,使XT2启动
do
{
IFG1 &= ~OFIFG; // 清除振荡器失效标志
for (i = 0xFF; i > 0; i--); // 延时,等待XT2起振
}
while ((IFG1 & OFIFG) != 0); // 判断XT2是否起振
BCSCTL2 =SELM_2+SELS+DIVS_0; //选择MCLK为XT2 SMCLK为XT2 不分频
}
/////////////////////////////////////////////////////////
void Init_TimeA()
{
TACCTL0 = CCIE; //TBCCR0允许中断
TACCR0 = 8000; //TIME:8000/(8mhz) =1ms
TACTL = TASSEL_2 + MC_1; //SMCLK,增计数模式
_BIS_SR( GIE);
}
///////////////////////////////////////////////////////////
void set_p12_to_int( void )
{
P1DIR&=~BIT2; // 中断引脚应该设置为输入
P1IES|=BIT2; //设置为下降沿触发,=0上升触发
P1IFG&=~BIT2; //因为P2IES设置会使中断标志位置位,故清零
P1IE|=BIT2; //设置中断使能
}
//////////////////////////////////////////////
void init_SD24()
{
uint i;
SD24CTL = SD24SSEL_1+SD24REFON+SD24DIV_3; // 1.2V ref, SMCLK,SMLCK 8分频
SD24INCTL0 = SD24INCH_0+SD24GAIN_16; // Set channel A0+/- 16倍增益
SD24CCTL0 |= SD24SNGL + SD24IE+SD24OSR_512+SD24DF; // Single conv,enable interrupt 采样率为512 数据格式(当增益为1时0-32768表示0~-600mv 65535~32768表示0~600mv)
for (i = 0; i < 0x3600; i++); // Delay for 1.2V ref startup
}
/////////////////////////////////////////////////////////////////////
void RecvDataProc() //处理从can来的数据或者命令
{
if(RecvBuff[1]<0x40)
{
switch(RecvBuff[1])
{
case 0x01: //读地址 ,单机命令
SendBuff[0]=0x00;
SendBuff[1]=0x01;
SendBuff[2]=Address;
SendBuff[3]=0X21;
SendIndex=4;
datapro_write_flag=1;
break;
case 0x02: //读压力
SendBuff[0]=Address;
SendBuff[1]=0x02;
SendBuff[2]= Ch0Adc /256;
SendBuff[3]= Ch0Adc %256;
SendBuff[4]= 0X21;
SendIndex=5;
datapro_write_flag=1;
break;
default :
datapro_write_flag=0;
break;
}//end switch
}//end
}
/************************************************************************************
** 函数名称: Pro_CAN_ERROR()
** 功能描述: CAN总线错误处理
** 输 入 : 数据类型 形参名 功能
** 输 出 : 数据类型 形参名 功能
** 全局变量: 无
** 调用模块: 无
*************************************************************************************/
void Pro_CAN_ERROR( void )
{
unsigned char num;
num=mcp2515_read_register( E** ); // 读错误标志寄存器,判断错误类型
if( num & EWARN ) // 错误警告寄存器,当TEC或REC大于或等于96时置1
{
mcp2515_write_register( TEC, 0 );
mcp2515_write_register( REC, 0 );
}
if( num & RXWAR ) // 当REC大于或等于96时置1
{ ; }
if( num & TXWAR ) // 当TEC大于或等于96时置1
{ ; }
if( num & RXEP ) // 当REC大于或等于128时置1
{ ; }
if( num & TXEP ) // 当TEC大于或等于128时置1
{ ; }
if( num & TXBO ) // 当TEC大于或等于255时置1
{ delay_s(10); } //延时10s,等待单片机看门狗复位
if( num & RX0OVR ) // 接收缓冲区0溢出
{
mcp2515_write_register( E**, num & ~RX0OVR ); // 清中断标志; // 根据实际情况处理,一种处理办法是发送远程桢,请求数据重新发送
}
if( num & RX1OVR ) // 接收缓冲区1溢出
{
mcp2515_write_register( E**, num & ~RX1OVR ); // 清中断标志;
}
}
/************************************************************************************
** 函数名称: CAN_ISR()
** 功能描述: CAN中断处理函数
*************************************************************************************/
void CAN_ISR(void)
{
uchar num1,num2,num3,num,i;
num1 = mcp2515_read_register(CANINTF);
// 读中断标志寄存器,根据中断类型,分别处理
//--------------------------- 报文错误中断
if( num1 & MERRF )
{
mcp2515_write_register( CANINTF, num1 & ~MERRF ); // 清中断标志
}
//--------------------------- 唤醒中断
if( num1 & WAKIF )
{
mcp2515_write_register( CANINTF, num1 & ~WAKIF ); // 清中断标志
mcp2515_write_register( CANCTRL, CAN_NORMAL_MODE ); // 唤醒后,在仅监听模式,须设置进入正常工作模式
//--------------------------- 判断是否进入正常工作模式
do
{
num = mcp2515_read_register( CANSTAT )& CAN_NORMAL_MODE;
}
while( num != CAN_NORMAL_MODE );
}
//--------------------------- Error interrupt!
if(num1 & ERRIF) // 错误中断
{
mcp2515_write_register(CANINTF, num1 & ~ERRIF); // 清中断标志
Pro_CAN_ERROR( ); // 分别处理各个错误
}
//--------------------------- TX2 success!
if( num1 & TX2IF ) // 发送2成功中断
{
mcp2515_write_register( CANINTF, num1 & ~TX2IF ); // 清中断标志
}
//--------------------------- TX1 success!
if( num1 & TX1IF ) // 发送1成功中断
{
mcp2515_write_register( CANINTF, num1 & ~TX1IF ); // 清中断标志
}
//--------------------------- TX0 success!
if(num1 & TX0IF) // 发送0成功中断
{
mcp2515_write_register(CANINTF, num1 & ~TX0IF); // 清中断标志
}
//--------------------------- RX1 interrupt!
if( num1 & RX1IF ) // 接收1成功中断
{
mcp2515_write_register( CANINTF, num1 & ~RX1IF ); // 清中断标志
}
if(num1 & RX0IF)
{
mcp2515_write_register(CANINTF, num1 & ~RX0IF); // 清中断标志
num2 = mcp2515_read_register( RXB0SIDL );
num3 = mcp2515_read_register( RXB0DLC );
num = num3 & 0x0f; // 求数据长度
if( num2 & IDE ) // 收到扩展帧
{
//--------------------------- Buffer 0 received extended remote frame!
if( num3 & RTR ) // 远程桢,则读取标识符,按照此标识符发送要求的数据
{ ; }
else // 数据桢,接收处理数据
{ //--------------------------- Buffer 0 received extended data frame,data length is num
for( i = 0; i < num; i++ )
{
RecvBuff[ i ] = mcp2515_read_register( RXB0D0 + i );
}
}
}
RecvDataProc(); //处理接收到的数据命令,诸如:读地址、读压力、设置地址。。。。
}
}
/////////////////////////////////////////////////////////
void can_service()
{
if(can_isr_flag==1) //如果有CAN中断
{
can_isr_flag=0;
CAN_ISR(); //can中断处理 :接收数据,以及错误、溢出等中断处理
if(datapro_write_flag==1)
{
datapro_write_flag=0;
CAN_TX_D_Frame( 0, SendIndex, &SendBuff[0] ); // 通过CAN发送缓冲区0,发送数据长度为SendIndex的扩展帧数据,数据在 SendBuff[]中
}
}
}
////////////////////////////////////////////////////////////////////////
void main(void)
{
/******************************************************************/
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
Init_Clk();
CAN_RST_1; //mcp2515退出复位
set_p12_to_int();
init_SD24();
/****************************************************************/
UCB0_SPI_Init(0X40); //USCI SPI模式初始化
UCB0_SPI_WriteByte(0X00);
/*******************************************************************/
CanBusConfig(); //MCP2515初始化模块
delay_s(1);
Init_TimeA();
__enable_interrupt(); //Enable the Global Interrupt
while(1)
{
if(SYSTime>=10) //TIME:100ms*10=1 S
{
SYSTime=0;
ConvToPreVal();
}
can_service(); //CAN服务程序,接收数据并按照协议处理数据,然后将处理的结果通过CAN总线上传
}
}
/******************************************************************
函数名称:
函数功能:CAN接收中断处理函数
入口参数:
返回参数:
函数说明:
******************************************************************/
#pragma vector = PORT1_VECTOR
__interrupt void CanRxISR_Handler(void)
{
if((P1IFG&BIT2) == BIT2) //处理P1IN.2中断
{
P1IFG &= ~BIT2; //清除中断标志
can_isr_flag=1;
}
}
/////////////////////////////////////////////////////////////
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
__disable_interrupt();
times++;
if(times>=100) //IME:1ms*100=100MS
{
SYSTime++;
SD24CCTL0 |= SD24SC;//AD开始转换
times=0;
}
__enable_interrupt();
}
/////////////////////////////////////////////////////////////////
uchar FilterIndex=0;
uint FilterBuf[4]={0};
#pragma vector=SD24_VECTOR //SD24 interrupt
__interrupt void SDA24(void)
{
//滑动平均滤波算法(递推平均滤波法)
uchar i;
long uint sum=0;
FilterBuf[FilterIndex++]=SD24MEM0;// Save CH0 results (clears IFG)
if(FilterIndex==4) FilterIndex=0; //先进先出,再求平均值
for(i=0;i<4;i++)sum+=FilterBuf;
Ch0Adc=(sum/4);
SD24INCTL0 = SD24INCH_0;
SD24CCTL0 |= SD24SNGL + SD24IE+SD24OSR_256; // Single conv,enable interrupt 采样率为512 数据格式(当增益为1时0-32768表示0~-600mv 65535~32768表示0~600mv
}
|