⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 一个基于SJA1000的CAN总线通讯程序
💻 C
字号:
#include <absacc.h>
#include <P89C58_PLUS.H>
#include "SJA1000.h"
#define MAX_AD_RECV_LEN		24
#define SLOT_ADDR			0xB000
#define SLOT_ADDR_COM  		0x02 // base addr

#define CAN_FLAG_NONE		0x00
#define CAN_FLAG_START		0x01
#define CAN_FLAG_RUNNING	0x02
#define CAN_FLAG_END		0x03

#define STA_IDLE			0
#define STA_RECEIVING		1
#define STA_SENDING			2

sbit    CAN0_RST = P3^4;
sbit    CAN1_RST = P1^0;
sbit    CS_LED = P1^3;
sbit    AD_CLK = P1^4;
sbit    AD_OUT = P1^5;
sbit    AD_IN  = P1^6;
sbit    AD_EOC = P3^3;
sbit    CS_AD  = P1^7;

sbit    TEST  =  P3^3;

unsigned char idata m_ad_buff[MAX_AD_RECV_LEN]; //高128位RAM7F-ff 指针方式
unsigned int  idata m_ad_tmp[5][11];
unsigned char m_times;

unsigned char bdata m_led_cond;//可位寻址的内存空间
sbit b_led1=m_led_cond^0;
sbit b_led2=m_led_cond^1;
sbit b_led3=m_led_cond^2;
sbit b_led4=m_led_cond^3;
sbit b_led5=m_led_cond^4;
sbit b_led6=m_led_cond^5;
sbit b_led7=m_led_cond^6;
sbit b_led8=m_led_cond^7;


unsigned char xdata *m_pByte;
unsigned int  m_last_time;
unsigned int  m_out_time;

unsigned char m_addr;
unsigned char m_chn_no;

// ...CAN Buffer....
unsigned char m_CanSend[10];
unsigned char m_CanRecv[10];
bit      m_bAuto;

unsigned char m_can_msg_len;
unsigned char m_can_recvs;
unsigned char idata m_buffull;

void P89C58_init();
void SJA1000_init();
bit  SJA1000_Send();
void TLC2543C_init();

unsigned char GetCANAddr();

unsigned int GetCRC(unsigned char num,unsigned char *pData);
extern void _nop_ (void);

void delay(unsigned int num)
{
    unsigned int i;
    for (i = 0; i < num; i ++) {
        _nop_();
    }
}

void LightLed()
{
    unsigned char i;
    unsigned char tmp;    
    unsigned char led;
    unsigned int  m_ad_result;

    led = 0;	
    for(i=0;i<8;i++)
    { 	
        m_ad_result =  m_ad_buff[2*i]<<8;
	    m_ad_result += m_ad_buff[2*i+1];
	    tmp = m_led_cond&(0x01<<i);
	    if(tmp&&(m_ad_result < 630))
	    {
	        led = led & (~(0x01<<i));
	    }	
        else led = led | (0x01<<i);
    }
    EA = 0;		
    P0 = led;
    CS_LED = 1; 
    CS_LED = 0; 
    EA = 1;
}

// ..Get CRC arrcording data
unsigned int GetCRC(unsigned char num,unsigned char *pData)
{
    unsigned char i,j;
	unsigned int  m_CRC;

    m_CRC = 0xffff;
    for( i = 0; i < num; i ++)
    {
      m_CRC = m_CRC^(*(pData + i));
      for( j = 0; j < 8; j++ )
	  {
	    if(m_CRC & 0x01)
	    {
		   m_CRC = m_CRC >> 1;
		   m_CRC=m_CRC ^ 0xa001;
	    }
	    else
	    {
		   m_CRC = m_CRC >> 1;
	    }
	  }
    }
	return m_CRC;    
}

/***************************************************************************************************************************************
 ..........................................P89C58.............................
 **************************************************************************************************************************************/
