proteldxp 发表于 2014-3-6 20:31:11

求救M128与sja1000的自收发程序问题

#include <mega128.h>
#define uchar unsigned char
#define uint unsigned int
#define clk   16000000
#definesja_baseaddr 0x4000
#defineMODE       0x00
#defineCMR       0x01
#defineSR      0x02
#defineIR      0x03
#defineIER       0x04
#defineBTR0      0x06
#defineBTR1      0x07
#defineOCR       0x08
#defineRXERR   0x0E      //接收错误计数器
#defineTXERR   0x0F      //发送错误计数器
#defineACR0      0x10
#defineACR1      0x11
#defineACR2      0x12
#defineACR3      0x13
#defineAMR0      0x14
#defineAMR1      0x15
#defineAMR2      0x16
#defineAMR3      0x17
#defineRMC       0x1D          //RX报文计数器
#defineRBSA      0x1E          //接收缓冲区起始地址
#defineCDR       0x1F
//发送缓冲器      
#define TXbuffer0   0x10
#define TXbuffer1   0x11
#define TXbuffer2   0x12
#define TXbuffer3   0x13
#define TXbuffer4   0x14
#define TXbuffer5   0x15
#define TXbuffer6   0x16
#define TXbuffer7   0x17
#define TXbuffer8   0x18
#define TXbuffer9   0x19
#define TXbuffer10    0x1A
#define TXbuffer11    0x1B
#define TXbuffer12    0x1C
   
// 接收缓冲器                                                                                                               
#define Rxbuffer0      0x10                                                                                                      
#define Rxbuffer1      0x11
#define Rxbuffer2      0x12
#define Rxbuffer3      0x13
#define Rxbuffer4      0x14
#define Rxbuffer5      0x15
#define Rxbuffer6      0x16
#define Rxbuffer7      0x17
#define Rxbuffer8      0x18
#define Rxbuffer9      0x19
#define Rxbuffer10       0x1A
#define Rxbuffer11       0x1B               
#define Rxbuffer12       0x1C
void uart_send(uchar data);
uchar *sja_address;
uchar read_sja( uchar addr)                //读SJA1000状态寄存器子程序
{
        sja_address=(uchar *)sja_baseaddr;
        sja_address=sja_address+addr;
        return (*sja_address);                  
}

void write_sja(uchar addr,uchar val)            //写SJA1000寄存器子程序
{   
      
       sja_address=(uchar *)sja_baseaddr;
       sja_address=sja_address+addr;
       *sja_address=val;
}
                                 
                                                   
void delay(uint x)
{
   uint i,j;
   for(i=x;i>0;i--)
   {
   for (j=1000;j>0;j--);
   }
}   
   
   voidcan_read()
   {
   uchar a;
   int i;
       a=read_sja(Rxbuffer0);
       a=read_sja(Rxbuffer1);
       a=read_sja(Rxbuffer2);
       a=read_sja(Rxbuffer3);
       a=read_sja(Rxbuffer4);
       a=read_sja(Rxbuffer5);
       a=read_sja(Rxbuffer6);
       a=read_sja(Rxbuffer7);
       a=read_sja(Rxbuffer8);
       a=read_sja(Rxbuffer9);
       a=read_sja(Rxbuffer10);
       a=read_sja(Rxbuffer11);
       a=read_sja(Rxbuffer12);
       write_sja(CMR,0X04);            //release RXbuffer   
      
      for(i=0;i<13;i++)
      {
         uart_send(a);
      }
    }   

/*interrupt void ex0()
{   
   if(IR&0x01==0x01)      //产生了接收中断
    can_read();
}    */

void uart_send(uchar data)
{
while (!UCSR0A.5 );   //判断发送缓冲器是否准备好接收新数据                                                
UDR0 = data;            //发送数据      
}      

void mcu_init()
{
UBRR0H=((clk/16/9600)-1)/256;            //波特率设置                              
UBRR0L=((clk/16/9600)-1)%256;
UCSR0B=0x18;         //接收和发送使能
UCSR0C=0x06;         //数据帧位数   
MCUCR=0x80;          //允许外部并行扩展接口
SREG=0x00;         //关总中断
EIMSK=0x01;       //外部中断0使能
EICRA=0x02;          //INT0下降沿产生中断请求

}      
                     
/*
***** **************************************
函数功能:初始化sja1000
内容:复位、波特率设置、开放中断等等
*******************************************
*/
                                          