void P89C58_init()
{    
    TMOD = 0x21; //Mode 2: 8-bits with auto-reload from THx
    RCAP2H = 0xFF;
    RCAP2L = 0xB2;
    CS_LED = 0; //disable 573
    TH0 = 0xF8; //...1mS interrupt
	TL0 = 0x30;

    // ...Enable all interrupts.
    IE = 0;
    ET0 = 1; //Enable Timer0 interrupt
    EX0 = 1; //Enable INT0 for SJA1000 INT
    EX1 = 0; //Disable INT1 for AD INT
    ES  = 0; //Disable Serial port 0 interrupt.

    // ...Start timer 2
    TR0 = 1;   
}


/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 * Function:P89C58_ISR_Timer0()
 * Description:
 *	 Timer0 interrupt service routine
 */
void P89C58_ISR_Timer0() interrupt 1 using 2
{
   m_last_time = m_last_time ++;
   if(m_last_time > 3000) m_last_time = 3000;
   TH0 = 0xF8; //...1mS interrupt
   TL0 = 0x30;
   TR0 = 1;
}

/***************************************************************************************************************************************
 ..........................................SJA1000.............................
 **************************************************************************************************************************************/
void SJA1000_init()
{
   int j;

   CAN0_RST = 0;
   for(j = 0; j < 1000; j ++)
   {
      _nop_();
   }
   CAN0_RST = 1;

   // Enter reset mode
   SJA_REG_CR = 0x01;

   SJA_REG_ACR = m_addr;
   SJA_REG_AMR = 0x03; // 0000 00XX 000

   SJA_REG_BTR0 = 0x00;
   SJA_REG_BTR1 = 0x14;
   SJA_REG_OCR = 0xAA;
   SJA_REG_CDR = 0x48;

   // Enter operate mode
   SJA_REG_CR = 0x1A; //Enable all interrupt but transmit   
  }
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 * Function:SJA1000_ISR_0()
 * Description:
 *	 CAN interrupt service routine
 */
void SJA1000_ISR_0() interrupt 0 using 1
{
    unsigned char i;
    unsigned char num;
    unsigned char dlc;
    unsigned char status;
    unsigned char iir;	

    iir = SJA_REG_IR;
    status = SJA_REG_SR;

    if (iir & 0x01) {//RI receive interrupt
        m_CanRecv[0] = SJA_REG_RxBuf0;
	m_CanRecv[1] = SJA_REG_RxBuf1;
        dlc = m_CanRecv[1] & 0x0F;
	    for ( i = 0; i < dlc; i ++){
	        m_pByte = SJA_REG + 0x16 + i; // 0x16: the offset of SJA_REG_RxBuf2
	        num = *m_pByte;
	        m_CanRecv[i + 2] = num;
	    }
            m_can_msg_len=dlc-1;
	    m_buffull = 0x55;
            SJA_REG_CMD = 0x04; // Set RRB bit(Release receive buffer)  
    }

    if (iir & 0x08) {//data overrun interrupt
	    SJA_REG_CMD = 0x08; // Set CDO bit
    }
 }

/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 * Function:SJA1000_Send()
 * Description:
 *	 SJA1000 Send data
 */
bit SJA1000_Send()
{
    unsigned char i;
    unsigned char num;
    unsigned char status;
    
    status = SJA_REG_SR;

    if (status & 0x04 == 0) return 0;
	if (status & 0x08 == 0) return 0;

	for ( i = 0; i < 200; i ++) {
	   _nop_();
	}

    num = m_CanSend[1] & 0x0F;
    num = num + 2;
    for ( i = 0; i < num; i ++)
    {
       m_pByte = SJA_REG + 0x0A + i; // 0x0A: the offset of SJA_REG_TxBuf0
       *m_pByte = m_CanSend[i];
    }
    SJA_REG_CMD = 0x01; // Set TR bit
    return 1;
}