void sja1000_init()
{
   write_sja(MODE,0x01);                //进入复位模式
   while(!(read_sja(MODE)&0x01))        //检测SJA1000是否达到复位模式
        {
           write_sja(MODE,0x01);                //进入复位模式
        }   
        delay(500);
   write_sja(CMR,0x12);               //自收自发
   write_sja(MODE,0x08);                //单滤波器
   write_sja(IER,0x01);               // 接收中断使能
   write_sja(RBSA,0x00);                        //缓存器起始地址寄存器设置为0
   write_sja(RXERR,0x00);                       
   write_sja(TXERR,0x00);
   write_sja(IR,0x00);
   write_sja(ACR0,0x00);                 //acceptcode buffer
   write_sja(ACR1,0x00);
   write_sja(ACR2,0x00);
   write_sja(ACR3,0x00);         
   write_sja(AMR0,0xff);                //验收屏蔽寄存器,接收任何标识符的数据包
   write_sja(AMR1,0xff);
   write_sja(AMR2,0xff);
   write_sja(AMR3,0xff);                                             
   write_sja(BTR0,0x00);             //设置1M的波特率通信
   write_sja(BTR1,0x14);
   write_sja(OCR,0x1a);            //配置输出管脚,TX1 悬空,TX0推挽输出
   write_sja(CDR,0xc8);            // 关闭时钟,工作于pelican模式
   write_sja(MODE,0x00);             //进入工作模式
}   
      
void CAN_Tx()
{
    uchar state;
state=read_sja(SR);

while(!(state & 0x04));            //检查发送缓冲器是否被锁定

write_sja(TXbuffer0,0x88);               //扩展帧,数据帧,长度为8字节   

write_sja(TXbuffer1,0x22);                  //节点IP
write_sja(TXbuffer2,0x00);         
write_sja(TXbuffer3,0x0F);
write_sja(TXbuffer4,0x30);
                                                            
write_sja(TXbuffer5,0x05);               
write_sja(TXbuffer6,0x06);
write_sja(TXbuffer7,0x06);
write_sja(TXbuffer8,0x07);                        
write_sja(TXbuffer9,0x07);                  
write_sja(TXbuffer10,0x08);
write_sja(TXbuffer11,0x0b);
write_sja(TXbuffer12,0x0c);         
write_sja(CMR,0x01);                  //启动发送   
   
   while(read_sja(SR)&0x08) ;         // 检测发送是否完成   
   SREG=0x80;         //开总中断
         
}                                       

/*
****************************
函数说明:主函数
****************************
*/
voidmain()
{   
   mcu_init();
   sja1000_init();
   DDRC=0xff;      
   PORTC=0x40;      //choose the sja1000   
   
   while(1)
   {CAN_Tx();
      
can_read();
      }

   
                     
                                                                                                                           
}         
大家帮帮忙 我的自收发程序 总是搞不通哪里有问题谢了                     

banalsheep 发表于 2015-2-1 12:36:40


最近也在调SJA1000,我的硬件应该没问题(见下面的测试过程),不知道哪里出了问题

你搞定了吗?搞定的话能不能发个demo啊

测试过程:
1、在正常模式下(地址0寄存器写入0)读写测试寄存器(地址0x09)正常;写入55读回55,写入aa读回aa;
2、在上述写完测试寄存器后立刻切入测试模式(地址0寄存器写入1)写时钟分频寄存器(地址0x1f),连续写C8/C4/C0(关闭clockout、clock=Fosc/2、clock=Fosc/10),用仿真器单步跟踪可以看到clockout频率分别为0(无输出)、8MHz、1.6MHz(注:Fosc=16MHz)。
从上述两点应该看可否得出结论:1、MCU和SJA1000硬件连接正常;2、SJA1000正常工作;

现在的我调试时发现:初始化(PeriCAN模式,初始化代码不能确定是否正确)完毕后(实际上是写完时钟分频寄存器后)状态寄存器(偏址0x02)是0X3C,也即收、发状态都是1(忙),无法进一步操作

以上测试已经断开TJA1050与SJA1000的TX/RX。)。

#include <REG52.H>                /* special function register declarations   */
                                  /* for the intended 8051 derivative         */

#include <stdio.h>                /* prototype declarations for I/O functions */
#include <absacc.h>                                  /* 主要是用于寻址外部存储器*/
#include "sja1000_reg.h"                  /* sja1000T的寄存器定义文件*/
#include "sja1000.h"

sbit SJARst = P1^0; //复位控制                                    

#define XtalFreq        (12000000)                /* main crystal frequency        */
#define CntrFreq        (XtalFreq/12)   /* main counter frequency        */
#define BaudRate        (4800)                        /* baud rate        */

#define UARTOPEN


void main (void)
{

        unsigned char tmp;

#ifdef UARTOPEN
        SCON        = 0x50;        /* SCON: mode 1, 8-bit UART, enable rcvr */
        TMOD        = 0x21;       
        /* TMOD: timer 1, mode 2, 8-bit reload*/
        /* TMOD: timer 0, mode 1, 16-bit        */

        PCON |= 0x80;   /* SMOD = 1 Double Baud Rate for TH1 load */
        TH0=TL0 = 0;
//        TH1=TL1 = (unsigned int)(256 - ( (XtalFreq / BaudRate) / 192));
        TH1=TL1 = (unsigned int)(256 - ( XtalFreq/ BaudRate / ((PCON&0x80)?1:2) ) / 192) ;
       
        TR1        = 1;        /* TR1:timer 1 run        */
       
        TI        = 1;        /* TI:   set TI to send first char of UART*/
//    SCON= 0x50;                        /* SCON: mode 1, 8-bit UART, enable rcvr      */
//    TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload      */
//    TH1   = 0xFD;                /* TH1:reload value for 9600 baud @ 11.0595MHZ   */
//    TR1   = 1;                  /* TR1:timer 1 run                        */
//    TI    = 1;                  /* TI:   set TI to send first char of UART    */
#endif
        PX0=1;                                          //外部中断0高优先级
        IT0=1;                                          //设置INT0为下降沿中断
        IE0=0;/* 清中断标志 */
        EX0=1;                                          //使能INT0中断
/*------------------------------------------------
Note that an embedded program never exits (because
there is no operating system to return to).It
must loop and execute forever.
------------------------------------------------*/

   
    printf ("Hello World\n");   /* Print "Hello World" */
        SJA_Init();//主要是使芯片复位
        tmp = SJA_Test();
       
        /* Enter the reset Mode        */
        REG_MODE = 0x01;
        while((REG_MODE&0x01)!= 0x01);        //确定进入复位模式
        printf("1.Enter the Reset Mode,REG_MODE=0x%.4x\n",REG_MODE);

        REG_CDR = 0xc0;//设置时钟分频寄存器。CDR.7 = 1,PeliCAN模式;CDR.6(RX0激活,关闭RX1)fCLKOUT = fOSC/2, CDR.3(CLKOUT ON)
        REG_CDR = 0xc4;//设置时钟分频寄存器。CDR.7 = 1,PeliCAN模式;CDR.6(RX0激活,关闭RX1)fCLKOUT = fOSC/10, CDR.3(CLKOUT ON)
        REG_CDR = 0xc8;//设置时钟分频寄存器。CDR.7 = 1,PeliCAN模式;CDR.6(RX0激活,关闭RX1)fCLKOUT = fOSC/2, CDR.3(CLKOUT off)
        REG_RBSA = 0x00;//RX缓冲器起始地址   
                  
        /*Configure acceptance code and mask register*/                                                            
        REG_ACR0 = 0xff;//验收码寄存器                     
    REG_ACR1 = 0xff;                           
        REG_ACR2 = 0xff;                           
        REG_ACR3 = 0xff;                           
                                                            
        REG_AMR0 = 0xff;//验收屏蔽寄存器,接收任何标识符的数据包         
        REG_AMR1 = 0xff;                           
        REG_AMR2 = 0xff;                           
        REG_AMR3 = 0xff;   
                               

        /*configure bus timing registers*/
        REG_BTR0 = 0x49;//0x00;                           
        REG_BTR1 = 0x14;//0x14; //100k@12MHz
                                           
        REG_IR_ABLE = 0x01;//Peli模式中断使能,接收中断使能,发送中断禁止                  
        REG_IR_ABLE = 0xff;//Peli模式中断使能,接收中断使能,发送中断禁止                  
   
        REG_OCR = 0x1a;//设置输出模式:正常输出,从TX0口输出;TX1悬空
                                              
        REG_MODE = 0x0c; //进入自接收模式.CDR.3(选择单个验收滤波器),CDR.2 (此模式可以检测所有节点)

        do
        {
                tmp = REG_MODE;
        }while(tmp != 0x0c);//确定进入自接收模式下
        printf("2.Enter the self-test Mode\n",REG_MODE);

        printf("REG_SR=0x%.4x\n",REG_SR);
       
        SJA1000_TxData();//发送数据
        printf("\n\n");
        //SJA1000_Rx_Display();//接收数据展示
        EA = 1;//使能全局中断
        while(1);
}


void SJA1000_TxData(void)
{
        while(REG_SR & 0x10) /*printf("REG_SR=0x%.4x\n", REG_SR)*/;//当SJA1000不处于接收状态时才可继续执行,SR.4==0x1,正在接收,等待
    while(!(REG_SR & 0x08))printf("REG_SR=0x%.4x\n", REG_SR); //SR.3=0,发送请求未处理完,等待直到SR.3=1
    while(!(REG_SR & 0x04))printf("REG_SR=0x%.4x\n", REG_SR); //SR.2=0,发送缓冲器被锁。等待直到SR.2=1   
       
        REG_TxBuffer0 = 0x08;//帧信息,标准帧,数据帧,8字节      
                                                                   
        REG_TxBuffer1 = 0xFF;//标识符1                           
        REG_TxBuffer2 = 0xFF;//标识符2                     
                                                       
        REG_TxBuffer3 = 0x11;//发送数据位:1                     
        REG_TxBuffer4 = 0x22;//发送数据位:2                     
        REG_TxBuffer5 = 0x33;                                    
        REG_TxBuffer6 = 0x44;                                    
        REG_TxBuffer7 = 0x55;                                    
        REG_TxBuffer8 = 0x66;                                    
        REG_TxBuffer9 = 0x77;                                    
        REG_TxBuffer10 = 0x88;//here Over                        
                           
        SJA1000_Tx_Display();
        REG_CMD = 0x10;//自接收
        while(!(REG_SR & 0x08));//检测发送完毕       
}

void SJA1000_Tx_Display(void)
{
        printf( " TBSR3 = 0x%.4x \n", REG_TxBuffer3 );
        printf( " TBSR4 = 0x%.4x \n", REG_TxBuffer4 );
        printf( " TBSR5 = 0x%.4x \n", REG_TxBuffer5 );
        printf( " TBSR6 = 0x%.4x \n", REG_TxBuffer6 );
        printf( " TBSR7 = 0x%.4x \n", REG_TxBuffer7 );
        printf( " TBSR8 = 0x%.4x \n", REG_TxBuffer8 );
        printf( " TBSR9 = 0x%.4x \n", REG_TxBuffer9 );
        printf( " TBSR10 = 0x%.4x \n",REG_TxBuffer10);
}

void SJA_Init(void)                        
{   
        //SJA1000复位                                       
       unsigned char i;                           
       for(i = 0;i < 125;i++);         
       SJARst = 0;                                 
       for(i = 0;i < 125;i++);//给RST引脚一个低脉冲
       SJARst = 1;                                 
       for(i = 0;i < 125;i++);                     
}

unsigned char SJA_Test(void)
{
        unsigned char tmp;
        REG_MODE = 0;
        tmp = 0;
        tmp = REG_TEST;
        tmp = 255;
        do
        {
                REG_TEST = tmp;
                if(REG_TEST != tmp) return tmp;
        } while(tmp--);
        return 0;       
}

/************************************************************
                函数:ex0_int
                说明:中断服务程序
                入口:无
                返回:无

***********************************************************/
void handle_int(void) interrupt 0 using 1
{
        if(REG_IR & 0x01)      //产生了接收中断
{
       #pragma disable
       printf( " Received message.\n");
       printf( " RBSR3 = %x \n", REG_RxBuffer3 );
       printf( " RBSR4 = %x \n", REG_RxBuffer4 );
       printf( " RBSR5 = %x \n", REG_RxBuffer5 );   
       printf( " RBSR6 = %x \n", REG_RxBuffer6 );   
       printf( " RBSR7 = %x \n", REG_RxBuffer7 );   
       printf( " RBSR8 = %x \n", REG_RxBuffer8 );   
       printf( " RBSR9 = %x \n", REG_RxBuffer9 );   
       printf( " RBSR10 = %x \n",REG_RxBuffer10);   

}
}
页: [1]
查看完整版本: 求救M128与sja1000的自收发程序问题