/***************************************************************************************************************************************
 ..........................................AD Converter(TLC2543C).............................
 ADDRESS BITS 		L1 L0 LSBF 	BIP
 D7	D6 D5 D4 		D3 D2 D1   	D0
(MSB)							(LSB)
 **************************************************************************************************************************************/
void TLC2543C_init()
{
    unsigned char i;
   
    AD_CLK = 0;
    CS_AD = 0;
   
    for (i = 0; i < 22; i ++) m_ad_buff[i] = 0;   
    delay(5);
   
}

void TLC2543C_filter()
{  
    unsigned char i;
	unsigned char j;
	unsigned int max;
	unsigned int min;
	unsigned int sum;    
	
    for (i=0;i<11;i++)
	{
	    max = m_ad_tmp[0][i];
		min = m_ad_tmp[0][i];
		
        for(j=1;j<5;j++)                //get the maxium and minimum value
		{
            if(m_ad_tmp[j][i] > max) max = m_ad_tmp[j][i];
			else if(m_ad_tmp[j][i] < min) min = m_ad_tmp[j][i];			
		}

		sum = 0;                       //calculate the five values
		for(j=0;j<5;j++)
		{
		    sum += m_ad_tmp[j][i];								
		}

		sum = sum - max;               //reduce the max and the min value
		sum = sum - min;
		sum = sum / 3;

		m_ad_buff[2*i]   = sum >> 8;   //get the result
		m_ad_buff[2*i+1] = sum;
	}
   
}

unsigned int TLC2543C_ad(unsigned char channel)
{    
    unsigned char chn;
	unsigned char i;
    unsigned int  val;    

	chn = channel<<4; /*0xB0----(Vref+ - Vref-)/2   0xC0---Vref-   0xD0---Vref+*/	
	val = 0;
    
	AD_CLK = 0;
	CS_AD = 0;	
    delay(10);    

	for (i = 0; i < 12; i ++) {
        if (chn & 0x80) AD_IN = 1;
		else AD_IN = 0;
		chn <<= 1;
		delay(10);	
		AD_CLK = 1; 
        val = val << 1;
		if (AD_OUT) val ++;			
		delay(10);
		AD_CLK = 0;		
	}		
	
	delay(10);
	CS_AD = 1;
	return val;	
}

unsigned char GetCANAddr() {
    unsigned char tmp_addr;
    m_pByte = SLOT_ADDR;
    tmp_addr = *m_pByte;
    tmp_addr = tmp_addr & 0x0F;
    tmp_addr = tmp_addr - SLOT_ADDR_COM;
    tmp_addr = tmp_addr*4; 

	return tmp_addr;
}

// ...transfer data by can net.
void UploadData()
{    
       m_CanSend[0] = m_addr;
	   m_CanSend[1] = 0x08;
	   m_CanSend[2] = CAN_FLAG_START;
	   m_CanSend[3] = m_ad_buff[0]; //chn0
	   m_CanSend[4] = m_ad_buff[1];
	   m_CanSend[5] = m_ad_buff[2]; //chn1
	   m_CanSend[6] = m_ad_buff[3];
	   m_CanSend[7] = m_ad_buff[4]; //chn2
	   m_CanSend[8] = m_ad_buff[5];
	   m_CanSend[9] = m_ad_buff[6]; //chn3
	   while(!SJA1000_Send());
	   
       m_CanSend[0] = m_addr;
	   m_CanSend[1] = 0x08;
	   m_CanSend[2] = CAN_FLAG_RUNNING;
	   m_CanSend[3] = m_ad_buff[7];
	   m_CanSend[4] = m_ad_buff[8];  //chn4
	   m_CanSend[5] = m_ad_buff[9];
	   m_CanSend[6] = m_ad_buff[10]; //chn5
	   m_CanSend[7] = m_ad_buff[11];
	   m_CanSend[8] = m_ad_buff[12]; //chn6
	   m_CanSend[9] = m_ad_buff[13];	  
	   while(!SJA1000_Send());	   
       
	   m_CanSend[0] = m_addr;
	   m_CanSend[1] = 0x08;
	   m_CanSend[2] = CAN_FLAG_RUNNING;
	   m_CanSend[3] = m_ad_buff[14]; //chn7//
	   m_CanSend[4] = m_ad_buff[15];
	   m_CanSend[5] = m_ad_buff[16]; //chn8//
	   m_CanSend[6] = m_ad_buff[17];
	   m_CanSend[7] = m_ad_buff[18]; //chn9//
	   m_CanSend[8] = m_ad_buff[19];
	   m_CanSend[9] = m_ad_buff[20]; //chn10//	   
	   while(!SJA1000_Send());
	   
       m_CanSend[0] = m_addr;
	   m_CanSend[1] = 0x04;
	   m_CanSend[2] = CAN_FLAG_END;;
	   m_CanSend[3] = m_ad_buff[21];
	   m_CanSend[4] = m_ad_buff[22];
	   m_CanSend[5] = m_ad_buff[23]; //sum	      
	   while(!SJA1000_Send());
}

//...Serial Transfer Protocol....
void STProtocol()
{
     unsigned char fun; 
   	 unsigned int  timeout;
     bit bRet=1;

    fun = m_CanRecv[3];
	 
    if(m_buffull!=0x55) return;
    m_buffull=0;		 	 

    if (fun == 0x04 && m_can_msg_len == 4) 
    {// set timeout
	    timeout = m_CanRecv[5];
        timeout = timeout << 8;
        timeout = timeout + m_CanRecv[4];
        m_out_time = timeout;
		m_led_cond = m_CanRecv[6];
    }
    else if (fun == 0x06 && m_can_msg_len == 1) 
    {// reset	    
	    while(1) {;} //wait for watch dog
    }
    else if (fun == 0x07 && m_can_msg_len == 1) 
    {// pause the action of sending command on time
        m_bAuto = 0;
    }
    else if (fun == 0x08 && m_can_msg_len == 1) 
    {// start the action of sending command on time		 
        m_bAuto = 1;
    }
    else 
    {
	bRet = 0;
    }

    if (bRet) 
    {	  
        m_CanSend[0] = m_addr;
	    m_CanSend[1] = 0x03;
        m_CanSend[2] = CAN_FLAG_END;
	    m_CanSend[3] = fun;
	    m_CanSend[4] = 0;
	    while(!SJA1000_Send());
    }
}

void main(void)
{    
    unsigned char i;
    unsigned int value;

    EA = 0;

    m_addr = GetCANAddr();
    P89C58_init();
    SJA1000_init();
    TLC2543C_init();

    m_out_time = 200;
    m_can_recvs = 0;    
    m_can_msg_len=0;
    m_led_cond = 0x00;       //电流环断线时指示灯灭	
    m_bAuto = 0;
    EA = 1;

    while(1) 
    {
        kickdog;//Feed watch_dog 
	          
        STProtocol();	   
 	    m_times ++;
    	if(m_times > 4) m_times = 0; 	   
    	for(i=0;i<11;i++)                        //get ad value,about 22mS
	    {
	        if(i==10)  m_ad_tmp[m_times][i] = TLC2543C_ad(0);        
            else m_ad_tmp[m_times][i] = TLC2543C_ad(i+1);
    	} 
	   
 	    TLC2543C_filter();										//do with ad data
        LightLed();                              //make led on behalf of the abnormal ad value     
  	   
        if (!m_bAuto) continue;              //Don't upload data	
   	    if (m_last_time < m_out_time) continue;  //Don't upload data,because time is too short
	    m_last_time = 0;	 

	    m_addr = GetCANAddr();
    	value = GetCRC(22, m_ad_buff);          //calculate crc
    	m_ad_buff[22]=value;
     	m_ad_buff[23]=value>>8;   
  	    UploadData();                           //upload ad data
    }
}// end main

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -